DDD实体验证

Mar*_*kus 8 validation domain-driven-design

我有一个与实体验证有关的问题.作为一个例子,有一个User可以注册到给定的系统emailpassword.业务规则说:

  1. email 必须有效(必须符合电子邮件格式)和独特;
  2. password 应该在6到20个字符之间.

我最初的想法是将验证置于其中User.Register(email, password).这种方法的主要优点User是通过验证注册数据的正确性来控制注册方式.缺点是电子邮件唯一性验证需要调用UserRepository,因此User可能依赖于它Repository.要解决此问题,可能会对某些BusinessRule对象进行电子邮件和密码验证.所以User.Register()方法中的验证可能如下所示:

var emailValidationErrors = _emailRule.Validate(email);
var passwordValidationErrors = _passwordRule.Validate(password);
Run Code Online (Sandbox Code Playgroud)

where _emailRule_passwordRule可能作为构造函数参数传递:User(EmailRule emailRule, PasswordRule passwordRule).

在这个casse User不直接耦合UserRepository.通过这种方式,规则在域中明确显示,这使其更具表现力.

所以问题是:你对这种方法有什么看法?还有其他解决方案吗?

小智 1

马库斯,

他的做法还不错,但我只是做法不同。

在我看来,您尊重 OCP,将验证规则置于实体之外,这是明智的决定。在类构造函数中使用这些验证规则,您表明这些规则是不可变的,对吧?

我不会这样做,只需创建一个方法二元组,将规则设置为此构造函数。对我来说,不清楚如果违反验证规则会发生什么。我喜欢向用户界面抛出异常,以处理更普遍的警告。

我不清楚的另一件事是触发此验证的事件。当实体 User 添加到存储库或实体的方法可以执行此操作时?我将采用第二个选项,调用 isValidAuthentication() 方法并抛出异常。

关于实体对存储库的依赖,我斗胆说这是错误的。你甚至可以让实体依赖于他,因为存储库是对象的集合,这有什么问题吗?然而,在这一点上,验证似乎很清楚是一项服务。因此,如果我们将这些验证放入服务中,就会消除这种耦合并再次应用 OCP。你同意?

一个大大的拥抱和成功!