在看过Jimmy Bogard的优秀video on crafting wicked domains后,我尝试将同样的原则应用于我现有的一个项目,以评估我对这个概念的掌握程度。我对下面列出了疑问和怀疑。
域背景:管理员可以查看公司列表。然后他批准了一家公司。数据库应该将布尔字段更新为true并存储批准公司的用户的ID。
最初,我在服务层中编写了以下代码。它将请求传递给存储库,存储库更新db中的相应字段,然后发送邮件通知。
public void ApproveCompany(int companyId, int userId)
{
_companyRep.ApproveCompany(companyId, userId);
//send mail to company representatives on successful approval.
}
为了创建丰富的域并在域类中封装逻辑,我创建了以下内容。
public void ApproveCompany(int companyId, int userId)
{
var user = _userRep.GetById(userId);
var company = _companyRep.GetById(companyId);
user.Approve(company);
_companyRep.Insert(c);
//send mail to company representatives on successful approval.
}
public class AdminUser
{
public string Name { get; set; }
public void Approve(MyApprovedCompany c)
{
c.SetIsApproved(this);
}
}
public class Company
{
public bool IsApproved { get; private set; }
public AdminUser ApprovedBy { get; private set; }
public void SetIsApproved(AdminUser user)
{
if (this.IsApproved)
throw new Exception("This company has already been approved by user: " + user.Name);
this.IsApproved = true;
this.ApprovedBy = user;
}
}
查询:
或者,我可以编写如下的服务层,但我认为这也不正确。
public void ApproveCompany(int companyId, int userId)
{
var user = _userRep.GetById(userId);
var company = _companyRep.GetById(companyId);
if(company.IsApproved)
{
throw new Exception("This company has already been approved by user: " + _userRep.GetById(company.ApprovedUserId).Name);
}
else
{
user.Approve(company);
_companyRep.Insert(c);
}
}
答案 0 :(得分:2)
这些问题几乎不可能正确回答,但是我可以从我看到的内容中告诉你:
这有些正确,但我通常倾向于在操作所针对的AR上放置行为而不是执行它的actor。在这种情况下,双重调度并没有带来任何有用的恕我直言。因此,我会简化为company.Approve(adminUser)
。您可能会说adminUser.approve(Company)
更好地反映了一个用例,例如"管理员用户批准公司",但您可以转过身来说“#34;公司是由管理员批准的用户&#34 ;.另请注意,您拥有的company.SetIsApproved
方法非常注重CRUD,当然也不能很好地反映您无处不在的语言。
AR应设计得尽可能小。只要您不创建不必要的大型群集聚合,我就不会发现这会成为一个问题。我强烈建议您阅读Effective Aggregate Design by Vaughn Vernon。
理想情况下,您应该依靠域事件来实现操作的副作用。有很多关于如何在Web上实现域事件的信息。但是,由于缺少发布/订阅机制,可以在应用程序服务层完成,也可以在AR方法级别注入邮件服务。
问题是您在另一个AR中引用了AR。 AR通常应通过身份引用其他AR。因此,Company
不会保留AdminUser
,只能保留用户的ID。通过这样做,您的问题就会消失,并减少AR的大小。