2009-07-20 10 views
5

Law of Demeterは、オブジェクトをクラスコンストラクタに渡すことを妨げません。しかし、同じオブジェクトを後で戻すことと、スカラー値を取得するためのメソッドを呼び出すことは禁じられています。その代りに代わりにスカラー値を返すプロキシメソッドが作成されるはずです。私の質問は、オブジェクトをクラスコンストラクタに渡すことは容認できますが、後で同じオブジェクトを取得してそのオブジェクトから値を引き出すのは容認できません。デモータとクラスコンストラクタの法則

+0

"直径の法則"へのリンクを提供できますか? – gahooa

答えて

13

デメテルの法則は、あなたがクライアントがただの保留やアクセスをつかむことができ、既知のインタフェースを備えた特定の他のオブジェクトで構成されているかのように見えるように、オブジェクトの外部インタフェースを設計するべきではないと言うので。

新しいオブジェクトにどのように振る舞うかを伝えるためにオブジェクトをコンストラクタに渡しますが、オブジェクトがそのパラメータオブジェクトを保持しているかどうか、またはそのコピーを保持するか、それが存在するのを忘れてしまった。 getMyParameterBackメソッドを使用することにより、将来のすべての実装をオンデマンドでオブジェクト全体を生成できるようにし、すべてのクライアントを2つのインタフェースではなく2つのインタフェースで結合することができます。

たとえば、URLパラメータをHTTPRequestオブジェクトのコンストラクタに渡すと、HTTPRequestにgetURLメソッドが必要であることを意味するわけではありません。このメソッドは、呼び出し元がgetProtocol、getQueryString、 HTTPRequestオブジェクトを持っている人がリクエストのプロトコルを知りたいのであれば、getProtocolを自分が持っているオブジェクトで呼び出すことで見つけ出すべきです。内部的に。

アイデアは、結合を低減することである - デメテルの法則せずに、ユーザーは、プロトコルを得るためには、HTTPRequest へのインタフェースと URLを知っている必要があります。法律では、HTTPRequestへのインターフェイスのみが必要です。そして、HTTPRequest。getProtocol()は、いくつかのURLオブジェクトを議論に関与させる必要なく、明確に "http"を返すことができます。

リクエストオブジェクトのユーザーが、リクエストオブジェクトの作成者である場合があり、そのためパラメータを渡すためにURLインターフェイスも使用していることがあります。 HTTPRequestオブジェクトのすべてのユーザーがそれらを作成したわけではありません。したがって、法律に基づいてURLをアクセスする権利を持つクライアントは、それを自分で作成したため、リクエストから取り戻すのではなく、そのようにすることができます。 URLを作成していないクライアントはできません。

私は個人的には、通常、単純な形式で記載されているようにデメテルの法則は、ひびが入っていると思います。私のオブジェクトに文字列のNameフィールドがある場合、名前にASCII以外の文字が含まれているかどうかを知りたい場合は、文字列自体を見る代わりにオブジェクトにNameContainsNonASCIICharactersメソッドを定義するか、文字列が私が書いた関数のパラメータであることを保証することによって制限を回避するためにコールバック関数を取るクラスにvisitName関数を追加しますか?これはカップリングをまったく変更しません。ゲッターメソッドをビジターメソッドに置き換えます。整数を返すすべてのクラスは、戻り値を操作したい場合に備えて、算術演算の完全なセットを持つべきですか? getPriceMultipliedBy(int n)?確かにそうではありません。

あなたがそれを壊すと、なぜそれを壊しているのか、それを壊さないことでより良いインターフェースを設計できるかどうかを尋ねることができます。頻繁に行うことができますが、実際にはあなたが話しているオブジェクトの種類に依存します。特定のインターフェイスは、広範に使用されている概念を表す整数、文字列、URLなどのコードの膨大な部分に対して安全に結合できます。

+0

Uriラッパーはちょうど文字列のように私がこのルールから免除されると思われるユビキタスクラスのものです。終わりの手段として見ても、これは良い経験則ですが、それ自体は終わりではありません。目標は内部の実装の詳細を非表示にすることです。 –

+0

はい、私はそれがDemeterのガイドラインと呼ばれていても何の議論もないでしょうが、群れの猫に助言をしようとすると臆病ではありません。私は学問的な練習として法律としてそれを適用することは興味深く実りあり、インターフェースデザインを改善するための多くのアイデアを提供することは間違いありません。 IMOでは、あるインタフェースを他のインタフェースに日常的に埋め込むとすぐに線を引いていきます。ときどきXは実際にはYしか持っていません。誰もがそれを知っています:-) –

+0

についての私の心配狂気の猫典型的なプログラマーは、いくつかは魔法のような良いアイデアを見る傾向があるということです。ステレオタイプの例は、GoFの本をDesign Patternsで読んでから、すべてをSingletonに変える最近の卒業生です。 –

4

あなたの直属の友人としか話すことができません。だから、あなたはこれをしない...

あなたがこれを行う代わりに
var a = new A(); 
var x = a.B.doSomething(); 

...

var a = new A(); 
var x = a.doSomething(); // where a.doSomething might call b.doSomething(); 

それは物事が発信者のために簡単になるなどの利点、(Car.Start()対のしていますCar.Engine.Start())、しかし、あなたは小さなラッピングメソッドをたくさん取得します。 Mediator patternを使用して、このタイプの「違反」を緩和することもできます。

+0

私はこれまでにDemeterの法則について聞いたことがないので、Bに委譲する便利な関数は必須であるが、 "B getB()const"は禁止されているのは理にかなっていますか?もしそうなら、なぜですか? –

+0

それは法律の全体的な考えです...「あなたはただの友人と話すだけです。そのメリットは何ですか?このアイデアは長い間ずっと続いていました。最近では、非常に疎結合のアプリケーションを作成しています。 –

4

JPの答えはかなり良いですので、これは単なるサプリメントではなく、意見の相違や他の代替品です。

私は、このヒューリスティックを理解する方法は、Aへの呼び出しがあるため、クラスBの変化を破るべきではないということです。したがって、a.b.foo()で呼び出しをチェーンすると、AのインターフェースはBに依存し、ルールに違反します。代わりに、あなたはb.foo()を呼び出すa.BFoo()を呼び出すことになっています。

これは親指の良いルールですが、それは実際にそれを安置ほどの依存性に対処していない厄介なコードにつながることができます。今、AはBがもはやFooを提供しなくても、BFooを永遠に提供しなければならない。 Bの変更がFooを望む呼び出し側を壊した場合、B自体ではなく、Fooを必要とする呼び出し側が壊れた場合は、改善の余地はほとんどありません。

私もそれを追加することになり、厳密に言えば、このルールは、文字列としてユビキタスクラッセ、特定のグループのために常に壊れています。おそらく、アプリケーションの特定のレイヤー内でどのクラスが同様に遍在しているのかを判断し、Demeterの「ルール」を自由に無視することはおそらく許容されます。

+0

あなたは私と同じように言ったので、ここで+1する必要があります。 –

+0

Amd素敵な例が含まれて以来、私は好意を返しました。 –

関連する問題