6
public class BigPerformance  
{  
    public decimal Value { get; set; }
}  

public class Performance  
{  
    public BigPerformance BigPerf { get; set; }
}  

public class Category    
{  
    public Performance Perf { get; set; }     
}

私が電話した場合:

Category cat = new Category();  
cat.Perf.BigPerf.Value = 1.0;  

これはデメテルの法則/最小知識の原則に違反していると思いますか?
もしそうなら、内部クラスのプロパティが多数ある場合、どうすればこれを修正できますか?

4

5 に答える 5

9

Martin Fowler からの私のお気に入りの引用の 1 つ:

デメテルの時折有用な提案と呼ばれることを望みます

http://haacked.com/archive/2009/07/14/law-of-demeter-dot-counting.aspx

于 2010-04-19T11:50:51.793 に答える
3

「隣人の隣人を呼び出さないでください」のようにデメテルの法則について話している場合は、必要なことを行う他のメソッドに委任できます。

あなたの例から、パフォーマンス値などをリセットしたいと思います。コード例を変更して、代わりに本質的に連鎖するようにすることができます。

Category cat = new Category();

cat.resetPerf();

コードは次のようになります。

public class BigPerformance 
{
    //constructors 'n stuff

    public static decimal DEFAULT;

    public decimal Value {get; private set;}

    public void reset() {
        Value = BigPerformance.DEFAULT;
    }
}

public class Performance
{
    //constructors 'n stuff

    private BigPerformance BigPerf {get; set};

    public reset() {
        BigPerf.reset();
    }
}

public class Category
{
    // constructors 'n stuff

    public Performance Perf {get; private set;}

    public resetPerformance() {
        Perf.reset();
    }
}

そうCategoryすれば、デフォルト値が何か違う場合や将来型が変更された場合に、クラスは値をリセットする方法を知る必要がありません。

個人的には、変更のリスクが低い場合は、代わりにjuharrの答えを選びます。

于 2010-04-19T11:40:36.747 に答える
1

クラスのテスト可能性を常に念頭に置いてIoCを使用すると、LoDについてそれほど心配する必要がないことに気付くでしょう。

このように見てください

どのようにテストしCategoryますか?Performance遅いファイルシステムを使用しているを自動的に作成したくありません。IPerformanceにパススルーして、実際の実装をダミーインスタンスCategory に置き換えましょう 。Performance

どのようにテストしPerformanceますか?BigPerformanceデータベースへの接続を 自動的に作成することは望ましくありません。IBigPerformanceにパススルーして 、実際の実装をダミーインスタンスPerformanceに置き換え ましょう 。 ...あなたは明らかにパターンに気づきますBigPerformance

あなたのコードは次の行になります

BigPerformance BigPerf = new BigPerformance();
BigPerf.Value := 1.0;
Performance Perf = new Performance(BigPerformance);
Category cat = new Category(Performance);

(This would be retrieved from a factory.)

見た目は(そして短期的にはおそらく)もっと多くの作業のように見えますが、クラスを個別にテストできることで、長期的にはメリットが実を結びます。

このテーマや他のテーマに関する目を見張るようなものについては、 MiscoHeveryのブログをご覧ください。

于 2010-04-19T12:15:40.477 に答える
1
Category cat = new Category();  
cat.Perf.BigPerf.Value = 1.0;  

Category cat = new Category();  
cat.GetPerf().GetBigPerf().SetValue(1.0);  

したがって、ウィキペディアの定義が正しい場合、ルールに違反しています。

..[M]オブジェクト O のメソッド M は、次の種類のオブジェクトのメソッドのみを呼び出すことができます。

  • 〇そのもの
  • M のパラメーター
  • M 内で作成/インスタンス化されたオブジェクト
  • O の直接コンポーネント オブジェクト
  • M のスコープ内で、O からアクセスできるグローバル変数

特に、オブジェクトは、別のメソッドによって返されたメンバー オブジェクトのメソッドを呼び出すことを避ける必要があります。

3 つが密結合していることが心配な場合は、パブリック アクセサーを削除し、Category にメソッドを追加して値を設定します。次に、Performance と BigPerformance をリファクタリングしてプライベート メンバーにします。

于 2010-04-19T11:41:58.480 に答える
0

クラスのパブリック契約を使用しているため、これはデメテルの法則に違反していません。

于 2010-04-19T11:26:04.300 に答える