web-dev-qa-db-ja.com

プライベートメソッドがパブリックメソッドを呼び出すと、コードの匂いがしますか?

同じオブジェクトインスタンスのプライベートメソッドでパブリックメソッドを呼び出すのはコードの匂いですか?

25
Eimantas

悪臭はありません。これは必要かもしれませんが、なぜそれが間違っていると疑うのですか?アトミックレベルのメソッドは、タスクを実行する独立したエンティティです。タスクを実行する限り、それにアクセスできるすべてのユーザーがそれを呼び出してタスクを完了できます。

32
Geek

コードのにおい?はい、それほど悪いことではありませんが、クラスの責任が多すぎる可能性があることを示す良い指標です。

クラスをさまざまなオブジェクトに分割する必要があるかもしれないという兆候と考えてください。プライベートメソッドは、実際には同じオブジェクトのパブリックメソッドを呼び出す必要はないはずです。確かに、クリーンなOO設計です。

もちろん、クラスを検査し、メソッド呼び出しの理由が明らかであれば、それは完全に合理的な使用法である可能性があります。一般に、クラスのユーティリティメソッドはプライベートであると予想されますが、公開され、他の方法で利用される場合、一般的に、それらの方法も公開されることを期待します。

すべてのコードのにおいがそうであるように、これはさらなるコード検査、合理化、そしておそらくリファクタリングの動機ですが、警告の原因ではありません。

19
ocodo

このクラスのソースコードを読んでいない人がサブクラス化してpublicメソッドをオーバーライドすると、不愉快な驚きにつながる可能性があります。それが本当の懸念であるかどうかは、明らかにあなたの状況に依存します。たぶん、あなたはパブリックメソッドまたはクラスをさらにファイナルにすることを検討する必要があります。

18
Kim

私たちは一般化できるとは思いません。

それはすべてコンテキストに大きく依存します。

他のクラスが使用するクラスにパブリックユーティリティメソッドがあり、同じクラスにプライベートメソッドがあるかもしれません。

5
Nivas

いいえ。その場合、他に何をすべきですか?プライベートメソッドをパブリックにしますか、パブリックメソッドをプライベートにしますか?コードをパブリックメソッドからプライベートメソッドにコピーして貼り付けますか?

5
user281377

[〜#〜]いいえ[〜#〜]、ここには悪臭はありません。

リストを使用してキューのインターフェイスを実装する場合、キューの実装を簡単に実現するために適切なリスト関数を呼び出すだけでは悪臭ですか?

何かがあり、それを別のもの(ラッパーなど)に変換したい場合は、悪臭ではありません。デザインレベルのコードの再利用性は、関数レベルで機能します(関数はオブジェクトですか?)

4
Display Name

私はこれが古い記事であることを知っていますが、それは私が仕事で議論していたものです。私はこれをコードのにおいだと考えています。なぜこれをしたいのか理解できません。プライベートメソッドがパブリックメソッドを呼び出す必要がある場合は、パブリックメソッドのコンテンツを取得してプライベートメソッドに配置する必要があります。プライベートメソッドは、両方のメソッドから呼び出すことができます。どうして?

  1. Publicメソッドには、内部でコードを実行すると不要なテストが含まれる場合があります。たとえば、UserObjを受け取り、ユーザー権限をテストしたい場合があります。

  2. パブリックコールの後、スレッドを使用している場合、オブジェクトをロックする必要がある場合があるため、内部的にはパブリックメソッドをコールバックしたくないでしょう。

  3. 私の考えでは、循環エラーや無限ループ、メモリ不足の例外が発生する可能性が高くなります。

  4. プレーンで単純な、悪いデザインと「怠惰」。パブリックメソッドは、外部へのアクセスを提供します。あなたがすでに中にいるとき、外に戻る理由はありません。

2
Mark Graham

反対を想像してみてください。あなたはプライベートメソッドを使用していて、パブリックメソッドの機能が必要だとしたらできませんでしたプライベートメソッドからそのパブリックメソッドを呼び出します。あなたならどうしますか?

  • 重複するプライベートメソッドを作成しますか?番号
  • 機会のための特別なパブリックメソッドを作成しますか?番号
  • パブリックメソッドを呼び出すことができる特別なプライベートメソッドを呼び出しますか?番号
  • これを行うことができるある種のスーパー?番号

答えは明らかに、パブリックメソッドの機能が必要な場合、このクラスのメソッドまたは他のクラスからそのメソッドを呼び出すことができるはずです。

2
Michael Durrant

私のコードでは、レイジーロードゲッターを作成することがよくあります。つまり、オブジェクトは、最初に要求されたときに初期化され、その後、同じインスタンス化されたオブジェクトを再利用します。ただし、遅延ロードを使用してインスタンス化されたオブジェクトは、必ずしも特定の時点でインスタンス化されるとは限らないことを意味します。そのオブジェクトが既にインスタンス化されているか、別のメソッド内でレイジーロードの同じコードが繰り返されていることがわかるように、一連の呼び出しに頭を抱えるのではなく、そのオブジェクトが必要なときにレイジーローダーを呼び出すだけです。

パブリックメソッドをスマートに使用できるのと同じように、誤って使用することもできます。この例としては、別のプライベートメソッドを呼び出す前にパラメーターを処理するパブリックメソッドがあります。同じパラメーターを持っているからといって、単純にそのパブリックメソッドを呼び出すのは誤りです。間違いは微妙ですが、それは何よりも設計エラーであり、パブリックメソッドのパラメーターではなく、内部メソッドのパラメーターで管理することを学ぶ必要があります。

だからあなたの質問に答えるなら、あなたがそれを正しく使うなら、それは確かに悪いコードではありません。

1
Neil

あなたが自問する必要があるのは、なぜあなたのクラスはあなたのクラスのクライアントと同じニーズを持っているのですか?通常、クラスはクライアントとは非常に異なるニーズを持っています。はい、これはあなたがどちらかを持っていることを示しています

(a)プライベートであるべき何かを公に公開した;または

(b)クラスの動作が十分に狭くない(単一責任の原則を考えてください)。

1
Brad Thomas