德米特法则混淆

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

例如

public class Company { // company has a number of employees public List 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 } 

假设我有一个正在访问公司类的客户端,如果它违反了得墨忒耳的法则,就像是。

 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有什么问题吗?

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

谢谢

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

由于德米特定律基本上只是说“只谈你所知道的事情”……无论“客户”在第一个场景中是什么,实际上根本不了解员工。 它了解Company ……但不了解Company内部的复杂情况。

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

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

将它包装在Company会使未来处理得更好(无论是否遵循Demeter法则)。

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

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