DDD - 如何处理"returning domain events"模式中的事务?



在DDD语言中,返回域事件模式被描述为管理域事件的一种方式。从概念上讲,聚合根保存域事件的列表,当您对其进行一些操作时会填充这些列表

在聚合根上的操作完成后,在应用程序服务层完成DB事务,然后,应用程序服务对域事件进行迭代,调用事件调度器来处理这些消息。

我的问题是关于我们现在应该如何处理这笔交易。事件调度程序是否应该负责管理其处理的每个事件的新事务?或者应用程序服务应该在调用域事件调度程序的域事件迭代中管理事务?当调度器使用像RabbitMQ这样的基础设施机制时,问题是不重要的,但当域事件在进程中处理时,问题就是。

子问题与我的问题有关。您对使用ORM挂钩(即:NHibernate的IPostInsertEventListener、IPostDeleteEventListener和IPostUpdateEventListener)在聚合根上启动Domain Events迭代而不是在应用程序服务中手动执行有何看法?它是否增加了太多耦合?它是否更好,因为它不需要在每个用例中编写相同的代码(域事件在聚合上循环,如果不在调度器内,则可能会创建新的事务)?

我的问题是关于我们现在应该如何处理事务。事件调度程序是否应该负责管理其处理的每个事件的新事务?或者应用程序服务应该在调用域事件调度程序的域事件迭代中管理事务?

您在这里问的实际上是这个问题的一个专门版本:我们是否应该在单个事务中更新多个聚合?

你可以发现很多断言,答案是"不"。例如,Vaughn Vernon(2014)

设计得当的聚合是指可以按照业务所需的任何方式进行修改的聚合,其不变量在单个事务中完全一致。在所有情况下,一个设计得当的有界上下文在每个事务中只修改一个聚合实例。

Greg Young倾向于更进一步,指出遵守这一规则可以通过聚合id对数据进行分区。换句话说,聚合边界是如何组织数据的明确表达。

因此,您最好的选择是尝试安排更复杂的编排,以便每个聚合都在自己的事务中更新。

我的问题与我们处理在初始事务完成后更改初始聚合后发送的事件的事务的方式有关。必须处理域事件,其进程可能需要更改另一个聚合。

是的,所以如果我们要更改另一个聚合,那么(根据上面的建议)应该有一个新的事务来更改聚合。换句话说,决定我们是否需要另一个事务的不是域事件的路由——事件处理程序的选择决定了我们是否需要另外一个事务。

仅仅因为事件处理发生在进程中,并不意味着始发应用程序服务必须协调由于事件而发生的所有事务。

例如,如果我们通过Observable模式进行进程内事件处理,每个Observer将负责创建自己的事务(如果需要的话)。

您对使用ORM挂钩(即:IPostInsertEventListener、IPostDeleteEventListener,NHibernate的IPostUpdateEventListener)启动域事件对聚合根进行迭代,而不是在应用程序服务?

这不是必须在原始DB事务期间发生吗,有效地将一切转化为即时一致性(如果在过程中处理事件)?

最新更新