事件溯源:业务逻辑放在哪里?

11

在事件溯源系统中,我可以想到两个地方来放置域逻辑,但每个地方都有缺点。

  • 在聚合的事件处理程序中,在创建事件后本地调用。(这是我在大多数 示例 中看到的,尽管它们大多具有非常简单的逻辑)
    问题: 存储在事件存储中并发布给订阅者的事件不包括此已处理的数据,因此在投影上必须应用相同的逻辑。
  • 在创建事件之前。现在,处理后的数据可以存储在事件中,投影不必知道任何业务逻辑。(我没有在示例中看到过这种方法)
    问题: 在这种情况下,事件仅包括已处理的数据,这可能会导致信息丢失。
    更糟糕的是: 我还失去了通过重播事件来纠正错误业务逻辑的可能性,因为事件数据已经被计算出来了。

示例: 从一些数据计算度量值。
我要么需要两次计算度量值(一次在域模型中,一次在投影中)
要么在发送事件之前计算度量值并将其包含在其中。

2个回答

13

控制流通常如下:

  • 将命令发送到命令处理程序,对命令中的属性进行预验证,例如标识符指向现有实体,所有必需信息均存在且格式正确
  • 命令处理程序从存储库中检索聚合(通过读取事件流,但这不重要),并根据该命令需要执行的操作调用聚合方法
  • 聚合方法必须确保其参数和聚合状态相互允许执行操作。

  • 然后,聚合方法创建一个事件,并调用此WhenApply方法来处理该事件

  • 事件处理程序突变聚合状态,不涉及逻辑!

  • 然后将控制流返回到命令处理程序,并将所有新事件持久化到存储器中

进一步的操作与投影相关。

将不变式保护(即业务逻辑)放入聚合事件中,以应用事件之前的原因是当事件生成时,就无法回头了。事情已经发生了。您无法拒绝应用事件。考虑从事件流中恢复聚合(从存储库中读取)时重播事件,如果某天您决定在那里使用if-throw组合,这会如何工作?

因此,简而言之:

  • 在发送命令之前应用初始逻辑
  • 某些其他逻辑位于命令处理程序中
  • 聚合方法中的聚合保护(也可以在命令处理程序中)
  • 事件处理程序中没有逻辑,只有状态突变

没有人说过事件溯源可以帮助您修复计算中的问题。为了增加额外的安全保障,您可能需要保存命令,但然后您将不得不发布补偿事件或截断流,这并不是您想要做的。


修复计算问题被一些人描述为一个好处。请参见此处:“修复错误。您可能会发现一个编码错误,导致系统计算出不正确的值。与其在存储的数据项上执行风险较高的手动调整,不如修复编码错误并重新播放事件流,以便系统根据新版本的代码正确计算值。”(来自https://msdn.microsoft.com/en-us/library/jj591559.aspx#sec2) 但除此之外,感谢澄清。 - Marian Bäuerle
1
如果在读模型的投影中进行计算,这是有意义的。但在事件应用程序中进行计算以改变聚合状态则不然。 - Alexey Zimarev
事件处理程序中没有逻辑,只有状态变化。这里"state mutation"的意思是修改或更新字段。 - ssmallya
修改、更新和变异是同义词,指改变对象的状态。 - Alexey Zimarev

0

我猜你的聚合根里有一些状态。这个状态应该包含业务逻辑,因此它应该有足够的数据来创建基于命令的事件。
这个事件的消费者(查询模型)进行计算。所以如果意图是计算平均值,它必须设法以给定的方式存储自己。
我也做了类似的事情。一开始它是业务逻辑的一部分,所以它在聚合中;后来它在查询模型中,因为它不是业务逻辑的一部分,而更多地是指标计算。
不要害怕在多个地方存储数据。一致性的责任应该委托给事件分发,而不是你的业务逻辑。


你有一些图形展示你是如何做到的吗? - Marian Bäuerle
我不太明白最后一部分,所以你的意思是将逻辑分成两部分,一部分在聚合中,另一部分在查询模型中? - Marian Bäuerle
这是一篇很好的文章,介绍了CQRS/ES。https://msdn.microsoft.com/en-us/library/jj591559.aspx - hellxcz
谢谢提供链接,它很好地概述了事件溯源。但它并没有真正回答在哪里放置领域逻辑的问题。 - Marian Bäuerle
2
业务逻辑应该放在聚合根中,它持有命令模型。这个命令模型必须具备足够的信息来做出业务决策。基于此决策,事件被发射。这就是流程。然后,事件被读取模型(查询模型)消费,但实际上只是从域(业务)角度呈现的视图或投影。这种观点可以是基于系统变化的预计算,组织文档(在NoSQL中)以便进行快速读取(包括所有数据,因此不需要连接表、聚合函数开销等),甚至生成pdf文件。 - hellxcz
查询模型不应包含任何业务流程,只应包含业务决策的投影。它可能还包含一些平均值、求和计算,但仍然属于投影范围。 - hellxcz

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接