62

关于得墨忒耳法则的维基百科文章说:

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

然而,流畅界面的简单示例可能如下所示:

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

那么这是否合二为一呢?

4

7 回答 7

89

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

另请注意,“法律”只是“经典”API 的最佳实践建议。流畅的接口是一种完全不同的 API 设计方法,不能用得墨忒耳定律来评估。

于 2008-09-15T22:26:51.650 回答
28

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

当每个点代表不同对象的结果时,得墨忒耳法则不鼓励使用多个点,例如:

  • 第一个点是从 ObjectA 调用的方法,返回一个 ObjectB 类型的对象
  • 下一个点是只在 ObjectB 中可用的方法,返回一个 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() 都返回与原始列表相同类型的对象。没有违反得墨忒耳法则:该列表只与它的直系朋友交谈。

话虽如此,并非所有流畅的接口都违反得墨忒耳法则,只要它们返回与其调用者相同的类型。

于 2008-09-15T22:28:00.163 回答
9

得墨忒耳定律的精神是,给定一个对象引用或类,你应该避免访问一个多于一个子属性或方法的类的属性,因为这会使这两个类紧密耦合,这可能是无意的,并且可能导致可维护性问题。

流利的接口是一个可接受的例外,因为它们至少是紧密耦合的,因为所有属性和方法都是迷你语言的术语,它们组合在一起形成功能性句子

于 2008-09-15T22:31:51.107 回答
8

是的,尽管您必须对这种情况采取一些务实的态度。我总是将得墨忒耳法则作为指导而不是规则。

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

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

也许替换为:

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

随着我们中越来越多的人使用通常将整个域呈现为对象图的 ORM,为特定对象定义可接受的“范围”可能是一个想法。也许我们应该利用得墨忒耳定律来建议您不应该将整个图形映射为可到达的。

于 2008-09-15T22:23:36.447 回答
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) 正如 Good Ol' Phil Haack 所说:得墨忒耳定律不是点数练习

于 2010-11-24T16:52:01.617 回答
1

你的例子没有问题。毕竟,您正在旋转、添加水印等……总是相同的图像。我相信您一直在与 Pipeline 对象交谈,因此只要您的代码仅依赖于 Pipeline 的类,您就不会违反 LoD。

于 2010-03-20T09:57:56.597 回答
1

从本质上讲,一个对象不应该暴露它的内部(数据),而是暴露函数来操作内部。

考虑到这一点,Fluent API 要求对象使用其数据处理某事,而不是询问其数据。

这并不违反任何得墨忒耳法则。

于 2020-06-20T00:58:46.050 回答