2009-06-10 86 views
12

我与骨料和骨料根挣扎。我有一个自然的聚合根,可以满足大约60%的用户请求。即这些请求自然适用于聚合根。领域驱动设计 - 总根

在我的骨料我只能存在作为聚合根的成员另一个实体。但是,用户会被告知这个其他实体对象。从概念上讲,有时用户可以直接操作这个非聚合根对象。

所以,我觉得我有几个选择:

  1. 他们可以他们俩是取决于总根于正在由用户请求的操作。
  2. 所有的操作都需要经过顶层聚合根。

注意顶层聚合根将保持这个其他实体的集合。


实施例:

主要聚合根:车载

第二实体:座位(汽车具有2或4个座位取决于类型)。在我的领域,座椅只能作为汽车的一部分存在。

域内大多数手术是在汽车的水平。所以这将是聚合根的一个很好的候选人。但是,(我挣扎了这里的例子),有些操作会在座位级别,例如SpillCoffee,ChangeFabric,Clean ....

座椅和车都可以聚合根吗?或者我应该总是从Car开始?

感谢

回答

13

的总的指导思想是保证一致性,为根负责数据的完整性,并迫使不变。

假设有一个规则,如“所有座位的面料必须是相同的”,或“”你只能洒咖啡在座位上是否有车里面的人”,这将是更难执行这些,一旦客户将能够单独更换织物,或者这些不变量需要强制在外(危险区域)

恕我直言,如果完整性或强制不变量不是问题,那么聚合就不是真正需要的了,但是,如果有必要的话,我的建议是用汽车启动所有的东西,但是一定要考虑模型,如果存在这样的不变量,那么谁来执行这些不变式?然后尝试将这个想法传递给代码,一切都应该没问题。

1

对于带有购物车和订单项的购物车,由于我经常独立修改它们,因此我将它们都作为聚合根。

public class Cart : IAggregateRoot 
{ 
    public List<LineItem> LineItems {get;} 
} 

public class LineItems : IAggregateRoot 
{ 
    public List<LineItem> LineItems {get;} 
} 

不过,我有订单单独界上下文,在这种情况下,我只需要具有一个聚合根,因为我不再需要单独修改行项目。

public class Order : IAggregateRoot 
{ 
    public List<LineItem> LineItems {get;} 
} 

的另一种选择是有一个孩子ID查找总根的方法。

Car GetCarFromSeatID(guid seatID) 
2

可能您需要对领域模型某些方面有更深入的了解。这个问题表明,你正打算发明一种组织实体来提供系统的方法,理想情况下,这类问题在实施之前已经得到了解答。

只有在系统实施时才会弹出,您是否要回过头去查看域,或者是否发现了一些脆弱性,他们的反馈可以 - 也应该 - 汇总业务相关详细信息的变化,以使域更丰富,更好地建模。

在汽车的例子中,我使用了两个聚合关联不同上下文的方法。第一个是“汽车有座位”的方法,在这个总体上,“座位”可能的行动只是“坐上汽车的一部分”才有意义。例如:清洁。

第二个聚合将在“座位”的上下文中,并且将有可能的座位作为独立的动作和配置。示例:ChangeFabric,ColorList。这样,“汽车”总量就有了“座位”,但客户可以在有意义的背景下了解座位。这是危险的,就像samuelcarrijo在之前的文章中所说的那样。如果上下文之间的修改影响域的完整性,那么您就失去了所有的聚合概念。