【问题标题】:DDD – How to implement validation against databaseDDD – 如何对数据库实施验证
【发布时间】:2021-10-18 11:42:04
【问题描述】:

我正在努力解决一个基本问题。该项目使用 C#,但问题很普遍。

我遵循始终有效的对象原则。作为一个示例,我有一个具有强制性属性“ProductCategory”的产品实体。允许的产品类别是用户定义的,因此是持久的(在数据库中)。

为了类型安全和更好的阅读,我为各种属性定义了值对象来封装这些类型的业务规则。所以有一个 ProductCategory 类。创建 ProductCategory 实例时,工厂方法会检查例如在创建实例之前传递给工厂的字符串的最大长度。这确保了 ProdcutCategory 的每个实例都是有效的。

像长度这样的简单参数检查非常简单直接。我的问题是在哪里对保留的可能值实施验证检查。允许值的存储库隐藏了持久性技术并具有 Exists 或 IsValid 方法。

选项 1) 在调用工厂之前从应用层调用存储库。

这里的领域层没有像许多人提倡的那样依赖于存储库/基础设施层。但是工厂不能再确保一个有效的对象了。业务规则的实现取决于应用层。此外,每个需要 ProductCategory 的命令都必须检查存储库,这违反了 DRY。

选项 2) 从值对象工厂调用存储库

由于工厂是域层的一部分,因此该层必须有权访问存储库,这会引入额外的耦合。好处是ProductCategory的业务有效性是由对象本身保证的,无法规避。

对于这种困境是否有其他解决方案,或者是否有任何特定标准可以鼓励一种或另一种选择? 如果工厂是针对存储在域层中并且仅由基础设施层中的存储库实现的存储库接口进行编程的,是否可以? 我试图理解不同的方法,但在这种情况下我感到迷茫。

【问题讨论】:

    标签: c# validation domain-driven-design ddd-repositories user-defined


    【解决方案1】:

    如果我理解正确,您的 ProductCategory 值对象会处理其自身的不变量,但是否可以将特定 ProductCategory 分配给特定 Product 是用户定义并存储在数据库中的。

    您可以使用 DomainEvents:

    1. 您将类别分配给域模型中的产品。
    2. 产品添加了一个域事件“ProductCategoryAssigned”。
    3. 在提交您的工作单元之前,DomainEvent 处理程序会检查数据库是否可以将特定类别分配给产品,如果没有则抛出。

    这将防止交易以无效状态完成。

    您可以使用 ValidatorAggregate:

    如果您真的希望您的产品“始终有效”,甚至在工作单元提交之前,那么您可以选择:

    1. 创建一个 ValidCategoriesAggregate 和存储库,用于根据产品属性加载有效类别。
    2. 您的产品的“SetCategory”方法(或工厂方法)将 ValidCategoriesAggregate 声明为必需参数,从而强制您的应用程序层在调用工厂方法之前获取一个。
    3. 在您的工厂方法中,您可以调用“ValidCategoriesAggregate.HasCategory(category)”并在创建产品之前抛出(如果不存在)。

    尽量避免将存储库注入到您的域模型中。

    【讨论】:

    • 在域事件选项的情况下,检查应该在进程中并且同步?
    • 使用 ValidatorAggregate,如果在您的存储库加载 ValidCategoriesAggregate 之后创建(提交/存储)相同的类别会发生什么?
    • @deezg ... 是的,如果您有将命令传递给应用层命令处理程序的基础设施,那么它可以枚举和处理域事件(在处理命令)在进程中,并在提交工作单元之前将它们发送到事件处理程序。
    【解决方案2】:

    选项 2 似乎更好。
    在这种情况下,耦合不是问题,您将工厂耦合到检查验证所需的查询,使这种依赖关系显式化。

    请注意,使此检查最终保持一致的唯一方法是将所有数据放在一个聚合中。否则,无法阻止在您进行检查之后和提交事务之前创建相同类别的事实(这是聚合的真正原因)。

    只有在存在真正问题时才考虑最终一致性,创建类别的频率如何?多久创建一次产品?发生冲突的可能性有多大?如果发生这种情况,会有什么真正的问题吗?

    在大多数情况下,完全一致比接受最终一致性要昂贵得多。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-04-09
      • 1970-01-01
      • 1970-01-01
      • 2019-02-05
      • 1970-01-01
      相关资源
      最近更新 更多