维基百科文章 关于 德墨忒耳定律 说:

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

然而一个 简单的例子 的一个 流畅的界面 可能看起来像这样:

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

那么这可以在一起吗?

有帮助吗?

解决方案

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

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

其他提示

不必要。“只使用一个点”是对德墨忒尔定律的不准确概括。

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

  • 第一个点是从 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() 都返回与原始列表相同类型的对象。不违反德墨忒尔法则:该名单只与它的直接朋友交谈。

话虽如此 不是全部 流畅的接口违反了得墨忒耳定律,只要它们返回与调用者相同的类型即可。

是的,尽管你必须对这种情况采取一些实用主义。我总是把德墨忒尔法则作为指导方针,而不是规则。

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

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

也许替换为:

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

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

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

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

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 所说: 德墨忒耳定律不是点数练习

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

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top