域驱动设计方法重复

use*_*475 6 domain-driven-design aggregateroot

我目前正在研究Eric Evans的域驱动设计书,有一个概念我遇到麻烦...

根据该书,所有聚合都应该有一个聚合根,并且只能通过这个根访问聚合的所有成员.根也应该负责执行不变量.这会不会导致很多方法重复?以下面的场景为例:

我有一个Order类,它由一组OrderLine组成.在这种情况下,类顺序是聚合根,它必须强制执行单个订单的所有OrderLine必须具有唯一订单号的不变量.为确保不违反此不变量,类Order不会公开其OrderLine,并且只提供一个方法updateOrderLineOrderNumber(long orderLineId,int newOrderNumber),必须通过该方法更新OrderLines.此方法仅检查newOrderNumber是否与现有订单号冲突,然后调用相应OrderLine的方法updateOrderNumber(int newOrderNumber).这很好,因为它只是一种方法,但是当OrderLine类有两种方法时会发生什么?由于订单不公开其OrderLines,因此OrderLines的所有属性都必须通过类Order更新,即使属性更改不需要任何不变检查.毫无疑问,这会导致很多方法重复,随着更多类被添加到聚合中,这种方法只会变得更糟.

我明白这个错吗?我可以使用任何替代机制或设计模式来防止这种情况吗?

我想到的一种可能的策略是验证器的概念.每当OrderLine的属性发生更改时,它必须首先检查一组验证程序是否允许此更改.然后,只要将OrderLine添加到订单,订单就可以向OrderLine的name属性添加适当的验证器.你们怎么看待这个策略?

任何帮助或想法将不胜感激!

Raf*_*ski 1

老实说,我不认为这里有问题。首先,为什么要更改 orderId?id应该设置一次,不同的id等于不同的实体。

通常,如果你想更新 AR 的实体,你只需获取它并更新它即可。

orderLine = order.getOrderLine(index)
orderLine.changeProduct(someProduct)
Run Code Online (Sandbox Code Playgroud)

如果您需要在 AR 中保留一些不变量,例如 OrderLine.product 必须是唯一的,那么您可以调用 AR 方法。

order.changeOrderLineProduct(orderLineIndex, someProduct)
Run Code Online (Sandbox Code Playgroud)

该方法在内部检查 someProduct 是否唯一,如果是则调用上面的代码。这里不存在 DRY 违规,AR 方法检查不变量,orderLine 方法更新。

我还会考虑在此使用更多 UL,例如“客户按订单更改其订单行上的产品”

client.changeOrderLineProductOnOrder(orderLineIndex, product, order)
Run Code Online (Sandbox Code Playgroud)

这样您就可以检查客户是否是该订单的所有者。