以PurgeAllCompletedTodos等命令为例.我希望此命令导致一个事件,通过将IsActive设置为false来更新每个已完成的Todo聚合的状态.
为什么这不好?
我能想到的一个原因:
更新域状态时,将事务限制在整个状态的明确定义的部分可能是好的,这样在更新期间只需要对此部分进行写锁定.这样做可以在并行的不同聚合上进行多次写入,这可以在某些极端繁重的情况下提高性能.
解决方法
首先我会说你没有修改’n’聚合,但是你正在修改’n’个实体.
聚合包含多于一个的实体,它只是一个事务概念,当您需要在事务中修改应用程序中多个实体的状态(全部被修改或没有)时,使用聚合(模式).
现在,为什么要用一个命令修改多个聚合?
如果您觉得有这种需要,在做任何其他事情之前,请检查您的聚合边界,看看您是否可以修改它以删除对1命令的需求 – > ‘n’聚合.
聚合可以包含许多相同类型的实体,因此对于命令PurgeAllCompletedTodos,您还可以考虑将事务边界从单个Todo扩展到包含所有用户待办事项的聚合UserTodosAggregate,并让它管理所有命令对于单个用户的待办事项.
通过这种方式,您可以在单个事务中修改用户的所有待办事项.
如果这仍然无法解决您的问题,因为,假设需要清除应用程序中每个用户的所有已完成的待办事项,您仍然需要向’n’聚合发送命令,聚合边界无效,所以我们可以考虑使用一个管理命令的AllApplicationTodosAggregate.
可能这不是最好的解决方案,因为正如你所说的那样,命令会阻止应用程序的所有待机,但是,总是检查它是否是一个很好的权衡(这部分阻塞在蓝色中都得到了很好的解释) DDD的书和红皮书.
如果我需要修改某些实体并且不能将它们放在一个聚合中,该怎么办?
如前所述,由于事务,修改多个聚合的命令很糟糕.如果您修改3个聚合,第一个是好的,然后服务器关闭怎么办?
在这种情况下,您正在进行的是需要进行大量单个修改以防止系统不一致.
它可以使用流程管理器来完成,流程管理员负责修改所有聚合,向他们发送正确的命令,并在发生故障时管理故障.
聚合仍然接收它自己的命令,但是进程管理器负责以它知道的方式发送它们(一个时间,一个并行,每次5个,你想要什么)
因此,您可以制定策略来管理两个事务之间的故障,并做出如下决定:“如果某些事情失败,则回滚所有已完成的修改,直到现在”(向每个聚合发送回滚命令),或“如果操作失败重复它每30分钟3次,如果不起作用,则回滚“,”如果出现故障,则为系统管理员创建通知“.
(对不起,很长的帖子,至少希望它有帮助)