2008-09-15 99 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