Language agnostic 流畅的界面是否违反了德米特定律?

Language agnostic 流畅的界面是否违反了德米特定律?,language-agnostic,oop,api-design,Language Agnostic,Oop,Api Design,报告说: 法律可以简单地说是“只使用一个点” 然而,a的a可能是这样的: static void Main(string[] args) { new ZRLabs.Yael.Pipeline("cat.jpg") .Rotate(90) .Watermark("Monkey") .RoundCorners(100, Color.Bisque) .Save("test.png"); } 那么,这两者是同时发生的吗?是的,尽管你

报告说:

法律可以简单地说是“只使用一个点”

然而,a的a可能是这样的:

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

那么,这两者是同时发生的吗?

是的,尽管你必须在这种情况下运用一些实用主义。我总是以得墨忒尔定律作为指导,而不是规则

当然,您可能希望避免以下情况:

CurrentCustomer.Orders[0].Manufacturer.Address.Email(text);
或者替换为:

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

随着我们越来越多地使用ORM,ORM通常将整个域表示为对象图,因此为特定对象定义可接受的“范围”可能是一个好主意。也许我们应该用得墨忒尔定律来说明,你不应该把整个图形映射为可达的。

好吧,这个定律的简短定义把它缩短得太多了。真正的“定律”(实际上是关于良好API设计的建议)基本上是这样说的:只访问您自己创建的对象,或者作为参数传递给您的对象。不要通过其他对象间接访问对象。fluent接口的方法通常返回对象本身,因此如果再次使用该对象,它们不会违反法律。其他方法为您创建对象,因此也没有冲突

还请注意,“法律”只是“经典”API的最佳实践建议。流畅的接口是一种完全不同的API设计方法,不能用德米特定律进行评估。

不一定。“只使用一个点”是对得墨忒尔定律的不准确总结

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

  • 第一个点是从ObjectA调用的方法,返回ObjectB类型的对象
  • 下一个点是仅在ObjectB中可用的方法,返回ObjectC类型的对象
  • 下一个点是仅在ObjectC中可用的属性
  • 无限远
但是,至少在我看来,如果每个点的返回对象仍然与原始调用方的类型相同,则不会违反Demeter定律:

var List<SomeObj> list = new List<SomeObj>();
//initialize data here
return list.FindAll( i => i == someValue ).Sort( i1, i2 => i2 > i1).ToArray();
var List=newlist();
//在此初始化数据
return list.FindAll(i=>i==someValue).Sort(i1,i2=>i2>i1.ToArray();
在上面的示例中,FindAll()和Sort()都返回与原始列表相同类型的对象。《得墨忒尔法》并未被违反:该名单只与直接的朋友进行了交谈


也就是说,并非所有流畅的接口都违反了Demeter定律,只要它们返回的类型与调用者相同。

Demeter定律的精神在于,给定一个对象引用或类,您应该避免访问距离多个子属性或方法的类的属性,因为这将紧密耦合两个类,这可能是无意的,并且可能会导致可维护性问题


流畅的界面是一个可以接受的例外,因为它们意味着至少在某种程度上紧密耦合,因为所有的属性和方法都是一种微型语言的术语,它们组合在一起形成功能句。

你的例子没有问题。毕竟,你在旋转,水印等等。。。总是一样的形象。我相信您一直在与管道对象交谈,因此只要您的代码只依赖于管道的类,您就没有违反LoD。

1)它根本没有违反LoD

代码相当于

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) 正如Good Ol'Phil Haack所说:

从本质上讲,对象不应该公开其内部(数据),而应该公开使用内部操作的函数

考虑到这一点,fluentapi要求对象处理其数据,而不是要求其数据


这并不违反德米特定律。

有人可能会说,流畅的界面并不违反德米特定律,因为你只访问点链中的同一个对象。第二种方法是,流畅的界面只是一种替代,紧凑的执行顺序操作的方式,这种方式可以抽象出状态突变,因为每个中间步骤的结果都是隐式的。我认为单一责任原则可能意味着“在您的业务对象上没有发送电子邮件的方法”.这是一个重要的问题,因为违反Demeter定律会使包含模拟的单元测试难以维护(尽管fluent链可能是一个例外)。