在域驱动设计中获取聚合的正确方法
Proper way to get aggregates in Domain Driven Design
在 DDD
架构中,我有一个 Order
聚合根和一个 Product
聚合。当我想将 Product
添加到特定的 Order
时,我会这样做:
class Order
{
void AddProduct(Product p)
{
this.Products = p;
}
}
然后,OrderRepository
将内存中的 Order.Products
colleciton 保存到数据库中。
我的问题是:如何为特定的 Order
获取特定的 Product
?鉴于我们不应该将存储库注入实体,我不确定如何水化内存中的 Order.Products
集合:
class Order
{
Product GetProduct(int productID)
{
return this.Products.Where(x => x.ProductID == productID);
}
}
或者这是属于 OrderRepository
的东西?
class Order
{
void AddProduct(Product p)
{
this.Products = p;
}
}
这个模型可能是错误的。
(1)如果Product
的状态需要满足Order
中的业务不变性,那么Product
应该是Order聚合中的实体,而不是单独的聚合它自己的。
另一方面,如果 Order
不需要知道任何关于 Product
的状态来满足它自己的不变量,那么 Products 集合不应该包含产品,而是其他东西(大概Id<Product>
)
提示:通过更改 Order
来编辑 Product
是否有意义?
(2) 大多数关于 Order
聚合的讨论得出的结论是该顺序持有 OrderItems
的集合(注意:不是聚合),其中每个 OrderItem
持有一个 引用 到产品集合。
购物车是 DDD 讨论中相当常见的示例案例
我知道这个问题有一个公认的答案,但我还是会给出我的意见:)
聚合根 (AR) 不应引用另一个 AR。它只会使用相关 AR 的 Id 或包含相关 AR 的 Id 以及一些可选的额外数据的值对象 (VO)。
Order
-> Product
关系的有趣之处在于它是数据库术语中典型的多对多关系。在数据库世界中,人们通常会通过创建一个名为 OrderProduct
的关联(或 link)table 来建模,并为与该关联相关的任何数据添加列,例如数量和价格.然而,不知何故,我们都使用的 table 被称为 OrderItem
或 OrderLine
。我们这样做是因为让关联更接近订单是有意义的。
我有一个博客 post 围绕这个仍然有些正确:http://www.ebenroux.co.za/design/2009/09/08/many-to-many-aggregate-roots/
在 DDD 世界中,我们 Order
不会保留对 Product
实例的对象引用列表。相反,我们将创建一个名为 OrderItem
的 VO,它仅包含 ProductId
以及 Quantity
、Price
和一个非规范化的 ProductDescription
,因为该描述可能会在之后更改订单已经下达,从历史上看,这会改变订购的内容,这将是一个禁忌。
只是一些发人深省的东西:)
在 DDD
架构中,我有一个 Order
聚合根和一个 Product
聚合。当我想将 Product
添加到特定的 Order
时,我会这样做:
class Order
{
void AddProduct(Product p)
{
this.Products = p;
}
}
然后,OrderRepository
将内存中的 Order.Products
colleciton 保存到数据库中。
我的问题是:如何为特定的 Order
获取特定的 Product
?鉴于我们不应该将存储库注入实体,我不确定如何水化内存中的 Order.Products
集合:
class Order
{
Product GetProduct(int productID)
{
return this.Products.Where(x => x.ProductID == productID);
}
}
或者这是属于 OrderRepository
的东西?
class Order
{
void AddProduct(Product p)
{
this.Products = p;
}
}
这个模型可能是错误的。
(1)如果Product
的状态需要满足Order
中的业务不变性,那么Product
应该是Order聚合中的实体,而不是单独的聚合它自己的。
另一方面,如果 Order
不需要知道任何关于 Product
的状态来满足它自己的不变量,那么 Products 集合不应该包含产品,而是其他东西(大概Id<Product>
)
提示:通过更改 Order
来编辑 Product
是否有意义?
(2) 大多数关于 Order
聚合的讨论得出的结论是该顺序持有 OrderItems
的集合(注意:不是聚合),其中每个 OrderItem
持有一个 引用 到产品集合。
购物车是 DDD 讨论中相当常见的示例案例
我知道这个问题有一个公认的答案,但我还是会给出我的意见:)
聚合根 (AR) 不应引用另一个 AR。它只会使用相关 AR 的 Id 或包含相关 AR 的 Id 以及一些可选的额外数据的值对象 (VO)。
Order
-> Product
关系的有趣之处在于它是数据库术语中典型的多对多关系。在数据库世界中,人们通常会通过创建一个名为 OrderProduct
的关联(或 link)table 来建模,并为与该关联相关的任何数据添加列,例如数量和价格.然而,不知何故,我们都使用的 table 被称为 OrderItem
或 OrderLine
。我们这样做是因为让关联更接近订单是有意义的。
我有一个博客 post 围绕这个仍然有些正确:http://www.ebenroux.co.za/design/2009/09/08/many-to-many-aggregate-roots/
在 DDD 世界中,我们 Order
不会保留对 Product
实例的对象引用列表。相反,我们将创建一个名为 OrderItem
的 VO,它仅包含 ProductId
以及 Quantity
、Price
和一个非规范化的 ProductDescription
,因为该描述可能会在之后更改订单已经下达,从历史上看,这会改变订购的内容,这将是一个禁忌。
只是一些发人深省的东西:)