首先让我为这篇文章的长度道歉,但是我真的很想在前面传达尽可能多的细节,所以我不会浪费您的时间在评论中来回走动。
我正在按照DDD方法设计应用程序,并且想知道我可以遵循什么指南来确定聚合根是否应该包含另一个AR,或者是否应该将它们保留为单独的“独立” AR。
以一个简单的“时钟”应用程序为例,该应用程序允许员工在一天之内或每天进行自我计时。用户界面允许他们输入员工ID和PIN,然后对其进行验证并检索员工的当前状态。如果该员工当前正在上班,则UI会显示一个“ Clock Out”按钮。相反,如果它们没有被计时,则按钮显示为“ Clock In”。该按钮采取的操作也对应于员工的状态。
该应用程序是一个Web客户端,它调用通过RESTful服务接口公开的后端服务器。我在创建直观,易读的URL时的第一步是产生了以下两个端点:
http://myhost/employees/{id}/clockin
http://myhost/employees/{id}/clockout
注意:在验证员工ID和PIN并在标头中传递表示“用户”的“令牌”后,才使用它们。这是因为存在一种“经理模式”,允许经理或主管调入或调出另一名员工。但是,为了便于讨论,我试图使其保持简单。
在服务器上,我有一个提供API的ApplicationService。我对ClockIn方法的最初想法是:
public void ClockIn(String id)
{
var employee = EmployeeRepository.FindById(id);
if (employee == null) throw SomeException();
employee.ClockIn();
EmployeeRepository.Save();
}
这看起来很简单,直到我们意识到员工的时间卡信息实际上是作为交易列表维护的。这意味着每次调用ClockIn或ClockOut时,我不会直接更改Employee的状态,而是将新条目添加到Employee的TimeSheet中。Employee的当前状态(已计时或未计时)是从TimeSheet中的最新条目得出的。
因此,如果我使用上面显示的代码,则我的存储库必须认识到Employee的可持久属性没有更改,但是在Employee的TimeSheet中添加了新条目并执行到数据存储的插入。
另一方面(这是帖子的最终问题),TimeSheet似乎既是聚合根又具有身份(员工ID和期间),我可以轻松地实现与TimeSheet.ClockIn相同的逻辑(员工ID)。
我发现自己正在辩论这两种方法的优点,并且如开篇所述,想知道我应该评估哪种标准以确定哪种方法更适合该问题。