OOPの原則とメソッド名


22
class Boxer:

    def punch(self, punching_bag, strength):
        punching_bag.punch(strength)


class PunchingBag:

    def punch(self, strength):
        print "Punching bag punched with strength", strength

boxer = Boxer()
punching_bag = PunchingBag()

boxer.punch(punching_bag, 2)

punchボクサーの場合、それが良いメソッド名であることは間違いありません。しかし、名前punchはパンチングバッグの方法にも適していますか?どちらの場合も、コマンドとしてのパンチ(つまり、パンチ)を意味します。

回答:


23

経験則として、メソッド名は動詞または述語である必要があります。そのため、メソッド名(self標準的なPythonの慣習でthisは、他のほとんどの言語)が呼び出すオブジェクトが主題になります。

この規則によりfile.close、ファイルが閉じられる、またはfileオブジェクトがファイル自体を表すのではなく、ファイルハンドルまたは何らかのプロキシオブジェクトを表すというメンタルモデルを使用しない限り、一種の誤りです。

しかし、パンチングバッグはそれ自体を決してパンチしないので、punchingBag.punch()どちらの方法も間違っています。be_punched()技術的には正しいが、見苦しい。receive_punch()動作する可能性があります、またはhandle_punch()。JavaScriptで非常に人気の別のアプローチは、イベントなどのメソッド呼び出しを処理することで、大会は「オン」で始まるイベント名、で行くことがあるので、それは可能でしょうon_punched()on_hit()。あるいは、過去分詞が受動態を示す規則を採用することもできます。その規則では、メソッド名はになりますpunched()

考慮すべきもう1つの側面は、パンチングバッグが実際にそれを打ったものを知っているかどうかです。もしそうなら、違いは何ですか?違いを議論に要約することはできますか、それとも受けた罰の種類ごとに異なる方法が必要ですか?一般的なパラメーターを持つ単一のメソッドは、次のカップリングを低く保つため、おそらく最もエレガントなソリューションです。そのようなメソッドは、punched()またはhandle_punch()ではなく、のようなより一般的なものを呼び出す必要がありますreceive_hit()。このような方法を使用すると、パンチングバッグ自体を変更せずに、パンチングバッグにヒットするあらゆる種類のアクターを実装できます。


4
@Artur:はい、いいえ。ファイルは、(概念的に言えば)要求されたときに閉じられます。配列はそれ自体をソートできます。しかし、パンチングバッグはそれ自体をパンチしません。
ダンマー

2
さて、パンチングバッグが非常に速い速度で壁にぶつかった場合、それがパンチングバッグに当たったのでしょうか、それともパンチングバッグがそれ自体で実際にヒットしたのでしょうか?

1
@tdammers:一般化する提案は、と呼ばれるインターフェースにもつながる可能性がありますHitable
イェンスピエグサ

2
@Artur:これは、すべての文には自然な主題があり、この考えはプログラミングに適用できるというOOPの仮定が崩れる場所だと思います。
ダンマー

1
だから、主な質問は。ファイルが自分自身を閉じることができる場合、配列が自分自身を並べ替えることができる場合など、パンチバッグが自分自身をパンチできないのはなぜですか?実際の違いはありますか、それとも最初のケースでは慣れていますが、2番目のケースではそうではありませんか?
クライム

6

それは概念的な問題だと思います(世界についてどう考えるか)。次のように言っても大丈夫です:

  • 見て、ドアが閉まっている。 door.close()
  • うわー、紙はそれ自体で折り畳まれています。 paper.fold()
  • なんてこったい?!机の上のファイルは閉じたばかりで、誰もいません。 file.close()

言うのは奇妙です:

  • ジムにあるパンチングバッグは、パンチングしたばかりです。 bag.punch()

そもそも自分自身をパンチするもの(たとえば、腕)が必要です。あなたはおそらく言うでしょう:

  • パンチングバッグは、誰かがそれをパンチしたように、自力で動き始めました。 punching_bag.move()

プログラムオブジェクトは、通常は他の人が(「現実の世界」で)やり取りすることを実行できます。しかし、私はそれが常に/それ自体でそれをしているということを少なくともある程度理解すべきだと思います。(の場合のようにpunching_bag)あいまいになることなく簡単に想像できるはずです。


2

それは好みの問題だと思います。Punching bagpunch()方法は、少なくともそれ自体でアクションを経験するという意味で一貫しているfile.close()frame.move()、それを意味します。より大きな質問は、なぜメソッドをBoxer持っているのpunch(something)でしょうか?


file.close()についてのあなたの主張が好きです。それは私が得ていたものでした。ボクサーを訓練するコーチもいるので、ボクサーにはパンチ法があるかもしれません。実際、私はいくつかのオブジェクトを通過するアクション(メッセージ)の例を挙げようとしましたが、最後のオブジェクトは「アクションのオブジェクト」です。list.append(4)、account.deposit(50)、file.close()、paper.fold()vs. boxer.punch()、dog.bark()、logger.log()などにわずかな問題があります。
clime

複数のオブジェクトを通過するとき、バインドされたコンテキスト(自己)を使用する場合と使用しない場合の2つの場合があります。行う場合、メソッドはCoach.sayPunchToBoxer()Boxer.punchNearestBag()およびである必要がありBag.punch()ます。それ以外の場合は、電話するたびに何が起こるかを推測する必要がありますCoach.punch()。一般的なルールは、アクションが発生するオブジェクトがメソッド名で指定されていない場合、レシーバーはそのオブジェクトです。

まあ、これも大丈夫だと思います:coach.say_punch(boxer、punching_bag)、boxer.punch(punching_bag)。すなわち、レシーバはメソッド名ではなくパラメータにあります。
クライム

1
確かに、アクションレシーバーはcallステートメントから推測できるはずです。

2

2つの異なるメッセージがあります。1つはオブジェクトにパンチするように命令するメッセージ、もう1つはオブジェクトにパンチされたことを通知するメッセージです。ボクサーオブジェクトは両方に応答する必要がありそうだと考えてください。異なる。それは彼らに別の名前を付ける本当に良い理由です。

私の傾向はpunch(boxer, object, strength)、反対の方法を維持し、名前を変更することpunchedです。呼び出すこともできますがhandle_punch、パンチコマンドを処理するか、パンチされたという通知を処理するかは、まだあいまいです。


パンチとhandle_punchのようなものの両方を必要とするボクサーについての良い点(defendこの特定の場合になります)。しかし、パンチングバッグがそのような双方向になることはありません。そして...すでにこのfile.close()がある
clime

defendコマンドです。オブジェクトがに応答して実行できるアクションの1つpunchedですが、他のオブジェクトがdefend直接呼び出すことは望ましくありません。
user2313838

2

あなたのアプローチは最終的には非常に結合されたコードにつながります。

ここでエリック・リッパートを理想的に要約すると、ボクサーが非常に多くのものをパンチできるようにしたいと思うでしょう。ボクサー関数のシグネチャとしてパンチングバッグを持つことは、ボクサーがAll(パンチ可能)を即座に認識して作成されることを意味します。さらに、パンチを与えることとパンチを受け取ることは、まったく異なる2つのことなので、同じ名前を共有すべきではありません。

私はこれを、パンチ(パンチの属性の力、リーチ、方向などを含む別のオブジェクト)を作成するボクサーとしてモデル化します。

次に、このパンチオブジェクトを受け取るonPu​​nchなどのメソッドを使用してパンチングバッグを使用し、パンチ自体の効果を計算できます。

これを念頭に置いて、物事の名前は非常に重要です。それはあなたがその状況について持っているメンタルモデルに適合しなければなりません。一見すると意味をなさない、どういうことが起こるのかを説明しようとしている場合や、名前付けに苦労している場合は、モデルが間違っていて変更する必要があるかもしれません。

始めてからモデルを変更することは難しく、一般的に人々はモデルに合うように現実を曲げる傾向があります。これに伴う問題は、物を曲げて(物をパンチできるパンチングバッグなど)作成する世界がますます複雑になり、インタラクションの実装がますます難しくなることです。最終的には、最も些細なことを追加するだけでも、変更やバグの悪夢になります。この概念的な技術的負債は、その時点で初期費用が最も安価なものと認識されていたとしても、非常に急な価格になる可能性があります。


1

これは、私が「オブジェクト/サブジェクト」混乱と呼ぶ問題であり、非常に一般的です。

文章は、一般的に持っている主題ない動詞をそのターゲットにオブジェクトを

プログラミングに関して、実際に物事を行うのはコンピューターだけです。または、実質的にプロセス、糸、または繊維。オブジェクトはデフォルトではアニメーション化されません。独自のスレッドを実行していないため、実際には何もできません。

これは、メソッドがメソッドを操作することを意味し、メソッドを実行するのではなく、アクションのターゲットになります。それが、それらを「対象」ではなく「オブジェクト」と呼ぶ理由です!

File.closeファイル自体を閉じるのではないと言うとき、ファイルを閉じるのは現在実行中のスレッドです。と言うArray.sortと、現在実行中のスレッドが配列をソートします。と言うHttpServer.sendRequestと、現在実行中のスレッドがサーバーにリクエストを送信します(その逆ではありません!)。同様にPunchingBag.punch、現在実行中のスレッドがバッグをパンチすることを意味します。

つまり、BoxerをパンチThreadできるようにするには、スレッド関数でバッグをパンチするようなことをできるように、サブクラスにする必要があります。

ただし、各オブジェクトに独自のスレッドがある場合、パンチングバッグ自体をパンチすると言うのも理にかなっていpunchますその後、punch successfulメッセージ自体が返信されますが、これは実装の詳細にすぎません。


0

「パンチ」はBoxerクラスの優れたメソッド名であることに同意します。他のオブジェクトに対して(多少の調整を加えて)再利用できるためです。また、クラスのオブジェクトが別のオブジェクトに対してアクションを実行していることを正確に説明します。ただし、この関係をより明確に示すために、メソッドの名前を「doPunch」に変更します。

しかし、PunchingBagクラスの場合、メソッド名は曖昧すぎるか、メソッドで何が起こっているのか少し不正確であることがわかります。「パンチ」を見ると、何かが他の何かをパンチしていると思います。ただし、ここでは、PunchingBagオブジェクトはオブジェクト(この場合はBoxerオブジェクト)からのパンチに反応しています。そのため、ここではメソッドの名前を「isPunched」に変更して、オブジェクトがパンチに反応していることを示します。

ただし、これはメソッドの命名方法の解釈です。それはすべて好みの問題であり、あなたが従っている標準です。


3
isPunched本当に誤解を招く(フレームワークの命名スキームに応じて多かれ少なかれ)。

メソッドが呼び出されるオブジェクトに適用されるのが普通です。ちょうど何が問題なのpunch()ですか?

まあ、私は行動の方向を指定する必要があることを完全に理解していますが、OOPとその哲学にはこれを不要にするものがあると思います。オブジェクトが互いに「メッセージを送信する」という有名な説明に関連するある種の抽象化。
クライム

メソッドが何をしているかがメソッド名から明らかでない場合は、名前に問題があります。オブジェクト指向や使用されているパラダイムの問題ではありません。それが、あなたがそれを使いたいどんな文脈でも、パンチングバッグのpunch()が間違っている理由です。パンチングバッグにパンチするとはどういう意味ですか?また、仮定があいまいさを生む状況で何かが不必要であるという哲学によって仮定できない理由でもあります。経験則が機能する場合と機能しない場合があります。経験則が常に機能する場合、それらは規則と呼ばれます(「経験則」なし)。
ダンク

-2

うーん。あなたは本当にパンチングバッグを気にしないので、クラスとしてパンチングバッグに疑問を抱いています-あなたはボクサー拳の衝撃と強さを気にします。そのため、これらの方法は、パンチの影響を測定および報告するものについてのものである必要があります。これが「パンチングバッグ」から来ている場合でも、名前付けはまだ責任を明らかにする必要があります-punchImpactMeterなど。


-3

ボクサーはパンチングバッグをパンチ-> boxer.punch

パンチバッグはボクサーによってパンチされます-> punchingbag.get_punch


3
これは作られたポイントを超える大幅な提供の何にも思えるし、前6つの回答で説明していません
ブヨ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.