我应该在哪里对DDD进行独特的检查?

我正在研究我的第一个DDD项目,我想我了解实体,数据访问对象及其关系的基本角色。 我有一个基本的validation实现,它将每个validation规则与其关联的实体一起存储。 这适用于仅适用于当前实体的规则,但在需要其他数据时会崩溃。 例如,如果我有一个用户名必须唯一的限制,我希望IsValid()调用在存在具有当前名称的现有用户时返回false。

但是,我没有找到任何干净的方法来保持实体本身的validation规则。 我想在实体上有一个IsNameUnique函数,但是大多数执行此操作的解决方案都需要我注入一个用户数据访问对象。 这个逻辑应该在外部服务吗? 如果是这样,我如何仍然保持与实体本身的逻辑? 或者这是应该在用户实体之外的东西?

谢谢!

我喜欢塞缪尔的回应,但为了简单起见,我建议实施规范 。 您创建一个返回布尔值的规范,以查看对象是否满足特定条件。 将IUs​​erRepository注入规范,检查用户是否已存在该名称,并返回布尔结果。

public interface ISpecification { bool IsSatisfiedBy(TEntity entity); } public class UniqueUsernameSpecification : ISpecification { private readonly IUserRepository _userRepository; public UniqueUsernameSpecification(IUserRepository userRepository) { _userRepository = userRepository; } public bool IsSatisfiedBy(User user) { User foundUser = _userRepository.FindUserByUsername(user.Username); return foundUser == null; } } //App code User newUser; // ... registration stuff... var userRepository = new UserRepository(); var uniqueUserSpec = new UniqueUsernameSpecification(userRepository); if (uniqueUserSpec.IsSatisfiedBy(newUser)) { // proceed } 

在DDD中,有一个叫做聚合的概念。 它基本上负责应用程序内的一致性。

恕我直言,在这种情况下具体来说,我猜CustomerRepository会在类似“客户聚合”的内部,而Customer类是聚合根。

然后,root将负责执行所有这些操作,并且没有其他人可以访问CustomerRepository选项。 还有一些可能性:

  • 如果名称不唯一(Customer会捕获并返回错误,或类似的东西),CustomerRepository可能会抛出exception
  • CustomerRepository可以有一个IsValidUserName(),Customer在执行任何其他操作之前会调用它
  • 你能想到的任何其他选择

我要说这完全超出了DDD的范围。

你对DDD的看法是产生有用模型的事件集合。 但是,这些模型之间的数据关系不一定是可能的。

你使用什么一致性模型?

如果您可以在ACID事务中提交多个事件,则可以确保对一组聚合的更改以primefaces方式发生。

如果您使用最终一致性模型,则可能无法在以后实际validation这些内容。 当你这样做时,你可能需要补偿已经发生但不再有效的事情。

必须在上下文中回答唯一性。 如果模型很小(数千个),则可以使用聚合表示要使其唯一的值集。 假设可以进行组聚合事务。

如果没有,那么您只需将模型投影到支持唯一性约束的数据库。 如果此投影失败,您必须返回到聚合,并以某种方式将其标记为无效。 你需要考虑失败。 这是分布式长时间运行的过程,如saga模式可能有用,但也需要您考虑其他事情。

总之,如果您不能使用具有强一致性的存储模型,那么一切都会变得复杂得多。 也就是说,在分布式环境中管理故障有很好的,完整的模式,但它会把问题转移到它的头上,因为现在你需要考虑故障,在整个过程中的每一点,这是一件好事,但它将需要更多的时间投资。