1

私のアプリケーションには、このようなコードがいくつかあります。それはいくつかの XML を書き出します:-

public void doStuff( Business b, XMLElement x)
{
   Foo f = b.getFoo();
   // Code doing stuff with f
   // b is not mentioned again.
}

私が理解しているように、ディメンターの法則はこれが悪いと言っているでしょう. 「Code Complete」は、これがカップリングを増やしていると言います。このメソッドは、最初に "f" を取る必要があります。

public void doStuff( Foo f, XMLElement x)
{
    // Code doing stuff with f
}

しかし、今はこのコードを変更する必要があり、実際には の別のメソッドにアクセスする必要がありますb

public void doStuff( Business b, XMLElement x)
{
   Foo f = b.getFoo();
   // Code doing stuff with f
   // A different method is called on b.
}

このインターフェイスは、変更が完全にメソッド内にあるため、作業が楽になります。アプリケーションの周りから呼び出される多くの場所について心配する必要はありません。

これは、元の設計が正しかったことを示唆しています。同意しますか?私は何が欠けていますか?

PS。このシステムでは、ドメイン オブジェクトは XML としての外部表現を認識していないため、動作が b 自体に属しているとは思いません。

4

4 に答える 4

4

まず、実際に doStuff で Foo オブジェクト f のメソッドを呼び出していない限り、これは必ずしもデメテルの法則に違反しているわけではありません。そうでない場合は、おそらく問題ありません。ビジネス オブジェクトのインターフェイスのみを使用している b. したがって、「f」で少なくとも 1 つのメソッドを呼び出していると仮定します。

「欠けている」可能性のあるものの1つは、テスト容易性、特に単体テストです。あなたが持っている場合:

public void doStuff( Business b, XMLElement x)
{
    Foo f = b.getFoo();
    // stuff using f.someMethod
    // business stuff with b
    // presumably something with x
}

...次に、doStuff が異なる Foo に対して正しいことを行うことをテストしたい場合は、最初に必要な Foo 'f' ごとに新しいビジネス オブジェクトを作成 (またはモック) し、次にそのオブジェクトを doStuff にプラグインします (ビジネス固有のものの残りの部分が同一である場合)。メソッドから 1 回削除してテストしている場合、ソース コードは単純なままでも、テスト コードはより複雑になります。したがって、doStuff で f と b の両方が本当に必要な場合は、おそらく両方ともパラメーターにする必要があります。

それについてもっと読むために、この人は私が出会った中で最も強調されたデメテルの法則の運動家の一人です。その根拠を示すことが多い。

于 2009-11-26T07:15:47.963 に答える
2

明確な回答は難しいと思いますので、

1) 問題の記述は非常に抽象的であり、
2) 「絶対的な」優れた設計はありません。それはクラスの周りにも依存します。また、最初は優れた設計であったものが、システムが成長するにつれてリファクタリングしたいものに発展する可能性があります。進化し、ドメインの理解がより洗練されます。

最初の例は、デメテルの原則の「大規模な」違反とは見なされませんが、ここでもすべてが詳細に記載されています。コメント セクションでどれだけ進んでいるかによって異なります。必要に応じて、いつでも間接的な方法を追加できます. たとえば、WriteBusinessObjectToXmlService クラスでメソッド「DoStuff」を使用できます。f を使用して行っていた作業の量が増えている場合は、それをそのメソッド「DoStuffWithF(f, x)」に抽出するか、別のメソッドを作成することもできます。 DoStuff(f, x) を持つクラス WriteFToXmlService。

于 2009-11-26T05:37:30.750 に答える
1

このロジックをさらに進めると、システム内のすべてへのリンクを含む global-everything-objects-repository オブジェクト (またはサービス ロケーター) を使用する必要があるという考えにたどり着きます。必要なのはこのリポジトリだけなので、メソッド シグネチャをまったく変更する必要はありません。

問題は、メソッドの目的が変更されたのに、署名が変更されていないことです。メソッドが必要とするすべてが Foo である場合は、Foo のみを受け入れる必要があります。このようにして、Foo のみで動作することがわかります。これにより、メソッドの目的がより明確に伝えられます。突然ビジネスも必要になった場合は、メソッドのシグネチャを変更する必要があります。これは、他のメソッドの目的と要件を示す必要があるためです。

于 2009-11-26T05:27:43.347 に答える
0

おそらく、Business を渡すことが正当化されるか、メソッドに 3 番目のパラメーター (Business オブジェクトで呼び出される他のメソッドの戻り値の型) が必要になります。これは、doStuff メソッドの本体の残りの部分に依存します。

于 2009-11-26T05:31:56.360 に答える