【问题标题】:Law of Demeter can easily be bypassed?得墨忒耳法则很容易被绕过?
【发布时间】:2019-11-20 02:27:02
【问题描述】:

是否总是可以通过创建更多方法来绕过得墨忒耳法则?

有人提到这是无效的 (http://wiki.c2.com/?LawOfDemeterIsHardToUnderstand),但它似乎应该是有效的,因为得墨忒耳法则允许向任何参数发送消息。

例如,这违反了得墨忒耳定律(假设m1 不返回a1)但可以重构:

class C1 {
    m1 (a1: C2) {
        a1.m1().m2() // not allowed
    }
}

m2的访问可以重构为另一种方法:

class C1 {
    m1 (a1: C2) {
        m2(a1.m1()) // allowed
    }

    m2 (a1: C3) {
        a1.m2()
    }
}

【问题讨论】:

  • “我希望它被称为 Demeter 的偶尔有用的建议。”马丁·福勒
  • 我更喜欢将其称为“Martin Fowler 偶尔有用的建议”。 :) 即使 Martin Fowler 知道什么时候违反 LoD 是可以的,但您可能不知道。所以停止这样做

标签: oop software-quality law-of-demeter


【解决方案1】:

"当你的方法接受参数时,你的方法可以调用方法 这些参数直接。”

我想说的是,它的编写方式留给解释是否应该考虑整个方法的执行堆栈(对我来说,这意味着要考虑它)。如果是,那么无论添加的间接级别如何(m2)都是违规行为,如果不是,则代码不违反规则。但是,这只是一个指导方针,对于不了解它所服务目标的开发人员没有帮助:增加封装并限制耦合。

当然有许多创造性的方法来创建仍然符合大多数设计原则的规则和定义的糟糕模型,但这显然不是重点。这就像声明可以使用反射轻松绕过私有修饰符:这是真的,但很难做到这一点。

在封装和耦合方面,你发布的代码和a1.m1().m2()没有区别:C1耦合到C2 AND C3是通过C2获得的。 C2 客户端(例如 C1)需要挖掘其内部结构这一事实很好地表明了它的封装性可以改进。

另一个与得墨忒耳法则齐头并进的原则是Tell Don't Ask 原则,它指出应该告诉对象做什么而不是询问它们的状态。这也有利于更好的封装,从而减少耦合。

需要注意的重要一点是,有两种类型的对象,数据结构和“真实对象”(数据和行为)。数据结构(例如 DTO——getter/setter 包)不受大多数​​设计原则的约束,例如 Demeter 法则,因为它们的作用仅仅是表示和共享数据。但是,此类数据结构通常存在于系统边界(例如应用程序服务、HTTP API 等),并且在模型的核心中包含许多此类对象是面向对象的代码异味。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-06-25
    • 1970-01-01
    • 1970-01-01
    • 2012-08-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多