聚合根的子节点如何使用来自另一个聚合根的值

How can a child of an aggregate root use values from another aggregate root

例如,假设一家商店有多个菜单。菜单列表项和一个项目可以在多个菜单中列出。

想象一个Menu聚合根和Item聚合根。一个菜单将有一个 MenuItem 的集合,这些 MenuItem 引用一个 Item AR 以及特定菜单中的订购信息。

我的问题是,您将如何从 MenuItem 访问项目的名称、价格和描述。例如,Menu AR 处理一个按价格重新排序的命令(我知道这听起来 UI 相关,但我在这里严格来说是在谈论域模型,idk 也许这是菜单必须的业务规则以特定方式排序?)

您是否会为 MenuItem 中的 Item AR 获取值对象?如果是这样,Menu AR 是否会保留对域服务的引用以查找 Item 的值对象,或者 MenuItem 是否会使用域服务。

我想,Menu AR 应该始终保持一致,这可能意味着当一个 Item 添加到 Menu 时,MenuItem 持有对该 Item 的值对象的引用。

听起来这会违反 'reference entities by identity' 规则,因此 MenuItem 将包含对 ItemId 的引用。考虑到事件源的使用,无论何时你想对 Menu AR 应用一个命令,它都会重播它的所有事件以使其保持一致,然后你发出一个命令来重新排序菜单项。

MenuItem 将只有一个 ItemId 而不是该项目的详细信息,现在是加载这些项目的时候吗?菜单可以遍历它的 MenuItems,然后使用服务通过 ItemId 为每个 MenuItem 查找 Item 值对象,然后执行排序。

感谢您的任何意见,非常感谢。

就像你说的,这可能应该在查询端完成。我不确定我看到在域中保持顺序一致有什么用?如果菜单有不同的订购策略,也许我会,但即便如此。无论如何...

如果 AR 使用的数据不在其边界内,则只能使其最终一致,除非您在每个事务中修改多个 AR,这通常是一种不好的做法。

你可以这样做:

menu = menuRepository.findById(menuId);
menu.reorder(itemPricingService);

有些人还喜欢在应用程序中解决依赖关系 service/command 处理程序:

menu = menuRepository.findById(menuId);
itemIdList = menu.items().map(extractItemId);
itemPriceList = itemPricingService.pricesOf(itemIdList);
menu.reorder(itemPriceList);

但是,您还需要监听 ItemPriceChanged 等事件,以便使菜单排序与价格变化保持一致。

还有另一种策略,您可以将定价信息复制到 MenuItem。价格最终会根据事件保持一致,并且会从价格发生变化的项目重新订购。

您可以使用与实施的 here 类似的重新排序策略。查看 ProductProductBacklogItemreorderFrom 实现。