DDD:在另一个 AR 中创建一个聚合根

DDD: Create one aggregate root within another AR

假设我的域中有 2 个聚合根 (AR),调用第一个方法需要访问第二个的实例。 在 DDD 中,应该如何以及在何处检索和创建第二个 AR?

这是一个需要访问 SuitcaseEntity 的人为示例 TravelerEntity。我正在寻找一个不会用基础设施代码污染域层的答案。

public class TravelerEntity {
    // null if traveler has no suitcase yet.
    private String suitcaseId = ...;
    ...

    // Returns an empty suitcase ready for packing. Caller 
    public SuitcaseEntity startTrip(SuitcaseRepository repo) {
        SuitcaseEntity suitcase;
        if (suitcaseId == null) {
          suitcase = new SuitcaseFactory().create();
          suitcase = repo.save(suitcase);
          suitcaseId = suitcase.getId();
        } else {
          suitcase = repo.findOne(suitcaseId);
        }

        suitcase.emptyContents();

        return suitcase;
    }
}

处理开始行程请求的应用层服务将通过 DI 获得适当的 SuitcaseRepository 实现,通过 TravelerRepository 实现获得 TravelerEntity 并调用其 startTrip()方法。

我想到的唯一选择是将 SuitcaseEntity 管理移至域服务,但我不想在开始旅行之前创建手提箱,而且我不想结束贫血 TravelerEntity.

我有点不确定一个 AR 创建并保存另一个 AR。这可以吗,因为回购和工厂封装了关于第二个 AR 的细节?我有失踪的危险吗?还有更好的选择吗?

我是 DDD 的新手,可以质疑我对此的想法。我发现的关于 AR 的其他问题似乎侧重于正确识别它们,而不是管理它们之间的生命周期。

首先,持久化不是域的工作,所以我会从域模型中删除所有存储库,并创建一个使用它们的服务。

其次,您应该重新考虑您的设计。为什么 Traveler 的 StartTrip 方法应该 return SuitCase?

旅行者有或没有手提箱。一旦你找回了旅行者,你应该也已经有了他们的手提箱。[​​=11=]

public class StartTripService {
     public void StartTrip(int travellerId) {
         var traveller = travellerRepo.Get(travellerId);
         traveller.StartTrip();
     }
}

理想情况下 TravelerEntity 不会操纵 SuitcaseRepository,因为它不应该知道存储手提箱的外部事物,只知道它自己的内部结构。相反,它可以新建一个 SuitCase 并将其添加到其内部 [list of] 手提箱中。如果您希望它与 ORM 一起工作而无需专门将手提箱添加到存储库中,则必须将整个手提箱对象存储在 TravelerEntity.suitcaseList 中,而不仅仅是它的 ID,这与 "store references to other AR's as IDs" 最好的冲突练习。

此外,TravelerEntity.startTrip() return 手提箱似乎有点做作和不明确,如果你需要 return [=15= 创建的其他实体,你会遇到麻烦].因此,一个好的解决方案可能是让 TravelerEntity 在将手提箱添加到其列表后发出一个带有手提箱数据的 SuitcaseAdded 事件。应用程序服务可以订阅该事件,将手提箱添加到 SuitcaseRepository 并提交事务,有效地将新手提箱和修改后的旅行者都保存到数据库中。

或者,您可以将 startTrip() 放在域服务而​​不是实体中。使用 SuitcaseRepository 可能更合法,因为允许域服务了解多个域实体和正在进行的整个域过程。