DDD:坚持聚合

时间:2010-04-13 07:41:48

标签: persistence domain-driven-design aggregate aggregateroot persistence-ignorance

让我们考虑典型的订单 OrderItem 示例。假设 OrderItem 订单聚合的一部分,它只能通过订单添加。因此,要向订单添加新的 OrderItem ,,我们必须通过存储库加载整个聚合,向订单对象添加新项并再次坚持整个Aggregate。

这似乎有很多开销。如果我们的订单有10个 OrderItems 怎么办?这样,只需要添加一个新的 OrderItem ,我们不仅需要读取10个 OrderItems ,而且我们还应该重新插入所有这10个 OrderItems 再次。 (这是Jimmy Nillson在他的DDD书中采用的方法。每次他想要坚持一个Aggregate,他清除所有子对象,然后再次重新插入它们。这可能会导致其他问题,因为孩子的ID是由于数据库中的IDENTITY列,每次都会更改。)

我知道有些人可能会建议在Aggregate Root中应用工作单元模式,以便跟踪已更改的内容并仅提交这些更改。但这违反了持久性无知(PI)原则,因为持久性逻辑正在泄漏到域模型中。

以前有人想过这个吗?

MOSH

3 个答案:

答案 0 :(得分:1)

这不一定是个问题,一些ORM支持懒惰列表。 例如 您可以加载订单实体并将项目添加到Details集合中,而无需实际实现该列表中的所有其他实体。

我认为N / Hibernate支持这一点。

如果您正在使用任何ORM编写自己的实体持久性代码,那么您将非常幸运,您将不得不重新实现与ORMappers免费提供的相同的脏跟踪机制。

答案 1 :(得分:1)

必须从数据库加载整个聚合,因为DDD假定聚合根确保聚合边界内的一致性。要使这些规则有效,必须加载所有必要的数据。如果要求特定客户的订单价值不超过100000美元,则聚合根(订单)必须在持久更改之前检查此规则。这并不意味着必须加载所有现有项目并总结其价值。订单可以保留现有项目的预先计算的总和,在添加新项目时更新。这种方式检查业务规则只需要在添加新项目时加载订单数据。

答案 2 :(得分:1)

我对这种方法并不是100%肯定,但我认为应用工作单元模式可能就是答案。请记住,应该在应用程序或域服务中完成任何事务,您可以使用已更改的聚合中的对象填充工作类/对象单元。在那之后让UoW类/对象发挥魔力(在某些情况下构建一个合适的UoW可能很难)

以下是here

中工作单元格的说明
  

工作单元会跟踪您在业务事务中可能影响数据库的所有操作。当您完成后,它会计算出因您的工作而需要更改数据库的所有事项。