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
可能更合法,因为允许域服务了解多个域实体和正在进行的整个域过程。
假设我的域中有 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
可能更合法,因为允许域服务了解多个域实体和正在进行的整个域过程。