14

アジャイル開発者に不可欠なスキル、ニーズと機能のインターフェース、第 12 章では、著者がこの章の終わりまでに言及している DEMETER の法則を適用するという課題に対して提案された主な解決策を理解しようとしています。

話を短くするために。

次のスタディ ケースから始めます。

public class City {
  public string name{};
  public City twinCity{};
  public Street[] streets{};
}
public class Street {
  public string name{};
  public House[] houses{};
}
public class House {
  public int number{};
  public Color color{};
}

都市グリッドのモデル

著者は次のように述べています。

このようなモデルは、カプセル化するのではなく、公開することを奨励します。コードに特定の City インスタンスへの参照が含まれている場合 (たとえば、シアトルをマップするインスタンス)、メイン ストリート 1374 番地の家の色が必要な場合は、次のようにします。

public Foo() {
  Color c = Seattle.streets()["Main"].
    houses()[1374].
    color();
}

これが一般的な慣行として行われる場合の問題は、システムがあらゆる場所で依存関係を開発し、このモデルの任意の部分を変更すると、これらの依存関係のチェーンの上下に影響を与える可能性があることです。ここで、「見知らぬ人と話すな」2 というデメテルの法則の出番です。これは、関数/メソッドのデメテルの法則としてオブジェクト システムで形式化されています。オブジェクト O のメソッド M は、次の種類のオブジェクトのメソッドのみを呼び出すことができます。

  1. オーズ
  2. M のパラメーター
  3. M 内でインスタンス化されたすべてのオブジェクト
  4. O の直接コンポーネント オブジェクト
  5. O によってアクセス可能なグローバル変数

そして、DEMTERの法則を適用するときは、次のようなものを目指すべきであることを提案します

public Foo() {
   Color c = Seattle.ColorOfHouseInStreet("Main",1374);
}

そして、次のことからすぐに警告します。

これは最初は賢明なポリシーのように見えますが、特定のエンティティのインターフェイスが文字通り関連するものすべてを提供することが期待できるため、すぐに手に負えなくなる可能性があります。これらのインターフェイスは時間の経過とともに肥大化する傾向があり、実際、特定のグラスが最終的にサポートする可能性のあるパブリック メソッドの数にはほとんど終わりがないように思われます。

次に、結合と依存関係の問題を説明する際の簡単な回り道の後、サービスのインターフェースによってクライアントとそのサービスを分離することの重要性に言及し、さらにクライアントを「サービス機能」から「インターフェースが必要」に分離することによって、彼は言及します。理想的であるが必ずしも実用的ではないものとしてアダプターを使用することによる「インターフェイス」。

理想的なデカップリング

彼は、問題を解決するために、以下に説明するファサード パターンを使用して、DEMETER の法則とニーズ/機能の分離を組み合わせることができると提案しています。

元の依存関係から

デメテルの法則違反

デメテルの法則とニーズ/機能の境界面の分離を適用すると、最初に次のことが得られます。

複雑すぎる

しかし、特にモッキングの観点からは非現実的であることを考えると、次のようにファサードを使用してより単純なものを作成できます。

LoD ニーズ/機能分離 モック

問題は、デメテルの法則に違反しないという問題を正確に解決する方法がわからないことです。元のクライアントと元のサービスの間の法律を維持していると思います。しかし、FACADE 内で違反を移動しただけです。

4

3 に答える 3

3

あなたの説明から、彼は CityMapFacade の形で Cirty/Street/House 機能の周りにブラックボックス コンポーネントを導入しただけだと思います。さらに、そのコンポーネントは、IClientNeeds というインターフェイスの形式で公開インターフェイスに準拠しています。この種のブラックボックスのカプセル化は、都市/通り/家の関係の複雑さが明らかにされないため、より大きなアプリケーションを保護し、テスト可能にします。かつて古いものが再び新しくなったようです :) この種のブラックボックス コンポーネント スタイルの方法論 (より適切な用語がないため) は、長い間存在しています。明確に定義されたインターフェイスを使用して、機能の再利用可能なカプセル化されたコンポーネントを作成することに重点を置いています。公開契約が履行されている限り、クライアントは実装を気にしません。コンポーネントは交換可能、アップグレード可能、モック可能です。コンポーネント内では、アプリケーションの分離されたサブセットのみを担当するため、複雑さも軽減されます。通常、完全に単体テスト可能であり、パブリック コントラクト/インターフェイスを正しく実装していることを確認します。私の意見では、著者は、説明を単純化するために、このすべてについてのより深い議論を隠蔽しています。

于 2014-07-16T12:20:41.713 に答える
3

あなたと作者の間に「誤解」があると思います。

ステップ1:あなたはこれを持っています:

インターフェイスが必要

この時点で LoD 違反がないことを確認していただければ幸いです。各具象クラスは、そのニーズの抽象化に依存しているため、その制限されたインターフェイスのみを呼び出します。さらに、 LoD で許可されているエンティティへの依存性 (例: Cityfor )。CityCapabilityAdapterというわけで、今のところ違反はありません。


ステップ 2 : 次に、これがあります。

ファサードが必要

ここでの著者は、概念的CityMapFacadeには3 つのエンティティすべてに依存しているが、物理的にはそれらと直接連携しないことを意味していると思います。代わりに、LoD インスツルメントを介してそれらと連携します。たとえば、ファサードは、以前に導入されたアダプターに依存する可能性があります。ここでも、LoD 違反はありません。

この解釈をさらに明確にするために、図の抽象的な部分に注意してください。それらは斜体で示されています(UML 2.0)。したがって、CityMapFacadeは独自の LoD 問題を解決する役割を担うインターフェースです。そして、それらは、すでに実証された事実 (アダプターなど) を使用して解決できます。具体的な解決策は図には示されていません。抽象化について話しているだけです。また、ファサードの具体的な実装における LoD 違反について議論する機会はありません。なぜなら、著者はアダプターを導入することで違反を回避するための手段を持っていることを既に示しているからです。

于 2014-07-24T02:52:59.477 に答える