请考虑我们正在为人力资源相关的应用程序构建工作,在这里我们需要建模关于部门和员工的域对象。我想知道域对象是否应该用嵌套聚合建模,特别是嵌套在自身中。
我试图考虑两种不同的风格,如下所示:
解决方案#01,使用嵌套聚合模拟员工。
public class Employee : BusinessObject, IEmployee
{
IList<IEmployee> ManagedStaffs { get; set;}
IEmployee Supervisor { get; set;}
}
因此我们可以将其用作:
var emp = empRepository.Get(1);
// dot accessors
var numberOfPeople = emp.Supervisor.ManagedStaffs[0].ManagedStaffs.Count;
解决方案#2,没有嵌套聚合的模型员工。
public class Employee : BusinessObject, IEmployee
{
//without nested aggregate
}
public class Supervisor : Employee, ISupervisor
{
IList<IEmployee> ManagedStaffs { get; set; }
}
因此我们可以将其用作:
var emp1 = empRepository.Get(1);
// GetManagedStaffs needs a parameter which is a ISupervisor
var empList1 = empRepository.GetManagedStaffs(emp1.Supervisor);
var empList2 = empRepository.GetManagedStaffs(empList[0]);
var numberOfPeople = empList2.Count;
如果我们想要在没有ORM的情况下持久化域对象,只需要纯ADO.NET,解决方案#2看起来要好得多。
如果我们想在解决方案#1中使用点访问器,则需要引入透明的ORM框架,并且由于递归嵌套聚合而欢迎延迟加载。
我认为确定哪一个是更好的解决方案的关键点在于如何处理嵌套聚合。
我可以提出你的建议吗?或者我有需要纠正的事情?
感谢。
答案 0 :(得分:3)
第二种解决方案要好得多。
起初聚合应该很小。通常并非所有操作都需要所有聚合组件。如果聚合将很大 - 它的所有部分都将被加载到内存中,那么为这样的聚合实现持久性逻辑将更加困难,对数据库的查询将更加复杂(显然,持久性操作会对大型聚合产生巨大的性能影响)。您希望通过ORM的延迟加载功能来缓解这些影响,但延迟加载需要更多的关注和控制 - 您应该确切知道加载的内容和时间。同样从性能的角度来看,最好通过单个查询加载所有聚合,而不是像延迟加载那样加载几个查询。
其次,第一个场景的使用违反了得墨忒耳定律(https://en.wikipedia.org/wiki/Law_of_Demeter)。从这一点开始,#2场景的使用更加清晰。
答案 1 :(得分:0)
#Solution 2很不错。主管和员工之间有一种很好的“是 - a”关系。但这种关系将在未来引入耦合问题。你改变员工我担心主管也会受到影响。另一种解决方案可能是支持“组合而不是继承”以及#solution 1.决定是你的