“消息链”与“中间人”

时间:2011-07-07 10:38:11

标签: refactoring

我正在阅读福勒的重构书,对这两个代码气味有点困惑。

“消息链”是a.getB().getC().getValue()之类的调用。

“中间人”是一种类似

的方法
class A
{
    object getCValue()
    {
        return b.getCValue();
    }
}

我理解这两个部分的方式是,如果你有“消息链”,你可以通过引入“中间人”来缩短它们。如果你有“中间人”,你就把它们变成“消息链”......

现在显然必须有一些限制,或者你有一个程序员的旋转木马。 我应该在什么时候支持另一个?

一个是将类耦合到不相关的类,另一个是将类耦合到结构。所以理论上我的方法是检查任何给定的变化是否会减少一种耦合,而不是增加另一种耦合。但是,一种耦合是否更糟,应该更加权衡?即如果你可以删除X结构耦合,只添加一个类耦合?

3 个答案:

答案 0 :(得分:8)

优先考虑消息链的中间人也称为Law of Demeter,可以概括为“仅与您的直接依赖关系进行对话”。

使用中间人而不是消息链的一个好处是,在进行单元测试时必须提供更少的模拟。当你不仅要为它们的直接依赖提供模拟而且还要提供它们的间接依赖时,类很难测试。

它还有助于分离关注点,因为具有A且希望C的代码不应该知道涉及B。这有助于模块化。

消息链的主要论点是你不必在中间编写样板文件,在某些情况下它可能有意义,但我认为经验法则应该是偏爱中间人。

答案 1 :(得分:3)

正如哈马尔所说,这一个都是关于得墨忒耳的法则。像a.getB().getC().getD()这样的事情总是很糟糕。它们引入了与A接口客户端的耦合。更喜欢介绍一个中间人,例如:

class A
    def calculateHowManyCowsCanFitOnTheMoon
        doLocalCalculation(b.performEncapsulatedCalculation())
    end
end

当你没有像上面那样服务于目的时,你想要摆脱中间人,例如当它只是从B中提取数据时。我甚至会说重建一个坏中间人可能是Move Field / Move Method重构。

答案 2 :(得分:1)

这是你的选择。以您认为更易于维护的方式对其进行编码。顺便说一句,我认为没有“将课程与无关课程联系起来”的情况。相反,它是将间接关系转变为直接关系的问题。当您从类中多次访问间接类时,这尤其值得。这也可能会删除对中间类的一些依赖性,具体取决于您建立直接关系的方式。