【问题标题】:How can a child of an aggregate root use values from another aggregate root聚合根的子节点如何使用来自另一个聚合根的值
【发布时间】:2016-02-04 09:33:48
【问题描述】:

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

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

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

你会为 MenuItem 中的项目 AR 获取一个值对象吗?如果是这样,Menu AR 是否会持有对域服务的引用以查找 Item 的值对象,或者 MenuItem 是否会使用域服务。

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

听起来这样会破坏“通过身份引用实体”规则,因此 MenuItem 将持有对 ItemId 的引用。考虑到事件溯源的使用,每当您想对 Menu AR 应用命令时,它都会重播所有事件,使其保持一致,然后您发出命令以重新排序菜单项。

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

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

【问题讨论】:

    标签: domain-driven-design cqrs event-sourcing aggregateroot


    【解决方案1】:

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

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

    你可以这样做:

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

    有些人还喜欢在应用程序服务/命令处理程序中解决依赖关系:

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

    但是,您还需要收听诸如ItemPriceChanged 之类的事件,以使菜单顺序与价格变化保持一致。

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

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

    【讨论】:

    • 感谢您一直支持我重新制定业务规则,这只是我想到的第一件事。这很有帮助,我认为你是对的,如果项目的定价在商业术语中对菜单很重要,那么 MenuItem 将价格复制到自身上是有意义的。它只需要像你说的那样最终保持一致,依靠ItemPriceChanged 事件保持最新。我必须做更多的研究,因为如果Menu AR 听了ItemPriceChanged 的所有事件都是MenuItem 的,那听起来已经不对了,并且在重播Item 时可能会导致副作用
    猜你喜欢
    • 2019-08-07
    • 1970-01-01
    • 2015-01-04
    • 2013-07-10
    • 2018-08-12
    • 1970-01-01
    • 2010-12-16
    • 1970-01-01
    • 2017-08-25
    相关资源
    最近更新 更多