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


25

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


AAMOIに具体的な例はありますか?
オコド

いいえ、現在はありません。同僚と話し合ったケースを思い出しただけです。ここでも意見を聞きたかった。
アイマンタス

5
通常、文脈から頭字語を理解することができますが、AAMOIは絶対に調べなければなりませんでした
カーソンマイヤーズ

@カーソン-あなたは何かを見つけましたか?
エイマンタス

4
関心事として
カーソンマイヤーズ

回答:


33

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


同意する。一部のメソッドは、内部と外部の呼び出し元の両方に役立つ機能を提供します。レッドメソッドは、パブリックメソッドが内部実装に非常に固有のものであったとしても、それでもすべてのクラスがその内部を隠すことを意図しているわけではありません。たとえば、コンテナの抽象型レイヤの下にデータ構造の「ツール」レイヤがあることがよくあります。そのようにして、他のコンテナの基礎となる他のデータ構造にデータ構造コードの一部を再利用できます。
Steve314

20

コードの匂い?はい、本当に悪いものではありませんが、クラスに多くの責任があるかもしれないという良い指標です。

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

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

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


5
「アラームの原因ではない」場合は+1。何度も「におい」が発生し、考えずに即座にリファクタリングモードに入ります。
マイケルK

SRPの場合は+1。装飾されたクラスがデコレータをバイパスして独自のパブリック関数を呼び出していたため、デコレータが機能していなかった場合に遭遇しました。解決策:クラスを2つに分割し、装飾された依存関係を注入します。
ジョンハルカ

18

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


どうして?上書きされたパブリックメソッドが不快な驚きにつながる場合、誰がメソッドを呼び出したかは本当に重要ですか?
user281377

4
はい、そうです。あるパブリックメソッドをオーバーライドすると、別のパブリックメソッドが壊れる場合、他のメソッドもオーバーライドできます。それがプライベートメソッドを壊した場合、私はできる....?
キム

5
パブリックメソッドをオーバーライドしたことによる不快な驚きは、それ自体がコードのにおいです。実際、コードの悪臭。
ラリーコールマン

キム:メソッドがパブリックの場合、他のクラスも同様にそのメソッドを呼び出すと仮定する必要があります
...-user281377

@ラリー:その通り!パブリックメソッドを呼び出すプライベートメソッド(通常は実装固有の仮定を含む)は、パブリックメソッドをオーバーライドすると問題が発生する可能性が高くなります。
キム

5

私たちは一般化できるとは思わない。

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

たとえば、他のクラスによって使用されるクラスのパブリックユーティリティメソッドと、同じクラスのプライベートメソッドがある場合があります。


5

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


または、他のプライベートメソッドによって呼び出される(新しい)プライベートメソッドにパブリックメソッドを委任します。しかし、なぜわざわざ?
ローレンスドル

4

いいえ、悪臭はありません。

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

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


2

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

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

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

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

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


1
既存のパブリックメソッドが他の多くのクラスから呼び出されるとどうなりますか?プライベートにすることはそれを壊します。パブリックメソッドは、このクラスだけでなく、他の理由で他のクラスによって呼び出されることに注意してください。なぜパブリックメソッドが存在するのか。
マイケルデュラント

「パブリックメソッドのコンテンツを取得してプライベートメソッドに配置する必要があります...」と述べましたが、パブリックメソッドは残りますが、新しいプライベートメソッドを呼び出します。同じ機能を再利用する必要がある他のプライベートメソッドも同様です。
マークグラハム

だから、あなたはこれを「コードの匂い」と宣言したので、他の理由で別のメソッドを追加しています。無意味なメソッドはコードの悪臭です。
gnasher729

申し訳ありませんが、上記の理由をいくつか挙げただけではありません。私が書いたコードの多くはビジネスシステム用であり、多くのクラスはロールに基づいてユーザーに制限されています。多くのパブリックメソッドは、ユーザーのアクセス許可とパラメーターをテストします。いったいなぜ同じパブリックメソッドにコールアウトしてその機能を再利用し、ユーザーのアクセス許可を再テストしたいのですか?
マークグラハム

プライベートメソッドからパブリックメソッドを呼び出す必要はありません。それは私には非常に間違っているように思えます。ほとんどの人が大丈夫だと思って本当に驚いています。
トラップ

2

反対を想像してください。プライベートメソッドにあり、パブリックメソッドの機能が必要な場合プライベートメソッドからパブリックメソッドを呼び出せなかった場合はどうなるでしょう。あなたならどうしますか?

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

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


1

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

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

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


1

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

(a)プライベートである必要がある何かを公開しました。または

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

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.