【问题标题】:Should an aggregate root's behaviour be dependent on other aggregate root's attributes?聚合根的行为是否应该依赖于其他聚合根的属性?
【发布时间】:2014-01-15 20:37:51
【问题描述】:

我正在阅读一本关于 DDD 的书,我看到了一个涉及汽车、发动机、车轮和轮胎的示例域。

上面是书中的模型。客户也是聚合根。
有了这个模型,引擎可能会有高度、宽度和长度属性。
当您需要在小型汽车上安装大型发动机时会发生什么?引擎无法安装。
如果汽车检查引擎属性并允许它成为汽车的一部分,这是否有问题?
该引擎具有全球标识(就像您知道每个引擎都有一个序列号/制造商编号)。也许发动机需要由制造商跟踪。

所以我再次问,如果汽车使用引擎的属性将其装入内部(允许或不成为其中的一部分),这是否有问题?

【问题讨论】:

    标签: oop architecture domain-driven-design aggregation


    【解决方案1】:

    来自 DDD 书,第 128 页:

    任何跨越 AGGREGATES 的规则都不会一直是最新的。通过事件处理、批处理或其他更新机制,可以在特定时间内解决其他依赖关系。

    所以,这真的取决于 Car 聚合的用途:如果它需要与 Engine 的强一致性,那么 Engine 应该是 Car 聚合的一部分。 否则,如果它只需要“最终一致性”,您可以将该验证逻辑放在域事件中。

    查看这个 Udi Dahan 的 post

    【讨论】:

      【解决方案2】:

      如果汽车检查引擎属性并允许它成为汽车的一部分,是否有问题?

      没有。

      话虽如此,您的验证可能已经复杂到足以引入域服务。由于涉及到两个聚合,您可以这样:

      car.Fit(engine)
      

      或者这个:

      engine.Fit(car)
      

      但是,您可能还是想检查汽车型号:)

      由于规则会更高级并涉及一些数据,您可能想要引入域服务并可能对对象使用双重调度:

      所以你可以有这个而不是car.Fit(engine)

      car.Fit(engine, IModelServiceImplementation)
      

      并在Fit方法调用中:

      if (!IModelServiceImplementation.CanFit(car, engine)) { throw new Exception(); }
      

      该服务可能会加载正确的模型,而是根据引擎进行检查。根据领域的不同,甚至可能需要处理修改级别和其他规则。

      由于Car 实例不包含实际的Engine 实例,而仅包含EngineId 或某些值对象,因此不会将引擎真正分配给汽车。您仍然可以将引擎实例传递给汽车并让它创建它认为合适的关联。

      “Enrico S.”提出的解决方案可能与更改影响聚合根的场景更相关,在这种情况下,可能没有所有聚合根可用,甚至聚合根存在于单独的有界上下文中。即使CarEngine 位于不同的BC 中,也可能能够以某种方式查询有效性。有些事情对于最终的一致性来说是可以的,但有些事情可能不是。

      像往常一样,有很多事情要考虑:)

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2014-04-22
        • 2011-01-16
        • 1970-01-01
        • 1970-01-01
        • 2012-10-03
        • 2018-02-06
        • 1970-01-01
        相关资源
        最近更新 更多