24

デメテルの法則に関する記事を目にするときはいつでも、著者はこの法則に従う方法の確かな例を示しているようには見えません。彼らは皆、それが何であるかを説明し、法を破る例を示していますが、それは簡単です.

この法則に従う方法はおそらくたくさんあります (優れた設計と計画はその 1 つです)。

これらのプロパティを持つクラスがあるとしましょう:

public class Band {

    private Singer singer;
    private Drummer drummer;
    private Guitarist guitarist;
}

私はプログラムのどこかにいて、このBandクラスのインスタンスがあり、ギタリストの名前が必要です。通常、次のようなものが表示されます。

guitaristName = band.getGuitarist().getName();

それはチェーンに深く入りすぎていないため、それほど悪くはないように見えますが、デメテルの法則は、おそらく次のようにする必要があると言っています。

guitaristName = band.getGuitaristName();

私のBandクラスにはメソッドがあります:

public String getGuitaristName() {
    return guitarist.getName();
}

これがあなたが法律に従うことになっている方法ですか?

ありがとう。

4

4 に答える 4

45

Dancrumbが上で述べているように、法律の考え方は、人々が適切なレベルでオブジェクトにアクセスできるようにすることだと思います。

Band私たちのクラスがバンドのオフィスのフロント デスクをモデル化していると想像してください。バンドメンバーへのPAとして活動し、バンドと交流したい人に対応するのが仕事です.

ここで、PR 会社のツアー プロモーターが、次のツアーの PR 資料をまとめたいと考えているとします。クラスで彼をモデル化できます。

class TourPromoter {

  public String makePosterText(Band band) {
    String guitaristsName =  band.getGuitarist().getName();
    String drummersName = band.getDrummer().getName();
    String singersName = band.getSinger().getName();
    StringBuilder posterText = new StringBuilder();

    posterText.append(band.getName()
    posterText.append(" featuring: ");
    posterText.append(guitaristsName);
    posterText.append(", ");
    posterText.append(singersName);
    posterText.append(", ")
    posterText.append(drummersName);
    posterText.append(", ")
    posterText.append("Tickets £50.");

    return posterText.toString();
  }

}

実生活では、これはツアー プロモーターがオフィスに電話をかけ、次のように言っているのと同じです。

  • ツアー プロモーター:ギタリストと話せますか?

  • 受付係:わかりました、彼を連れて行きます。

  • ギタリスト:こんにちは、ギタリストです

  • ツアー プロモーター:こんにちは、あなたの最新のポスターをまとめています。名前を確認したかっただけですか?

  • ギタリスト:ジミー・ペイジです

  • ツアー プロモーター:ありがとうございます。ああ、あなたのドラマーを呼んでくれませんか?…</p>

PAはすぐに解雇されると言えば十分です。ほとんどの合理的な人々は、「その電話を処理してくれませんでしたか?」と尋ねるでしょう。

getGuitaristsName()技術的にはデメテルの法則を尊重する方法を使用することもできますが、TourPromoterクラスにはまだバンドに関する詳細を覚えておくように求めています。

賢明な方法でメソッドを導入していることを確認するには、ツアー プロモーターが実際に探しているもの、つまりすべてのバンド メンバーの名前を調べる必要があります。Bandそのメソッドをコードでモデル化すると、後で変更する際の柔軟性が高まりますTourPromoter

public class Band {
    private Singer singer;
    private Drummer drummer;
    private Guitarist guitarist;

    public String[] getMembers() {
        return {singer.getName(), drummer.getName(), guitarist.getName()};
    }  
}

public class TourPromoter {
    public String makePosterText(Band band) {
        StringBuilder posterText = new StringBuilder();

        posterText.append(band.getName());
        posterText.append(" featuring: "); 
        for(String member: band.getMembers()) {
            posterText.append(member);
            posterText.append(", ");
        }
        posterText.append("Tickets: £50");

        return posterText.toString();
    }    
}

ここで Bassist または KeyboardPlayer を追加すると、Band クラスだけが違いを知る必要があり、ツアー プロモーターは変更する必要がありません。これは、単一責任の原則も尊重していることを意味します。つまりmakePosterText()、バンドが変わった場合ではなく、ポスターのフォーマットを変更した場合にのみ方法を変更する必要があります。

私は、デメテルの法則が、最良の方法で(例えば、上記getMembers()ではなく)原則を満たすためにどの方法を引き出す必要があるかを教えてくれるとは思わない.getGuitaristsName()物事が壊れたときですが、必ずしもそれらを修正する方法ではありません。ただし、LoD を念頭に置くということは、SRP などの他の設計原則の組み合わせによって修正できる違反に注意を払うことを意味します。

于 2013-07-06T15:01:07.283 に答える
29

適切なレベルで LoD を適用していません。 と の両方BandGuitarist同じモジュールの一部と見なす必要があり、ジレンマは最大の利便性に基づいて決定する必要があります。

あなたの質問は、私がデザインパターンなどに関する本で頻繁に遭遇した、より広範な問題の例です。それらは、複雑なシステムの設計に関係する広範囲にわたる原則を、途方もなく小さい問題について説明しようとしています。その結果、読者は混乱するだけです。

この原則が実際に効果を発揮する場所は、次のようなものです。 Java NIO の上に構築さAsyncHttpClientれた抽象化であるを使用しています。Nettyここで、AsyncHttpClientの API がどこかで Java NIO オブジェクトを直接管理することを強制した場合、その API ははるかに未加工であり、完全に とは異なる概念を扱っていますAsyncHttpClient。これは LoD を壊す例です。

于 2013-06-30T18:07:54.603 に答える
2

この楽器を演奏しているのは誰ですか?

public String whoIsPlaying(String instrument);

次に、ギタリストの名前が必要な場合は、次のように言います。

band.whoIsPlaying("guitar");

他の楽器へのpingも止められません。

于 2015-04-27T19:42:55.067 に答える