问题 DDD - 唯一约束的验证


在DDD中,您绝不应让您的实体进入无效状态。话虽这么说,你如何处理独特约束的验证?

创建实体不是一个真正的问题。但是,假设您有一个必须具有唯一名称的实体,并且该实体类型有一千个实例 - 它们不在内存中,而是存储在数据库中。现在假设你要重命名一个实例。

您不能只使用setter ...对象可能进入无效状态 - 您必须对数据库进行验证。

您如何在Web环境中处理此场景?


4741
2018-04-18 02:03


起源



答案:


唯一性约束可以简化为持久性异常,而不是被视为“无效状态”。在持久化对象之前,它不是无效状态。唯一性在持久性的背景下才有意义。实际上,您可以将此类规则放在验证机制中以帮助降低此错误的可能性,但在任何实际的多用户系统中,在成功的工作单元完成持久性操作之前,您无法保证唯一性。

因此,您可能需要在验证机制中使用此功能,但必须在持久层中强制执行此功能。

我一般都喜欢DDD作为一种方法论,但我认为“不允许对象进入无效状态”可能需要一些曲折的抽象。在Web应用程序中,拥有单独的“视图模型”是一种可能的解决方案,作为持久性之前的中间层,但我通常不这样做,直到我确信它会比简单的替代方案减少痛苦。


10
2018-04-18 02:17



谢谢您的回答。我非常赞同你所说的,但我想听听纯粹主义者所说的“唯一性限制可以简化为持久性异常” - 不是无效状态......而对于View模型,我几乎总是使用但是有一刻你必须使用View Model中的数据更新你的“真实”模型,你仍然会遇到同样的问题。 - W3Max
DDD不是宗教;它不仅仅是关于纯度,而是关于清晰度。就纯度而言,你会发现我的思维倾向于在大多数情况下与规范的DDD非常接近。但是,如果您确实希望在持久层之外寻求解决唯一性,可以尝试调整规范模式以满足您的需求。 - JasonTrue


答案:


唯一性约束可以简化为持久性异常,而不是被视为“无效状态”。在持久化对象之前,它不是无效状态。唯一性在持久性的背景下才有意义。实际上,您可以将此类规则放在验证机制中以帮助降低此错误的可能性,但在任何实际的多用户系统中,在成功的工作单元完成持久性操作之前,您无法保证唯一性。

因此,您可能需要在验证机制中使用此功能,但必须在持久层中强制执行此功能。

我一般都喜欢DDD作为一种方法论,但我认为“不允许对象进入无效状态”可能需要一些曲折的抽象。在Web应用程序中,拥有单独的“视图模型”是一种可能的解决方案,作为持久性之前的中间层,但我通常不这样做,直到我确信它会比简单的替代方案减少痛苦。


10
2018-04-18 02:17



谢谢您的回答。我非常赞同你所说的,但我想听听纯粹主义者所说的“唯一性限制可以简化为持久性异常” - 不是无效状态......而对于View模型,我几乎总是使用但是有一刻你必须使用View Model中的数据更新你的“真实”模型,你仍然会遇到同样的问题。 - W3Max
DDD不是宗教;它不仅仅是关于纯度,而是关于清晰度。就纯度而言,你会发现我的思维倾向于在大多数情况下与规范的DDD非常接近。但是,如果您确实希望在持久层之外寻求解决唯一性,可以尝试调整规范模式以满足您的需求。 - JasonTrue


为了找到你问题的答案,我发现了这篇文章: https://thinkbeforecoding.com/post/2009/10/28/Uniqueness-validation-in-CQRS-Architecture

实质上:查找唯一性的范围,并在表示该范围的聚合根中存储唯一值的权威列表。

例如,给定用例“在注册新用户时,所请求的登录必须是唯一的”,这将是:登录必须在租户(或公司或国家,......)中是唯一的。将有关给定登录的信息存储在代表租户的聚合根目录中的列表中。

这样您就可以确保租户永远不会进入无效状态。


0
2018-04-19 08:52