一般化よりも構成を優先することをどうやって知ることが常に正しい選択でしょうか?


9

オブジェクトが物理的に存在するかどうかに関係なく、さまざまな方法でモデリングすることができます。多くの場合、一般化または合成を任意に使用できます。ただし、「一般化よりも構成を優先する」というGoFの原則により、構成を使用するようにガイドされます。したがって、たとえばラインをモデル化する場合、Point(一般化)を拡張する代わりに、タイプPoint(構成)の2つのメンバーPointAおよびPointBを含むクラスを作成します。これは、オブジェクトが通常ははるかに複雑であるにもかかわらず、モデル化するための構成または継承を任意に選択できる方法の単純化された例にすぎません。

これが正しい選択であることをどのように知ることができますか?少なくとも、それが間違っている場合に実行すべき大量のリファクタリングが存在する可能性があるため、問題になりますか?


9
あなたの例は、線点であると言えないので実際には機能せず、したがって、リスコフの置換原理に失敗し、継承は適切ではありません。
ディーンハーディング

@Dean:ご存知のように、この例は中心的なものではありません。レコードの場合、線は2点で定義される方程式として表すことができます。
CarneyCode、2011


1
@Songo:ポイントを完全に逃したようです。
CarneyCode

一般化の代わりに特殊化を拡張していませんか?
TulainsCórdova2012

回答:


17

常に正しい選択とは限りません。ほとんどの場合、それは好ましいものです。複合モデルが変更または拡張を必要とする場合、他のクラスに不注意に影響を与えることを恐れずに構成を変更できるため、それに対する耐性が大幅に高まります。

どうやってこれを知るのですか?経験から、そして他人の経験から。

単純な概念として始まったものから大規模なクラス階層が成長する多くの状況を見てきましたが、ここであなたの主要なリファクタリングが必要になります。その間、私は合成構造が継承へのリファクタリングを必要とする状況を見たことがありません。

しかし、私の事例証拠は十分ではありません。インターネットを見回すだけで、かなりの数の人が同じ経験をしました。


私はそれが好きです。賛成票を投じます。
CarneyCode、2011

+1「構成構造が継承へのリファクタリングを必要とする状況を見たことがありません。」
Kazark

7

「継承よりも構成を優先する」よりも強力な経験則が必要な場合は、次のようなものをお勧めします。

オブジェクトを特殊化する2つの方法(継承と構成)のうち、継承を使用するのは、特殊化している基本クラスに対してオブジェクトを多態性(置換可能)にする必要がある場合のみにしてください。

ただし、すべての経験則と同様に、いったんルールを理解したら、自由にルールを破ることができます:)


0

構成と一般化がどのように選択肢であり、引用を見つけることができなかったのかわかりません
構成と継承は(特殊化を実現するため)であり、抽象化と一般化は(モジュール化を実現するため)であると主張できます。

必要なのは、設計を単純でもっともらしいものにすることです。これは、本質的に非常に簡単に測定できる2つの品質です。
あなたの場合、点の概念を拡張するのではなく、自然に線を2点で定義するので、それを拡張するのではなく、2点の線を構成するほうがもっともらしく思えます。


もっと自然ですか?直線は、1つの点が延長された場合よりも2つの点にすぎませんか
CarneyCode、2011

2
2点以上で構成されているという事実を含まない線の定義を見たことがありません。数値のドメインに1 x値しかない場合、線の方程式を使用しても、それは点ではなく線です。
Rig

0

両方の候補者が適格である場合に有利になります。質問に述べられている問題は、構成オプションしかないため、このアカウントでは失敗します。

「組成も汎化を使用できます」。このステートメントは私たちにとって意味がありますか?そうでない場合、「有利な」ルールを把握する準備がまだできていません。

コンポジションを支持する理由は、コンポジションが一般化よりも拡張/柔軟性の可能性を提供することです。この拡張/柔軟性は、主にランタイム/動的柔軟性を指します(これは、インターフェースと構成の組み合わせで実現されます)。

メリットはすぐにはわかりません。メリットを確認するには、次の予期しない変更リクエストを待つ必要があります。そのため、ほとんどの場合、一般化に固執した人は、構成を採用した人と比較すると失敗します(後述する明らかな1つのケースを除く)。したがって、ルール。学習の観点から、依存性注入を正常に実装できる場合は、どちらをいつ使用するかを知る必要があります。このルールは、どちらを選択すればよいかわからない場合に決定を下すのに役立ちます。繰り返しますが、どちらか一方を優先するために、最初に両方のオプションを確認できます。

概要:構成:小さなものを大きなものに接続するだけで結合が減少し、大きなオブジェクトは小さなオブジェクトをコールバックするだけです。ジェネラライゼーション:メソッドをオーバーライドできることを定義するサードパーティAPIの観点からは、メソッドを呼び出すことができると定義するよりも強い責任があります(一般化には確実に有利です)。また、構成では、大きなクラスの代わりにインターフェースから一般化も使用していることを忘れないでください。しかし、すべてのクレジットは、残念ながら作曲に使用されます。


-4

今日私は約300 LoCを書きました。そして、私は違反することができ、違反しなかったという原則を思い出すことができません。リファクタリングは私の魂を救ってくれると思います。

抽象化がサードパーティのAPIによって指示されている場合-通常は継承を使用するのが適切です。国内のデザインでは、エンティティは抽象的であるか、封印されている必要があります。抽象エンティティには、潜在的に約3つの継承が必要です。one-virtual-method拡張ポイントは好きではありません。上記はすべて私の好みについてです。私は、完全に異なる物語であるインターフェースの抽象化について話しているのではありません。

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