6
public class BigPerformance  
{  
    public decimal Value { get; set; }
}  

public class Performance  
{  
    public BigPerformance BigPerf { get; set; }
}  

public class Category    
{  
    public Performance Perf { get; set; }     
}

如果我打电话:

Category cat = new Category();  
cat.Perf.BigPerf.Value = 1.0;  

我认为这违反了得墨忒耳定律/最少知识原则
如果是这样,如果我有大量内部类属性,我该如何解决这个问题?

4

5 回答 5

9

我最喜欢 Martin Fowler 的一句话:

我希望它被称为 Demeter 的偶尔有用的建议

http://haacked.com/archive/2009/07/14/law-of-demeter-dot-counting.aspx

于 2010-04-19T11:50:51.793 回答
3

如果你在谈论得墨忒耳法则,“不要叫邻居的邻居”,你可以将它委托给其他方法来做你想做的事。

从您的示例中,我猜您想重置性能值或其他内容。您可以修改示例代码,以便将它们固有地链接起来:

Category cat = new Category();

cat.resetPerf();

代码将类似于以下内容:

public class BigPerformance 
{
    //constructors 'n stuff

    public static decimal DEFAULT;

    public decimal Value {get; private set;}

    public void reset() {
        Value = BigPerformance.DEFAULT;
    }
}

public class Performance
{
    //constructors 'n stuff

    private BigPerformance BigPerf {get; set};

    public reset() {
        BigPerf.reset();
    }
}

public class Category
{
    // constructors 'n stuff

    public Performance Perf {get; private set;}

    public resetPerformance() {
        Perf.reset();
    }
}

这样Category类就不需要知道如何重置该值,以防默认值不同或将来更改其类型。

就个人而言,如果改变的风险很低,我会选择juharr 的答案

于 2010-04-19T11:40:36.747 回答
1
Category cat = new Category();  
cat.Perf.BigPerf.Value = 1.0;  

Category cat = new Category();  
cat.GetPerf().GetBigPerf().SetValue(1.0);  

因此,如果维基百科的定义是正确的,那就违反了规则:

..[M] 对象 O 的方法 M 只能调用以下几种对象的方法:

  • O本身
  • M的参数
  • 在 M 中创建/实例化的任何对象
  • O 的直接组件对象
  • 一个全局变量,可由 O 访问,在 M 的范围内

特别是,一个对象应该避免调用另一个方法返回的成员对象的方法

如果您担心 3 紧密耦合,则删除公共访问器并在 Category 上添加一个方法来设置值。然后将 Performance 和 BigPerformance 重构为私有成员。

于 2010-04-19T11:41:58.480 回答
1

如果您始终牢记类的可测试性并使用 IoC,您会注意到您不必担心 LoD。

这样看

我将如何测试Category我不希望它自动创建一个Performance使用慢速文件系统的文件。让我们通过 一个虚拟实例IPerformanceCategory 替换实际的实现。Performance

我将如何测试Performance 我不希望它自动创建BigPerformance与数据库的连接。让我们通过 一个虚拟实例IBigPerformancePerformance替换实际的实现 。 ...您显然注意到了这种模式BigPerformance

您的代码将在

BigPerformance BigPerf = new BigPerformance();
BigPerf.Value := 1.0;
Performance Perf = new Performance(BigPerformance);
Category cat = new Category(Performance);

(This would be retrieved from a factory.)

它看起来(并且在短期内可能是)需要更多的工作,但从长远来看,通过能够单独测试你的类,这些好处将得到回报。

查看Misco Hevery 的博客,让您大开眼界,了解这个主题和其他主题。

于 2010-04-19T12:15:40.477 回答
0

这并没有违反得墨忒耳法则,因为您使用的是公共课程合同。

于 2010-04-19T11:26:04.300 回答