德米特法则混淆

mag*_*ets 2 c# aggregate law-of-demeter

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

例如

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
}
Run Code Online (Sandbox Code Playgroud)

假设我有一个客户端正在访问公司类,首先它会违反demeter法则.

Employee e = aCompany.Employees.Where(e => e.Id == 1).Single();
e.LastName = "MarriedName";
Run Code Online (Sandbox Code Playgroud)

或者这应该总是委托给公司

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

在客户端

aCompany.UpdateEmployeeLastName(1, "Marriedname");
Run Code Online (Sandbox Code Playgroud)

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

这似乎可能会开始变得复杂,你有许多嵌套聚合.

谢谢

Sim*_*ead 5

您的第二个选择是德米特法则的目标.

因为德米特定律基本上只是说"只谈你所知道的事情"......无论"客户"在第一个场景中是什么,实际上根本不了解员工.它知道Company...而不是Company内部的复杂性.

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

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

把它包装起来Company使得将来更好地处理(无论是否试图遵循得墨忒耳定律).

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

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