Law of Demeter指示您只能与直接了解的对象交谈。即,不要执行方法链接来与其他对象交谈。这样做时,您正在与中间对象建立不正确的链接,从而不恰当地将您的代码coupling与其他代码联系起来。

那很糟。

解决方案将是针对您所知道的类,从本质上公开简单的包装器,这些包装器将职责委派给与其具有关系的对象。

那很好。

但是,这似乎导致该类的cohesion低。它不再只是对它的确切工作负责,而是在某种意义上也具有委托(delegate),这可以通过复制相关对象接口(interface)的某些部分来降低代码的内聚性。

那很糟。

真的会降低凝聚力吗?是两个邪恶中的较小者吗?

这是发展的灰色 Realm 之一,在这里您可以讨论分界线在哪里,或者是否有强有力的原则性方法来决定分界线以及可以使用哪些标准来做出决定?

最佳答案

Grady Booch在“面向对象的分析和设计”中:

“凝聚力的想法也来自结构化设计。简单地说,凝聚力
测量单个模块的各个元素之间的连通程度(以及
对于面向对象的设计,可以使用单个类或对象)。最不希望的形式
凝聚力是巧合的凝聚力,其中完全不相关的抽象是
扔到相同的类或模块中。例如,考虑一个包含
狗和航天器的抽象,它们的行为是完全无关的。的
最理想的内聚形式是功能内聚,其中
一个类或模块一起工作以提供一些良好的行为。
因此,如果Dog类的语义包含行为,则它在功能上具有凝聚力
一只狗,整个狗,只剩下那只狗。”

在上面用“客户”替换“狗”,它可能会更清晰一些。因此,目标的真正目的只是为了实现功能上的凝聚力,并尽可能地避免巧合的凝聚力。根据您的抽象,这可能很简单,也可能需要一些重构。

请注意,内聚对“模块”的作用与对单个类(即一组协同工作的类)的作用相同。因此,在这种情况下,Customer和Order类仍然具有良好的凝聚力,因为它们具有这种强大的关系,客户创建订单,订单属于客户。

马丁·福勒(Martin Fowler)说,将其称为“Demeter的建议”会更自在(请参阅文章Mocks aren't stubs):

“模拟测试人员确实谈论了避免'火车残骸'的更多方式-getThis()。getThat()。getTheOther()风格的方法链。避免方法链也被称为遵循Demeter定律。虽然方法链是一种气味,中间人用转发方法肿的对象的相反问题也是一种气味。(我一直觉得如果把Demeter定律叫做推荐给Demeter ,我会更满意。)”

这很好地总结了我的来历:完全严格地接受“法律”可能需要的凝聚力是完全可以接受的,并且经常是必须的。避免巧合的内聚力,并追求功能上的内聚力,但不要在需要适应设计抽象的自然情况下进行调整。

09-28 03:47