其实两种情况都不是。
实体不会越过聚合边界。如果实体是聚合的一部分,那么聚合将管理其生命周期,或者该项是其他聚合的一部分,在这种情况下,您不共享实体,而是共享一个引用。
order.AddItem(id)
聚合的定义之一是不同聚合的更改可以独立于彼此发生。换句话说,这个聚合无法知道“现在”那个聚合正在发生什么。
换句话说,你无法确保跨聚合边界的事务一致性。
如果您愿意接受数据竞争,正确的答案是使用域服务来查询边界外的状态。
interface InventoryService{
boolean currentlyInStock(Item id);
}
order.addItem(id, inventoryService);
一些要点:
使用领域服务而不是传递其他仓库,因为它更好地传达了正在发生的事情。领域服务作为聚合实际需要的合同的描述。此外,通过拒绝传递存储库,您排除了订单聚合尝试写入项目存储库的任何可能性。
(此领域服务的琐碎实现只是将调用转发到存储库,但订单聚合不需要知道这一点)。
在这种情况下,领域服务不应该通过根据库存的可用性选择操作来“帮助”--也许当订单超过一百万美元时,聚合应该抛出异常,但对于低交易量订单/低优先级购买者使用不同规则。弄清楚这一点是订单的工作,领域服务只提供数据。
由于数据竞争,一些误报可能会滑过去;检测和缓解是个好主意。
如果您不愿接受数据竞争(您确定吗?亚马逊经常接受缺货商品的订单...),那么您需要重新考虑模型的设计以及设置聚合边界的位置。
模型的空设计是将所有业务状态捕获到单个聚合中;它自己的状态在内部是一致的,但可能与外部状态不一致。当您开始将模型划分为单独的聚合时,您正在做出相同的断言--聚合需要在内部保持一致,但可能与聚合外部状态不一致。
如果这是不可接受的,则请将母亲的画像转到墙上,并直接在记录簿中实现业务规则(即,在RDBMS中约束)。