取决于vaughn vernon在其关于Agile的书中给出的示例。他将Product设计为Aggregate,将BackLogItem设计为通过Id引用Product AR的聚合。
现在我们需要在BackLogApplicationService中规划新的BackLogItem,如下所示:
public class ProductBacklogItemService
{
//...
public void planProductBacklogItem(
String aTenantId, String aProductId,
String aSummary, String aCategory,
String aBacklogItemType, String aStoryPoints)
{
Product product =
productRepository.productOfId(
new TenantId(aTenantId),
new ProductId(aProductId));
BacklogItem plannedBacklogItem =
BacklogItem.planBacklogItem(
aSummary,
aCategory,
BacklogItemType.valueOf(aBacklogItemType),
StoryPoints.valueOf(aStoryPoints),
product);
backlogItemRepository.add(plannedBacklogItem);
//commit the changes
}
//...
}
工厂方法如下:
public static BacklogItem planBacklogItem(String aSummary, String aCategory,BacklogItemType aType, StoryPoints aStoryPoints,Product product)
{
if(product.Suspended)
//here prevent planning this backlogitem
//...
backLogItem.ProductId=product.Id
return backLogItem;
}
我是否违反了Factory方法中BackLogItem聚合的一致性边界,因为我正在使用有关产品状态的一些信息来决定将新的backLogItem规划到该产品中,如果是这样的话我怎么能阻止在该产品中规划新的backLogItems产品是暂停还是不活动?
答案 0 :(得分:1)
DDD中的聚合根之间允许哪种级别的通信?
核心准则是:任何给定的交易最多可以修改模型中的一个聚合。
因此,如果您的模型包含Product和BacklogItem之间的关系,那么您可以使用来自BacklogItem的数据的陈旧副本来修改Product,或者您可以使用来自Product的数据的陈旧副本来修改BackLogItem。 / p>
为了帮助在代码中明确这一点,我们使用接口将消息从一个聚合传递到另一个聚合。在我们要修改产品的用例中,我们有一个支持突变的产品接口,以及一个仅支持查询的后台日志项接口。如果我们要更新后备日志项,那么该项具有可变接口,产品接口是只读的。
换句话说,我们使用适当的role interfaces来确保没有代码作者无意中违反了在事务中修改多个聚合的规则。
我们的答案意味着上面的代码它没有违反DDD,因为我不在这里更新产品聚合(因为ddd不允许每次事务更新多个聚合
对 - 当Evans described DDD in 2003时,他正在使用不依赖于接口的编码风格;拥有一个产品实例,意味着可以同时提供所有产品的功能。
角色接口有助于减少这种灵活性带来的错误数量。只是不犯错误也是一种选择。