DDD-聚合中子对象的修改

问题描述 投票:12回答:6

我在解决应对相当复杂的情况的最佳方法时遇到了一些困难。我已经看到了很多类似的问题,但是没有一个令我满意。

使用多个OrderLine(子实体)创建了一个Order(集合根)。根据业务规则,每个OrderLine必须在Order的整个生命周期内保持相同的身份。 OrderLine具有许多(20+)个属性,在Order被视为“锁定”之前,可以相当频繁地进行更改。另外,必须在根级别强制执行不变式。例如,每个订单行都有一个数量,该订单的总数量不能超过X。

当考虑对OrderLines进行更改时,我不确定如何为这种情况建模。我有4个可以想到的选择,但似乎没有一个令人满意的选择:

1]当需要修改OrderLine时,请使用根提供的引用来进行修改。但是我无法检查根中的不变逻辑。

var orderLine = order.GetOrderLine(id);
orderLine.Quantity = 6;

2)在订单上调用方法。我可以应用所有不变逻辑,但是后来我被大量方法修改OrderLine的许多属性所困扰:

order.UpdateOrderLineQuantity(id, 6);
order.UpdateOrderLineDescription(id, description);
order.UpdateOrderLineProduct(id, product);
...

3)如果将OrderLine作为值对象,这可能会更容易,但是它必须根据业务需求维护相同的标识。

4)我可以获取对OrderLines的引用,以进行不影响不变量的修改,并进行对OrderLines的修改。但是,如果不变性受大多数OrderLine属性的影响,该怎么办?这个异议是假设的,因为只有少数属性会影响不变量,但是随着我们发现更多的业务逻辑,事物会发生变化。

任何建议都值得赞赏...如果我很稠密,请随时告诉我。

我在解决应对相当复杂的情况的最佳方法时遇到了一些困难。我已经看到了很多类似的问题,但是没有一个问题令我满意。订单(...

domain-driven-design aggregateroot
6个回答
5
投票
  1. 不是最佳选择,因为它允许打破域不变性。


5
投票

4与2相比的一个缺点是缺乏一致性。在某些情况下,在更新订单行项目方面保持一定程度的一致性可能是有益的。现在尚不清楚为什么某些更新是通过订单进行的,而其他更新是通过订单行项目进行的。此外,如果订单行具有20多个属性,则可能表明这些属性之间有可能分组,从而导致订单行上的属性较少。总体而言,方法2或4很好,只要您确保使操作原子化,一致并与普遍存在的语言相对应即可。


5
投票

有第五种方法。您可以触发domain event(例如QuantityUpdatedEvent(order, product, amount))。让聚合通过在订单行列表中进行内部处理,选择一个具有匹配产品的行并更新其数量(或将操作委托给OrderLine更好)[]


4
投票

域事件是最可靠的解决方案。


2
投票

如果您的项目很小,并且想避免域事件的复杂性,这是另一种选择。创建一个处理Order规则的服务,并将其传递给OrderLine上的方法:


0
投票

使用DTO有什么用?

© www.soinside.com 2019 - 2024. All rights reserved.