【问题标题】:Creating child instances on an aggregate root in DDD在 DDD 中的聚合根上创建子实例
【发布时间】:2015-11-22 04:25:58
【问题描述】:

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

"如果您需要在预先存在的 AGGREGATE 中添加元素,您可以在 AGGREGATE 的根目录上创建 FACTORY METHOD"

我假设可以像这样实现,其中方法 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))而变得臃肿。我们的想法是,将这些工厂方法移到它们的集合中有助于组织设计并保持根聚合不那么杂乱无章。有什么建议吗?

谢谢

【问题讨论】:

    标签: domain-driven-design


    【解决方案1】:

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

    例如registration = course.register(registrant)registration = new Registration(registrant, courseId)

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

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

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

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

    【讨论】:

    • 听起来你和 Eban 都在说同样的话。感谢您的反馈,并将查看弗农的书。
    【解决方案2】:

    Demeter 业务总是有“法则”:)

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

    如果您担心臃肿或发现自己使用笨拙的 AR,这可能表明您的设计存在问题。 Vaughn Vernon 在他的书中很好地涵盖了这些场景。你确实需要高度凝聚力的 AR,但要正确识别它们可能会很棘手。可能需要多次迭代才能获得最舒适的设计。

    因此,我会尝试坚持 Eric 的建议,并尽可能处理 AR 本身的交互。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-06-29
      • 1970-01-01
      • 2016-11-05
      • 1970-01-01
      • 2016-03-21
      • 2015-11-11
      • 1970-01-01
      相关资源
      最近更新 更多