【问题标题】:DDD, Is it ok to have multiple aggregate root shared same identity in bounded contextDDD,是否可以在有界上下文中让多个聚合根共享相同的身份
【发布时间】:2018-06-21 16:42:49
【问题描述】:

在有界上下文中是否可以有许多这样的聚合根

Product
   ProductID : GUID
   Name : string
   Price : float

ProductPromotion
   ProductID : GUID
   Discounted : float

ProductShortName
   ProductID : GUID
   ShortName : string

我不知道它会打破有界上下文的规则,虽然这些是不同类型的产品,但在一个上下文中。

link to my actual problem

【问题讨论】:

  • 我已经编辑了这个问题。最后一个问题是我真正需要的东西。但如果我这样设计,它可能会通过仅使用域设计来解决问题。
  • 根据以前的版本回答。将检查新的。
  • @PedroGoes 我在 se stackexchange 上问过。你可以在那里回答:) softwareengineering.stackexchange.com/questions/372857/…

标签: domain-driven-design aggregateroot bounded-contexts


【解决方案1】:

在 DDD 场景中,每个聚合根都应该有自己的唯一 ID,而这似乎是缺失的(如果我正确理解您的场景,您似乎希望所有 3 个类都是根)。所以,如果你的设计是这样的:

Product <ROOT>
   ProductID : GUID
   Name : string
   Price : float

ProductPromotion <ROOT>
   PromotionID: GUID
   ProductID : GUID
   Discounted : float

ProductShortName <ROOT>
   NameID: GUID
   ProductID : GUID
   ShortName : string

就其本身而言,这种设计不会损害聚合或限界上下文原则。应该允许一个聚合持有对另一个聚合根的 id 的引用(如在无数购物车示例中 LineItem 持有对 ProductID 的引用)。

你不应该做的(看起来你没有做的)是在另一个内部持有对整个聚合的完整引用。

但是,在设计聚合时,您应该始终思考您的目标是什么。是的,它们应该很小,但它们也必须传达一个目标。通常它们旨在强制执行某些不变量,而这些示例似乎并没有实现该目标。

也许你的例子对于这个问题来说过于简化了,我无法真正评估它,但在我看来,“ProductPromotion”和“ProductShortName”似乎不是它们呈现方式的完整聚合的良好候选者。

【讨论】:

  • 一般来说,如果我设计我不会让这些聚合根在同一个有界上下文中。不好吗?
  • 但也通过你提到的方式,我不能使用promotionID引用promotionID,这是必需的,因为所有这些逻辑都发生在流程管理器中,不利于从读取模型中查询:*(
  • 为什么它们不在同一个有界上下文中?看起来他们应该是。
  • 我认为此时最好的做法是重新设计聚合。很明显,他们目前没有帮助您实现域规则。您有几个难以在评论中解释的选项,但我将删除其中的一些:(1)您可以使您的产品成为促销聚合的工厂,并确保promotionID 在创建时与productID 匹配。 (2) 看起来你最好有一个“定价”聚合,它集中了产品的所有价格+折扣逻辑(包括主动折扣、临时折扣等)。
  • (3) 您可以通过读取模型找到促销,始终注意读取模型可能已过时并且最终保持一致。
【解决方案2】:

我已经在两个不同的应用程序中使用了该“模式”,并且效果很好。
我认为,如果您的聚合内部有一个状态(其所有属性),可以让您检查它可以工作的命令的所有不变量。
如果要在聚合的命令方法中进行验证,您需要将一个属性存储在另一个聚合中,则会出现问题。
在另一个回复中,我读到每个聚合都有一个唯一 ID,在这种情况下,聚合的 ID 可以视为 (AggregateType, GUID)
最后,您只是将单个聚合存储在多个分区中,作为一致性/事务边界的聚合,直到您的命令修改使用原子操作存储的单个部分,您的聚合不会违反任何规则。
为了了解它是否适​​合您的问题,您还必须检查这些聚合的读取方式,因为如果您需要读取整个聚合状态,取决于持久性技术,您最终可能会对存储进行多个查询来检索所有这些都会降低性能,这可以接受也可以不接受,具体取决于您的用例(在我的情况下,一个是使用事件源开发的,所以读取模型是单次读取操作,第二个是带有一些缓存的帮助还进行多个查询,性能还可以)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-07-28
    • 1970-01-01
    • 1970-01-01
    • 2014-08-22
    • 1970-01-01
    • 2015-04-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多