62

デメテルの法則に関するウィキペディアの記事は、次のように書かれています。

法則は「一点だけ使う」と簡単に言えます。

ただし、流暢なインターフェースの簡単な例は次のようになります。

static void Main(string[] args)
{
   new ZRLabs.Yael.Pipeline("cat.jpg")
        .Rotate(90)
        .Watermark("Monkey")
        .RoundCorners(100, Color.Bisque)
        .Save("test.png");
}

それで、これは合っていますか?

4

7 に答える 7

89

まあ、法の短い定義はそれをあまりにも短くします。本当の「法則」(実際には優れたAPI設計に関するアドバイス)は基本的に次のように述べています。自分で作成したオブジェクト、または引数として渡されたオブジェクトにのみアクセスします。他のオブジェクトを介して間接的にオブジェクトにアクセスしないでください。流暢なインターフェースのメソッドは、オブジェクト自体を返すことが多いため、オブジェクトを再度使用する場合でも、法律に違反することはありません。他のメソッドはあなたのためにオブジェクトを作成するので、違反もありません。

また、「法則」は「従来の」APIのベストプラクティスのアドバイスにすぎないことにも注意してください。Fluentインターフェイスは、API設計とはまったく異なるアプローチであり、デメテルの法則では評価できません。

于 2008-09-15T22:26:51.650 に答える
28

必ずしも。「1つのドットのみを使用する」は、デメテルの法則の不正確な要約です。

デメテルの法則は、各ドットが異なるオブジェクトの結果を表す場合、複数のドットの使用を推奨していません。例:

  • 最初のドットはObjectAから呼び出されるメソッドで、ObjectB型のオブジェクトを返します。
  • 次のドットは、ObjectBでのみ使用可能なメソッドであり、ObjectC型のオブジェクトを返します。
  • 次のドットは、ObjectCでのみ使用可能なプロパティです
  • ad infinitum

ただし、少なくとも私の意見では、各ドットの戻りオブジェクトが元の呼び出し元と同じタイプである場合、デメテルの法則に違反することはありません。

var List<SomeObj> list = new List<SomeObj>();
//initialize data here
return list.FindAll( i => i == someValue ).Sort( i1, i2 => i2 > i1).ToArray();

上記の例では、FindAll()とSort()の両方が、元のリストと同じタイプのオブジェクトを返します。デメテルの法則に違反することはありません。リストはその直接の友人とだけ話しました。

とはいえ、発信者と同じタイプを返す限り、すべての流暢なインターフェイスがデメテルの法則に違反しているわけではありません。

于 2008-09-15T22:28:00.163 に答える
9

デメテルの法則の精神は、オブジェクト参照またはクラスが与えられた場合、2 つ以上のサブプロパティまたはメソッドが離れているクラスのプロパティにアクセスすることは避けるべきであるということです。保守性の問題。

すべてのプロパティとメソッドは機能的な文を形成するために一緒に構成されたミニ言語の用語であるため、流暢なインターフェイスは少なくともある程度緊密に結合されることを意図しているため、法律の許容可能な例外です。

于 2008-09-15T22:31:51.107 に答える
8

はい、状況にいくつかの実用主義を適用する必要がありますが。私は常に、ルールではなく、デメテルの法則をガイドラインとしてとらえています。

確かに、次のことは避けたいと思うかもしれません。

CurrentCustomer.Orders[0].Manufacturer.Address.Email(text);

おそらく次のように置き換えます:

CurrentCustomer.Orders[0].EmailManufacturer(text);

一般にドメイン全体をオブジェクトグラフとして表示するORMを使用する人が増えるにつれ、特定のオブジェクトに対して許容可能な「スコープ」を定義することが考えられるかもしれません。おそらく、デメテルの法則に従って、グラフ全体を到達可能としてマップするべきではないことを示唆する必要があります。

于 2008-09-15T22:23:36.447 に答える
6

1) 全く違反していません。

コードは次と同等です

var a = new ZRLabs.Yael.Pipeline("cat.jpg");
a = a.Rotate(90);
a = a.Watermark("Monkey");
a = a.RoundCorners(100, Color.Bisque);
a = a.Save("test.png");

2) 古き良きフィル・ハークが言うように:デメテルの法則は点を数える練習ではありません

于 2010-11-24T16:52:01.617 に答える
1

あなたの例に問題はありません。結局のところ、回転、透かしなど...常に同じ画像です。コードが Pipeline のクラスのみに依存している限り、LoD に違反していません。

于 2010-03-20T09:57:56.597 に答える