DDD,在有界上下文中让多个聚合根共享相同的身份是否可以
DDD, Is it ok to have multiple aggregate root shared same identity in bounded context
在有界上下文中有很多像这样的聚合根可以吗
Product
ProductID : GUID
Name : string
Price : float
ProductPromotion
ProductID : GUID
Discounted : float
ProductShortName
ProductID : GUID
ShortName : string
我不知道它会打破有界上下文的规则,因为这些是不同种类的产品,但在上下文中。
每个聚合根在 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 的引用)。
您不应该做的(而且看起来您没有做的)是在另一个内部持有对整个聚合的完整引用。
但是,在设计聚合时,您应该始终反思您的目标是什么。是的,它们应该很小,但它们也必须传达一个 objective。通常它们旨在强制执行某些不变量,而这些示例似乎并未实现该目标。
也许你的例子对于这个问题过于简化了,我无法真正评估它,但在我看来 "ProductPromotion" 和 "ProductShortName" 并不是完全聚合的好候选者他们被呈现。
我已经在两个不同的应用程序中使用了 "pattern",而且效果很好。
我认为如果你的聚合内部有一个状态(它的所有属性),让你检查它可以工作的命令的所有不变量。
如果要在聚合的命令方法内进行验证,您需要将 属性 存储在另一个聚合方法中,就会出现问题。
在另一个回复中,我读到每个聚合都有一个唯一的 ID,在这种情况下,聚合的 id 可以看作是 (AggregateType, GUID)
.
最后,您只是将单个聚合存储在多个分区中,作为 consistency/transactions 边界的聚合,直到您的命令修改了使用原子操作存储的单个部分,您的聚合才不会违反任何规则。
为了了解它是否适合您的问题,您还必须检查这些聚合是如何读取的,因为如果您需要读取整个聚合状态,根据持久性技术,您最终可能会对存储进行多次查询以检索所有这些都会降低性能,这可以接受也可以不接受,具体取决于您的用例(在我的例子中,一个是使用事件源开发的,所以读取模型是一个单一的读取操作,在第二个中有一些缓存帮助还做了多个查询,性能还可以。
在有界上下文中有很多像这样的聚合根可以吗
Product
ProductID : GUID
Name : string
Price : float
ProductPromotion
ProductID : GUID
Discounted : float
ProductShortName
ProductID : GUID
ShortName : string
我不知道它会打破有界上下文的规则,因为这些是不同种类的产品,但在上下文中。
每个聚合根在 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 的引用)。
您不应该做的(而且看起来您没有做的)是在另一个内部持有对整个聚合的完整引用。
但是,在设计聚合时,您应该始终反思您的目标是什么。是的,它们应该很小,但它们也必须传达一个 objective。通常它们旨在强制执行某些不变量,而这些示例似乎并未实现该目标。
也许你的例子对于这个问题过于简化了,我无法真正评估它,但在我看来 "ProductPromotion" 和 "ProductShortName" 并不是完全聚合的好候选者他们被呈现。
我已经在两个不同的应用程序中使用了 "pattern",而且效果很好。
我认为如果你的聚合内部有一个状态(它的所有属性),让你检查它可以工作的命令的所有不变量。
如果要在聚合的命令方法内进行验证,您需要将 属性 存储在另一个聚合方法中,就会出现问题。
在另一个回复中,我读到每个聚合都有一个唯一的 ID,在这种情况下,聚合的 id 可以看作是 (AggregateType, GUID)
.
最后,您只是将单个聚合存储在多个分区中,作为 consistency/transactions 边界的聚合,直到您的命令修改了使用原子操作存储的单个部分,您的聚合才不会违反任何规则。
为了了解它是否适合您的问题,您还必须检查这些聚合是如何读取的,因为如果您需要读取整个聚合状态,根据持久性技术,您最终可能会对存储进行多次查询以检索所有这些都会降低性能,这可以接受也可以不接受,具体取决于您的用例(在我的例子中,一个是使用事件源开发的,所以读取模型是一个单一的读取操作,在第二个中有一些缓存帮助还做了多个查询,性能还可以。