2008-09-15 102 views

回答

71

那麼,法律的簡短定義會縮短它太多。真正的「法律」(實際上建議良好的API設計)基本上是這樣說的:只訪問你自己創建的對象,或者作爲參數傳遞給你。不要通過其他對象間接訪問對象。流暢的接口方法通常會返回對象本身,所以如果再次使用對象,它們不會違反法律。其他方法爲你創建對象,所以也沒有違規。

另請注意,「法律」只是「經典」API的最佳實踐建議。 Fluent接口是一種完全不同的API設計方法,不能用Demeter法進行評估。

+11

有人可能會說,流暢的界面不會違反Demeter法則,因爲您只能訪問點鏈中的同一個對象。 – MSN 2009-01-29 06:53:18

8

是的,雖然你必須運用一些實用主義的情況。我總是以德米特法爲準則,而不是一條規則。

當然,你可能想避免以下:

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

有可能取代:

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

隨着越來越多的我們的使用ORM通常呈現整個域作爲一個對象圖它可能成爲爲特定對象定義可接受的「範圍」的想法。也許我們應該採用德米特的法則來建議你不應該將整個圖形映射爲可達。

+3

我認爲單一職責原則可能採取的意思是「沒有一個方法對你業務對象發送電子郵件「。 – 2011-01-18 14:57:08

23

不一定。 「只用一個點」是對德米特法的不準確的總結。

迪米特法則不鼓勵使用多個點的當每個點代表一個不同的對象,結果如:

  • 首先點是從對象A被調用的方法,返回類型的對象對象B
  • 接下來點是這樣的方法只在對象B可用,返回類型的對象ObjectC
  • 接下來點是一個屬性僅在ObjectC
  • 循環往復
可用

但是,至少在我看來,迪米特法則不受侵犯,如果每一個點返回的對象仍然是相同類型的原調用:

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

在上面的例子中,兩個的FindAll( )和Sort()返回與原始列表相同類型的對象。德米特法沒有違反:名單隻與其直接的朋友交談。

這就是說並非所有的流利的接口違反德米特法則,只要他們返回與他們的調用者相同的類型。

6

得墨忒耳定律的精神在於,給定一個對象引用或類,你應該避免訪問一個類的屬性,這個類的屬性不止是一個子屬性或方法,因爲這會緊密地耦合兩個類,這可能是意外並可能導致可維護性問題。因爲他們是意味着是至少在某種程度上緊密耦合,因爲所有的屬性和方法是被組合在一起以形成功能的句子迷你語言的術語

流利接口是一個可接受的例外的法律。

1

你的例子沒有問題。畢竟,你在旋轉,加水印等等,總是有相同的圖像。我相信你一直在跟Pipeline對象通信,所以只要你的代碼只依賴於Pipeline的類,你就不會違反LoD。

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)良好的醇」菲爾哈克說:The Law of Demeter Is Not A Dot Counting Exercise