Domain driven design 正确设计聚合根

Domain driven design 正确设计聚合根,domain-driven-design,aggregate,Domain Driven Design,Aggregate,我在设计聚合根时遇到一些问题。以下是我的想法:) 基于此,我的聚合根将是存储。然而,如果我现在围绕它创建一个存储库,它会像这样吗 public class StoreRepository() { Store GetById() {...} StoreZone GetZone() {...} List<StoreZoneStyle> GetStylesByZone() {...} List<Color> GetColorsByStyle() {...} }

我在设计聚合根时遇到一些问题。以下是我的想法:)

基于此,我的聚合根将是存储。然而,如果我现在围绕它创建一个存储库,它会像这样吗

public class StoreRepository()
{
  Store GetById() {...}
  StoreZone GetZone() {...}
  List<StoreZoneStyle> GetStylesByZone() {...}
  List<Color> GetColorsByStyle() {...}
}
public类StoreRepository()
{
存储GetById(){…}
StoreZone GetZone(){…}
列出GetStylesByZone(){…}
列出GetColorsByStyle(){…}
}
这是继续下去的好办法吗? 不用说,我是DDD新手。

似乎“Store”不是聚合根,因为您不想在“Store”对象后面隐藏“Zones”、“Sales”等的所有功能。这样,“存储”对象可能会非常臃肿


“商店”、“区域”和“销售”可以有自己的存储库

我认为您需要将聚合边界和实体看作不仅仅是层次结构。很可能,你会有一个更丰富的模型

判断聚合是否正确的第一种方法是,您可以查看其中的每个实体,并询问“是否需要直接访问该实体?”如果回答是,则该实体可能不是聚合的一部分

如果不了解更多关于您的域的信息,我可能会假设存储确实是一个聚合。另一方面,销售则更为复杂。是的,销售发生在商店里,但你是否需要独立查看和使用销售?如果您需要的产品超出了仅与商店合作的范围,那么销售可能超出了该范围

我认为样式和颜色都是不可变和可重复的,所以在这种情况下它们很可能是有价值的对象。区域是商店独有的,还是各不相同

就我个人而言,我觉得在纸上(或白板上)识别域中的所有项目很有价值。我将与利益相关者一起经历一个发现阶段,并将他们带到那里。然后,在对话中使用这些词作为引导语,试图理解它们之间的关系。如果你对利益相关者的采访足够好,他/她给出的描述实际上将定义你所寻找的大部分内容


不是为了打败一匹死马,但埃文斯的书绝对值得一读。它有点枯燥,但很有洞察力。要快速启动,您可以阅读InfoQ上的综述,这基本上是Evans书的总结。

聚合根是事务、分发和并发的一致性边界()


当两个人修改同一存储中的不同区域时,是否会导致并发冲突?如果不是,那么分区可能应该是它们自己的聚合根,与存储区分开

是的,我也想直接访问销售,可能只需传递StoreId即可。我想我会在这种情况下创建一个存储库?区域因商店而异。每个商店都可以有不同数量的分区。我会在这里创建一个分区存储吗?我订购了埃文斯的书,但他已经开始研究我的领域了。如果您需要任何其他信息,请告诉我。我能得到的知识越多,我就越能理解DDD。再次感谢。在我看来,聚合边界可能是DDD中最困难的事情。如果您希望必须将门店标识符传递到建议的销售存储库中,那么有两种可能性是直接的。首先,销售可能是您提到的商店总数的一部分。另一个可能是商店可能是销售总额的一部分。如果您需要独立地访问它们,并且不需要直接了解彼此,那么它们将成为聚合的唯一方式。请注意,这并不阻止您持有对另一个聚合根的引用。例如,如果您确定Store和Sales都是聚合根,则没有什么可以阻止Sales引用Store标识符,然后您可以在需要时使用该标识符调用Store repository来获取Store。至于区域,与商店有着明确的关系。这加强了Store是聚合根而Zone是实体的情况(因为它们在您描述的上下文中不一定是不变的)。所以,现在,我们确定Store是一个聚合,包含区域。。。。。。颜色很可能是与样式相关的值对象。不过,我仍然不知道如何对待一种风格。同一风格可以存在于多个区域吗?谢谢Joseph。为什么你认为一个区域和一个商店有明确的关系,而不是一个商店的销售?两者几乎都是商店的一部分。不过,我想我希望通过传递StoreId就能够独立地访问它们。我认为这一事实使它们分开了?重新设置样式:是的,同样的样式也可以存在于其他区域中。为每个对象设置一个存储库不是很臃肿吗?毕竟它们都与存储相关,对吗?如果每个对象都有存储库,那么它就不会膨胀。它们是更小、更容易理解的对象(单一责任原则)。如果您有存储库(repository)的基类,那么编写代码就更少了。这样,您可能只需要为这些实体编写特殊查询。
public class StoreRepository()
{
  Store GetById() {...}
  StoreZone GetZone() {...}
  List<StoreZoneStyle> GetStylesByZone() {...}
  List<Color> GetColorsByStyle() {...}
}