Chr*_*ris 5 c# domain-driven-design
我的编程语言是C#.我在域模型中有一个关于持久性无知的问题.
我们假设我有一个这样的人类:
public class Person
{
private string email;
public string Email
{
get { return email; }
set { email = value; }
}
public Person(string email)
{
this.email = email;
}
}
Run Code Online (Sandbox Code Playgroud)
现在,在我的域模型中,有一条规则,即不能有两个人拥有相同的电子邮件地址.因此,在实例化新人时,需要验证以及更改电子邮件属性时.所以我想知道如何在持久性无知域层中解决这样的验证.我目前所做的是使用工厂模式进行人员实例化,我在其中注入人员存储库.在那里,我可以搜索具有相同电子邮件地址的其他人.像这样:
public class PersonFactory
{
private static readonly IPersonRepository personRepository;
public Person CreateNewPerson(string email)
{
Person personWithSameMail = personRepository.GetPersonByEmail(email);
if (personWithSameMail != null)
throw new ApplicationException("Email already exists.");
return new Person(email);
}
public PersonFactory(IPersonRepository personRepository)
{
this.personRepository = personRepository;
}
}
Run Code Online (Sandbox Code Playgroud)
但是,使用此解决方案时,更改人员电子邮件地址(可能是有效的业务案例)时的检查仍未涵盖.此外,Person类仍然公开了一个公共构造函数,并且绕过工厂,仍然可以使用具有重复电子邮件地址的人员.
任何一个解决这个问题的解决方案?
PS对所有以数据为中心的人:不,我不想在数据访问层验证欺骗电子邮件;)
更新:
无论如何,整个问题可能已经过时了.根据域模型上下文检查重复的电子邮件总是需要知道所有人的"某事" - 根."某事"可以是地址簿,也可以是包含所有具有电子邮件地址的人的整个世界.所以也许我正在混淆程序员需要技术上优雅的问题解决方案,这只是因为缺乏一个完整且经过深思熟虑的领域模型.这可以是这种情况吗?不仅仅有一个人在太空中漂浮着一个电子邮件地址(嘿,空间将是我在这里的聚合根;))只是为了存在的乐趣?但是,如果这是一个真实的商业案例,如地址簿应用程序,地址簿将是人的集合根,因此可以检查其内部集合中的所有人,以确保没有重复的电子邮件地址.
我不是 DDD 专家,但我对此的看法是这样的。
首先,对我来说,您的设计中最大的缺陷是允许实体上的设置者。这意味着您可以在聚合根不知道的情况下更改实体的状态。我会重构它,删除设置器,并在对象创建时通过构造函数设置它。
还有一点。个人实体不应该对电子邮件进行验证(以检查电子邮件是否已使用的形式),因为如果她是聚合的根,它只能知道自己的状态和相关的子实体。然后你应该从实体中引用存储库,这对我来说是糟糕的设计。我想这就是你使用工厂的原因。
我认为验证应该首先在 UI 中进行,以便尽快失败。但这还不够。当保留您的域状态时,您应该强制执行此人拥有唯一电子邮件的规则。我认为验证应该发生在域服务中,例如名为PersonRegistrationService 的域服务,该服务将引用IPersonRepository,并且在将人员实体添加到其集合中进行持久化之前,它会首先检查人员电子邮件是否唯一。如果不是,我会通知用户错误并且不添加实体。
你怎么认为 ?