ウィキペディアからの定義
より正式には、関数のデメテルの法則では、オブジェクトOのメソッドmは、次の種類のオブジェクトのメソッドのみを呼び出すことができる必要があります。
1. O itself
2. m's parameters
3. Any objects created/instantiated within m
4. O's direct component objects
5. A global variable, accessible by O, in the scope of m
特に、オブジェクトは、別のメソッドによって返されるメンバーオブジェクトのメソッドを呼び出さないようにする必要があります。フィールド識別子としてドットを使用する多くの最新のオブジェクト指向言語では、法則は単に「1つのドットのみを使用する」と表現できます。つまり、コードabMethod()は、a.Method()が違反しない法則に違反します。簡単な例として、犬に歩いてもらいたい場合、犬の足に直接歩くように命令することはありません。代わりに、犬に命令し、犬は自分の足に命令します。
上記の場合、はい、これはデメテルの法則に違反します。
def first_survey?
# Should this be broken according to Law of Demeter?
self.kingdom.surveys.count == 1
それがやり過ぎかどうかについては、私はノーと言いますが、悪いコードは好きではありません(つまり、正しくないコードであり、本来よりも多くのエラーが発生する可能性があります。多くの議論があります)。
あなたがしたいことはこのようなものです:
def first_survey?
self.kingdom.surveys_count == 1
私の理解が正しければ、suverys.count
プロパティに直接アクセスしていないため、これはDemeterに違反しません。kingdom
代わりに、あなたはそれが持っている内部プロパティをあなたに返すように頼んでいます(これはオブジェクトのAPIを利用しているので私の意見ではより正しいですkingdom
)
# Is this the "right thing to do", or overkill?
def surveys_count
self.surveys.count
end
これは、他にどのように外部システムがそのプロパティにアクセスするかという「正しいこと」です。
コメントから
"string" .strip.downcase.tr_s('^ [a-z0-9]'、'-')はデメテルの違反ではないため、実際には1つのドットのみを使用することは非常に悪いルールです。
さて、あなたがそれを提起したので、私はあなたの声明に反対します。ここで非常に重要な情報を見落としているため、実際には悪いルールではありません。strip関数は、tr_sと同様に、新しい文字列オブジェクトと小文字を返します。3つの追加オブジェクトを生成する場合、開発者がそれを見るのは非常に心配です。また、メンバーに直接アクセスしているため、実際にはルールに違反しています。あなたが考慮したいと思うこと、そして決して私はRubyの専門家ではありません:このようなものです:
class MyString
{
string internal_string;
def strip()
{
self.internal_string = self.internal_string.strip
}
def downcase()
{
self.internal_string = self.internal_string.downcase
}
def tr_s()
{
self.internal_string = self.internal_string.tr_s
}
}
上記の機能により、開発者はライブラリ関数の周りに薄いラッパーを配置することでAPIを呼び出すことができます。これをやり過ぎと呼ぶ人もいるかもしれませんが、何ができ、何をすべきかについて非常に明確な線が引かれています。このデメテルを承認するために(私が法律を正しく理解している場合)
myString.strip().downcase().tr_s()
はっきりしないかもしれませんが、これはDemeterに違反していません。これはmyString
、過剰(多分)、最も正確(ほぼ確実)に公開されているAPIを呼び出しているためです。