在DDD中的聚合根上创建子实例

时间:2015-11-22 04:25:58

标签: domain-driven-design

我一直在读Eric Evan关于DDD的书,他在第139页说:

“如果你需要在预先存在的AGGREGATE中添加元素,你可以在AGGREGATE的根目录上创建一个FACTORY方法”

我认为可以实现类似这样的方法,其中使用NewLineItem方法创建新订单项并将其添加到订单中。

class Order
{
   public IEnumerable<LineItem> LineItems { get; }

   public void NewLineItem(Product product, int quantity);
}

我能想到的另一种方法是将工厂方法移动到集合本身。这样的事情如下。然后我可以通过调用LineItems.New(...)添加一个新项目。

class Order
{
   public LineItems LineItems { get; }

   public class LineItems : IEnumerable<LineItem>
   {
       public void New(Product product, int quantity);
   }
}

每种方法的优缺点是什么?将工厂方法移动到集合中是否有任何问题?我们目前正在尝试找出实现大型域模型的最佳方法。我们担心这些根聚合模型中的一些会因为许多工厂方法和删除方法(如RemoveLineItem(LineItem))而变得臃肿。我们的想法是将这些工厂方法移动到它们的集合中有助于组织设计并使根集合更少混乱。有什么建议吗?

由于

2 个答案:

答案 0 :(得分:2)

demeter业务始终存在“法律”:)

聚合根(AR)将负责完整性和不变量。您可能会有一个不变的“最大订单总额为50美元且任何时候不超过6个订单项”。该集合将无法访问任何此类信息(好吧,也许是计数)。所以我们的想法是AR处理这些交互。

如果你担心臃肿或发现自己的AR很笨拙,可能表明你的设计有问题。 Vaughn Vernon在他的书中很好地介绍了这些场景。你真的想要高度凝聚力的AR,正确识别它们可能很棘手。可能需要进行几次迭代才能获得最舒适的设计。

所以我会尽量坚持Eric的建议并尽可能地处理AR本身的相互作用。

答案 1 :(得分:2)

直接在AR上使用工厂方法的一个优点是它使AR知道这些变化并允许它强制执行它的不变量。不仅如此,而且因为该方法知道AR的内部状态,您可以减少传递给工厂方法的参数数量(在创建其他相关AR时最有用)。

E.g。 registration = course.register(registrant) vs registration = new Registration(registrant, courseId)

此外,LineItem成为一个实现细节,因此客户不需要知道该类。

你提出这个问题并且实际上担心你的AR上有太多方法的事实可能表明你可能正在将不属于一起的对象聚集在一起。

不要忘记AR的主要目的:它是一个允许保护不变量的事务边界。如果没有保护不变量,那么聚类可能是不必要的,甚至是不可取的。

我强烈建议你阅读Vauhgn Vernon的Effective Aggregate Design