我正在开发一个CMS类型的应用程序,我希望使用一些ddd战术模式。情况如下:
该应用程序处理项目的创作和发布。
项目在工作流程组中组合在一起。在该组中,一个项目可能标记为“已发布”,一个项目标记为“正在工作”,任何数字标记为“已存档”。
只有当项目处于“工作”状态时才能进行编辑。
当工作项目发布时,它会替换相应的已发布项目(如果有的话),然后将其标记为已存档。
如果不存在草稿,则可以通过复制已发布的版本或任何已归档的版本来创建新的工作版本。
问题是,遵循Aggregates应该封装系统不变量的指导,Workflow Group应该是一个聚合根 - 包含其所有项吗?
我担心这会产生相当大的聚合,并且会阻止项目全局访问(即所有交互都必须通过工作流组AR)。
我看到的替代方法是使Item成为聚合根,然后对事务和不变量进行域服务处理。例如:
PublishWorkingItem(int itemId)
{
Item workingItem = itemRepo.GetWorkingItem(itemId);
Guid groupId = workingItem.GroupId;
Item publishedItem = itemRepo.GetPublishedItemForGroup(groupId);
if(publishedItem != null)
{
publisheditem.Archive();
}
workingItem.Publish();
}
答案 0 :(得分:3)
如果您还没有,我强烈建议阅读vaughn vernon关于effective aggregate design的一系列文章。 第二部分建议您应咨询您的域专家,了解是否可以接受系统中的陈旧数据。如果答案是肯定的,您可以考虑使用小聚合(例如,您域中的项目)来维护最终的一致性而不是事务性。例如,这可能意味着在一段时间内,可能有两个项目具有已发布状态,但最终只会发布一个项目。您可以使用域事件来实现此类行为。拥有大型事务性组合聚合也是一种选择,但如果许多用户尝试同时操作同一组,则可能导致高并发争用。
答案 1 :(得分:3)
AR应该有自己的生命周期。这是您应该能够从您的领域专家那里获得的。
AR也是关于在高度凝聚的对象图周围有尖锐边缘。
如果您发现另一个AR中有AR,则需要删除包含的AR并将其替换为仅包含的ID或值对象。
在您的情况下,例如,活动项目和已归档项目之间可能存在差异,因此已归档项目不属于Workflow
AR。但您可能最终将Item
设为AR,在这种情况下,您的Workflow
AR可能包含活动商品ID / VO列表。
只是一些想法:)