如何修改代码以使其遵守德米特定律

发布于 2024-08-29 01:41:35 字数 526 浏览 3 评论 0原文

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;  

我认为这违反了德米特定律/最少知识原则?< br> 如果是这样,如果我有大量内部类属性,我该如何解决这个问题?

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

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

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

If I call:

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

I assume this this breaks the Law of Demeter / Principle of Least Knowledge?
If so, how do I remedy this if I have a large number of inner class properties?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

假扮的天使 2024-09-05 01:41:35

我最喜欢马丁·福勒的名言之一:

我更喜欢它被称为
偶尔有用的建议
德墨忒尔

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

One of my favourite quotes from Martin Fowler:

I'd prefer it to be called the
Occasionally Useful Suggestion of
Demeter

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

琉璃梦幻 2024-09-05 01:41:35

如果您正在谈论德米特法则,“不要给邻居打电话”,您可以将其委托给其他可以完成您想要的操作的方法。

从你的例子来看,我猜你想重置性能值或其他东西。您可以修改示例代码,使它们本质上链接起来:

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 的回答 相反。

If you're talking about Law of Demeter as in, "don't call the neighbors of neighbors" you can delegate it to other methods that do what you want.

From your example I'm guessing you want to reset the performance value or something. You can modify the example code so they are chained inherently instead:

Category cat = new Category();

cat.resetPerf();

The code would be something akin to this:

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();
    }
}

That way the Category class doesn't need to know how to reset the value in case the default value is something different or it's type is changed in the future.

Personally if the risk for change is low I'd go for juharr's answer instead.

离去的眼神 2024-09-05 01:41:35
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 的直接组件对象
  • 全局变量,可在 M 范围内由 O 访问

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

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

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

is

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

So it is breaking the rules if the wikipedia definition is correct:

..[M]ethod M of an object O may only
invoke the methods of the following
kinds of objects:

  • O itself
  • M's parameters
  • any objects created/instantiated within M
  • O's direct component objects
  • a global variable, accessible by O, in the scope of M

In particular, an object should avoid invoking methods of a member object returned by another method

If you are worried about the 3 being tightly coupled, then remove the public accessors and add a method on Category to set the value. Then refactor Performance and BigPerformance to be private members.

提赋 2024-09-05 01:41:35

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

这么看

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

我如何测试性能
我不想让它自动
创建一个BigPerformance
与数据库的连接。让我们通过一个
IBigPerformance
性能并替换实际的
用假人实施
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 博客,了解在这个和其他主题上大开眼界。

If you always keep testabillity of your classes in mind and use IoC, you will notice you don't have to worry about LoD as much.

Look at it this way

How am I going to test Category? I
don't want it to automagically create
a Performance that's using the slow
filesystem. Let's pass a
IPerformance through to Category
and replace the actual implementation
with a dummy Performance instance.

How am I going to test Performance?
I don't want it to automagically
create a BigPerformance making a
connection to a database. Let's pass a
IBigPerformance through to
Performance and replace the actual
implementation with a dummy
BigPerformance instance.
...
you obviously notice the pattern

Your code would be in the line of

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.)

It looks (and in the shortrun probably is) like a lot more work but the benefits will pay off in the long run by being able to test your classes in isolation.

Take a look at Misco Hevery's blog for an eye opener on this and other subjects.

°如果伤别离去 2024-09-05 01:41:35

这并没有违反德米特法则,因为你正在使用类的公共契约。

This is not breaking the Law of Demeter, because you are using public contract of classes.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文