【问题标题】:DDD: Aggregates and sub-aggregatesDDD:聚合和子聚合
【发布时间】:2013-07-18 09:49:16
【问题描述】:

我有一个相当复杂的聚合,聚合根Order。它包含在聚合之外没有意义的实体(例如OrderItem)。但是也有一些实体应该是这个聚合的一部分,但在这个聚合之外也有意义(例如ShippingMethodInvoice)。

为这个复杂的聚合拥有一个存储库(通过 root 的 id 加载整个聚合)并且还有一个用于管理可能的运输方式的 CRUD 存储库和另一个用于列出发票的存储库是否正确?

更一般地说,在 DDD 中是否可能有一个聚合,它是另一个聚合的一部分?

【问题讨论】:

标签: language-agnostic doctrine-orm domain-driven-design aggregateroot


【解决方案1】:

您可以将“一个聚合,它是另一个聚合的一部分”视为“一个聚合包含另一个聚合的引用”。

例如

public class Order {
    private Invoice invoice;
}

<class name="Order" table="T_ORDER">
    <one-to-one name="invoice" column="INVOICE_ID" />
</class>

如果在这种情况下 Order 和 Invoice 都是聚合,我将有一个 OrderRepository 和一个 InvoiceRepository。您可以使用检索 Order

orderRepository.findBy(orderId)

您可以使用

检索发票
invoiceRepository.findBy(invoiceId) 

Order order = orderRepository.findBy(orderId);
Invoice invoice = order.getInvoice();

还有一篇关于如何设计聚合的著名文章 (http://dddcommunity.org/library/vernon_2011/) 建议使用身份参考来实现这种关系。

public Class Order {
    private InvoiceId invoiceId;
}

<class name="Order" table="T_ORDER">
    <component name="invoiceId">
        <property name="value" column="INVOICE_ID" />
    </component>
</class>

您可以使用

检索订单
orderRepository.findBy(orderId)

您可以使用

检索发票
invoiceRepository.findBy(invoiceId) 

Order order = orderRepository.findBy(orderId);
Invoice invoice = invoiceRepository.findBy(order.getInvoiceId()); 

【讨论】:

  • 如何使用 ORM 实现这一点(我正在使用 php 和学说)?实体中没有直接引用 id 是否被视为反模式?
  • 我不熟悉php和学说。但它可以在 Java 中使用与 Hibernate 的常规一对一映射来实现(在 Aggregate 引用 Aggregate 情况下)。我不确定引用 id 是一种反模式,是否有一些文章或资源讨论了这一点?
  • Doctrine 深受 Hibernate 的启发。根据docs.doctrine-project.org/projects/doctrine-orm/en/latest/…,我的意思是在实体中拥有像 invoiceId 这样的整数属性是一种反模式。编辑:现在我明白你的意思不是一个整数,而是一个只包含 id 的值对象。
  • 引用 id 是一个值对象。您现在将发出两个查询,而不是通过 Order 导航到 Orderitems
  • 但我希望将数据库中的 Order.invoice_id 作为外键,因为报告更容易。有没有办法将它映射到域模型中的 VO 和报告模型中的相关实体?或者我应该将域实体和持久性实体分开(它们几乎相同)?
猜你喜欢
  • 2017-05-25
  • 1970-01-01
  • 1970-01-01
  • 2016-03-21
  • 1970-01-01
  • 2016-11-05
  • 2011-02-07
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多