【问题标题】:Does the Law of Demeter only apply to methods?得墨忒耳法则是否只适用于方法?
【发布时间】:2010-10-21 16:19:51
【问题描述】:

我看到的 LOD 描述(例如,WikipediaC2 Wiki)谈到不调用方法。引用维基百科:

函数的得墨忒耳定律要求对象 O 的方法 M 只能调用以下类型对象的方法
- O 本身
- M的参数
- 在 M
中创建/实例化的任何对象 - O 的直接组件对象
- 一个全局变量,可以被 O 访问,在 M 的范围内

但是访问属性、变量或枚举呢?例如,鉴于此:

class FirstClass {
    public SecondClass GetRelatedClass() {
        return new SecondClass();
    }

    public enum InnerEnum {
        Violated,
        NotViolated
    }
}

class SecondClass {
    public int Property {get; set;}
    public string _variable = "Danny Demeter";
}

是否有任何/所有这些 LOD 违规? (如果可以的话,暂时忽略直接变量访问..)

void Violate(FirstClass first) {
    SecondClass second = first.GetRelatedClass();
    var x = second.Property;
    var y = second._variable;
    var z = FirstClass.InnerEnum.Violated;
}

我不会做前两个(无论是否“官方”违规),但对枚举不太确定。

【问题讨论】:

    标签: c# oop law-of-demeter


    【解决方案1】:

    我无法回答枚举问题——我似乎记得标准建议不是在类中定义枚举。

    对于属性,您真的可以将属性视为方法的快捷方式(getProperty()setProperty(value))。在这种情况下,您的回答是属性访问是违规行为。

    对于字段(变量),再一次,通常的做法是不暴露它们,而是使用属性,真正暴露字段是违反封装的。

    不过,Demeter 法则的最终目的是限制类之间的实现知识。对我来说,这意味着你所有的例子都是违规的。

    【讨论】:

    • 确实如此。 C2 Wiki 不讨论实例变量、字段、属性、枚举、属性、插槽等的原因仅仅是因为该社区的大部分成员都是旧的 Smalltalker,无论如何所有这些都是私有的。无论如何,字段、属性、实例变量、槽或它们被称为一对 getter/setter 方法是同构的,并且由于它们同构的,因此在一个字段和一个字段之间来回切换应该是显而易见的。 getter 不应该以任何方式更改 Demeter 属性。字段应该被简单地视为一种方法。
    【解决方案2】:

    FWIW...

    违规 #1 (x) 看起来像是一个粗略的服务位置模式,所以我怀疑该示例不是违规。

    违反 #2 (y) 看起来像是一种类设计气味,但通常不会证明超出违反 #1 所展示的任何内容。

    我认为公共枚举 (z),无论它们的范围如何,都不会在此处计入 LOD。

    您有更好的真实示例来证明您的担忧吗?如果没有适当的上下文,简单的代码示例可能没问题,或者它们可能违反设计原则。

    【讨论】:

    • 也许吧,虽然我认为如果你把它们都写在一起(从 LOD 的角度来看是相同的)看起来不太像:'x = first.GetRelatedClass().Property;'。或者服务位置有时会违反 LOD?
    猜你喜欢
    • 1970-01-01
    • 2018-04-14
    • 2016-06-25
    • 2011-04-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多