stream利的界面是否违反了德米特法?

维基百科关于Demeter法律的 文章说:

法律可以简单地表述为“只使用一个点”。

但是stream畅的界面的一个简单的例子可能是这样的:

static void Main(string[] args) { new ZRLabs.Yael.Pipeline("cat.jpg") .Rotate(90) .Watermark("Monkey") .RoundCorners(100, Color.Bisque) .Save("test.png"); } 

那么这是一起吗?

那么,这个法律的简短定义缩短了太多。 真正的“法律”(实际上是build立在良好的APIdevise上)基本上是这样说的:只访问你自己创build的对象,或者作为parameter passing给你。 不要通过其他对象间接访问对象。 stream畅的接口方法通常会返回对象本身,所以如果再次使用对象,它们不会违反法律。 其他方法为你创build对象,所以也没有违规。

另外请注意,“法律”只是“经典”API的最佳实践build议。 Fluent接口是一种完全不同的APIdevise方法,不能用Demeter法进行评估。

不必要。 “只用一个点”是得墨忒耳定律的一个不准确的总结。

德米特定律不鼓励在每个点代表不同对象的结果时使用多个点,例如:

  • 第一个点是从ObjectA调用的方法,返回ObjectBtypes的对象
  • 下一个点是仅在ObjectB中可用的方法,返回ObjectCtypes的对象
  • 下一个点是只在ObjectC中可用的属性
  • 无限的

不过,至less在我看来,如果每个点的返回对象与原来的主叫方仍然是同一types的话,则不会违犯德米特法则:

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

在上面的例子中,FindAll()和Sort()都返回与原始列表相同types的对象。 得墨忒耳的法律没有违反:名单只与其直接的朋友谈话。

这就是说, 并不是所有stream畅的接口都违反了德米特法则,只要它们返回与调用者相同的types即可。

是的,虽然你必须运用一些实用主义的情况。 我总是以德米特定律为准则,而不是一个规则。

当然,你可能想要避免以下情况:

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

也许换成:

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

随着越来越多的人使用ORM,它通常将整个域作为对象图来呈现,为特定对象定义可接受的“范围”可能是一个想法。 也许我们应该采用德米特的法则来build议你不应该把整个graphics映射为可达的。

德米特定律的精神是,如果给定一个对象引用或类别,你应该避免访问一个多于一个子属性或方法的类的属性,因为这会紧密地耦合这两个类,这可能是无意的,并可能导致可维护性问题。

stream畅的接口是法律的一个可接受的例外,因为它们意味着至less在某种程度上紧密耦合,因为所有的属性和方法都是迷你语言的术语,它们被组合在一起形成function句子。

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)正如菲尔·哈克(Phil Haack)所说: 得墨忒耳的定律不是一个点算的练习

你的例子没有问题。 毕竟,你正在旋转,水印等…总是相同的图像。 我相信你一直在和一个Pipeline对象交stream,所以只要你的代码只依赖于Pipeline的类,你就不会违反LoD。