在DDD中,你永远不应该让你的实体进入无效状态。话虽如此,那么如何处理唯一约束的验证呢?
创建实体并不是真正的问题。但是假设你有一个实体必须拥有唯一的名称,并且存在一千个这种实体类型的实例(它们不在内存中但存储在数据库中)。现在假设你想要重命名一个实例。
你不能只使用setter……对象可能会进入无效状态——你必须对数据库进行验证。
在Web环境中,你如何处理这种情况?
在DDD中,你永远不应该让你的实体进入无效状态。话虽如此,那么如何处理唯一约束的验证呢?
创建实体并不是真正的问题。但是假设你有一个实体必须拥有唯一的名称,并且存在一千个这种实体类型的实例(它们不在内存中但存储在数据库中)。现在假设你想要重命名一个实例。
你不能只使用setter……对象可能会进入无效状态——你必须对数据库进行验证。
在Web环境中,你如何处理这种情况?
唯一性约束可以转化为持久性异常,而不是被视为"无效状态"。除非对象被持久化,否则它不是无效状态。唯一性只在持久性的情况下才有意义。现实情况是,在验证机制中加入此类规则可以帮助减少此错误的可能性,但在任何实际的多用户系统中,直到成功完成持久性操作,您不能保证唯一性。
因此,您可能希望在您的验证机制中使用这种规则,但必须在持久层中执行。
我通常支持DDD作为一种方法论,但我认为“不允许对象进入无效状态”可能需要一些繁琐的抽象。在Web应用程序中,拥有一个单独的“View Model”是一种可能的解决方案,作为持久化之前的中介层,但我通常不会这样做,除非我确信它会给我带来比更简单的选择更少的痛苦。
在寻找答案时,我找到了这篇文章:https://thinkbeforecoding.com/post/2009/10/28/Uniqueness-validation-in-CQRS-Architecture。
简而言之:寻找唯一性的范围,并在代表该范围的聚合根中存储唯一值的权威列表。
例如,对于用例“当注册新用户时,所请求的登录必须是唯一的”,这将是:登录必须在租户(或公司、国家等)内是唯一的。在代表租户的聚合根中存储有关给定登录的信息。
通过这种方式,可以确保租户永远不会进入无效状态。