看到吉米博加德的优秀video on crafting wicked domains,我试图将相同的原则应用于我现有的项目之一,以评估我如何很好地理解了这个概念。我有以下列出的疑问和疑问。领域建模:做正确
域名后台:管理员可以查看公司列表。然后他批准一家公司。数据库应该将布尔字段更新为true并存储批准公司的用户的ID。
最初,我在我的服务层中编写了以下代码。它将请求传递给更新数据库中相应字段的存储库,然后发送邮件通知。
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);
}
}
虽然你的问题不适合SO,下面是一些提示:当你调出存储在db中的东西时,那不是DDD。存储库仅保存/加载持久化对象。你不“创造丰富的领域”,一个领域要么富有,要么不富有。 “管理员可以查看”是用户界面关注的问题。 “管理员可以批准”是一项业务规则。适当的建模始于识别**概念**和它们的**使用案例**。 DDD没有“正确”或“错误”的方式,只是正确理解域和DDD模式。 – MikeSW
@MikeSW说的另外一件事是掌握域事件。吉米的演讲没有解决这个问题,但这是什么可以启动您的电子邮件通知。 – Marco