德米特法则混淆

时间:2014-04-10 22:18:57

标签: c# aggregate law-of-demeter

我希望有人可以帮我解释一下demeter法则。如果我有一个我认为是聚合根的类,并且其中有一个子类集合,那么通过聚合根访问它们来更新这些子类的属性是不合法的吗?

e.g。

public class Company
{
    // company has a number of employees
    public List<Employee> Employees {get; set;}
}

public class Employee
{
    // each employee has a lastname
    public int Id {get; set;}
    public string LastName {get; set;}
    // other properties of employee
}

假设我有一个正在访问公司类的客户端,如果它违反了demeter定律,那就像是。

Employee e = aCompany.Employees.Where(e => e.Id == 1).Single();
e.LastName = "MarriedName";

或者是否应始终委托给公司

public class Company
{
    public UpdateEmployeeLastName(int employeeId, string newName)
    {
        Employee e = Employees.Where(e => e.Id == employeeId).Single();
        e.LastName = newName;
    }
}

在客户端

aCompany.UpdateEmployeeLastName(1, "Marriedname");

第二个似乎更好但是客户端有什么问题需要知道它想要更新的员工的ID吗?

在你有许多嵌套聚合的地方,这似乎开始变得复杂。

由于

1 个答案:

答案 0 :(得分:5)

你的第二个选择是德米特法则的目标。

因为得墨忒耳法律基本上只说明了你所知道的事情,而不管客户是什么&#34;在第一个场景中根本不了解员工。它知道Company ..但不知道Company内部的复杂性。

委派给Company,您可以灵活地更改员工的更新方式,而无需从客户端更改此功能的每个特定实例。如果有一天您决定只有Active名员工可以更改其名称,那么您必须更新第一选项的每个实例:

Employee e = aCompany.Employees.Where(e => e.Id == 1 && e.IsActive).Single();
//                                                        ^^^^ active flag
e.LastName = "MarriedName";

Company中将其包装起来,使得未来处理得更好(无论是否尝试遵守得墨忒耳定律)。

  

第二个似乎更好但是客户端有什么问题需要知道它想要更新的员工的ID吗?

你的两个例子都知道员工的身份证明......所以我不确定你的意思。在通过聚合传递信息时,消耗代码以识别ID是很常见的。