Domain driven design 为什么可以';萨加斯质疑阅读的一面吗?

Domain driven design 为什么可以';萨加斯质疑阅读的一面吗?,domain-driven-design,cqrs,event-sourcing,Domain Driven Design,Cqrs,Event Sourcing,在CQRS领域驱动的设计系统中,FAQ指出,传奇不应该查询读端()。然而,saga监听事件以执行命令,因为它执行命令,所以本质上是一个“客户机”,所以为什么saga不能查询读取模型呢?saga使用命令模型来更新系统的状态。命令模型包含业务规则,能够确保更改在给定域内有效为此,命令模型具有其所需的所有可用信息。 另一方面,读取模型有一个完全不同的用途:它构造数据,以便适合提供信息,例如显示在网页上 因为saga通过命令模型拥有它所需要的所有信息,所以它不需要read模型更糟糕的是,使用saga中的

在CQRS领域驱动的设计系统中,FAQ指出,传奇不应该查询读端()。然而,saga监听事件以执行命令,因为它执行命令,所以本质上是一个“客户机”,所以为什么saga不能查询读取模型呢?

saga使用命令模型来更新系统的状态。命令模型包含业务规则,能够确保更改在给定域内有效为此,命令模型具有其所需的所有可用信息。

另一方面,读取模型有一个完全不同的用途:它构造数据,以便适合提供信息,例如显示在网页上

因为saga通过命令模型拥有它所需要的所有信息,所以它不需要read模型更糟糕的是,使用saga中的read模型会引入额外的耦合,并大大增加系统的整体复杂性。


这并不意味着您绝对不能使用read模型。但如果你这样做了,一定要明白后果。对我来说,这个标准相当高,我一直都在寻找一个不同的解决方案。

Sagas不应该向阅读端(投影)查询完成任务所需的信息。原因是您无法确保读取端是最新的。在最终一致的系统中,您不知道何时更新投影,因此无法依赖其状态

这并不意味着传奇故事不应该成为国家大事。在许多情况下,传奇确实需要跟踪国家,但是传奇应该负责创建国家。在我看来,这可以通过两种方式实现

它可以通过从事件存储中读取事件来建立其状态。当它接收到应该触发的事件时,它将从存储中读取它需要的所有事件,并以与聚合类似的方式建立其状态。这可以通过创建新的流来实现


另一种方法是,它持续侦听来自事件存储的事件,并建立状态,并将其存储在一些数据存储上,就像投影一样。只是要小心这种方法。你不能像回复投影那样回复传奇故事。如果需要更改存储状态的方式并希望重建状态,请确保不执行已执行的命令。

这主要是关于分离关注点。过程管理器(SAGA)是负责协调活动的状态机。如果流程管理器希望影响更改,它将发送命令(异步)

还有:什么是阅读模式?这是一系列已经发生的事件的投影。所以如果处理器关心这些事件。。。它不应该一直订阅它们吗?所以这里有一股模特的味道

可能的问题:

流程管理器应该一直在侦听流中的早期消息,以便在该消息到达时处于正确的状态

当前事件应该更丰富(以便流程管理器“需要”的数据已经存在)

。。。变体-相反,命令处理程序应该侦听不同的事件,并且该事件应该更丰富

您想要的查询实际上应该是对已经知道答案的聚合的命令

其他一切都失败了


向服务发送命令,该服务运行查询并发送事件作为响应。这听起来很奇怪,但让流程管理器将消息发送到调度服务已经是一种常见的做法,当某个固定的时间流逝时,消息会被“唤醒”。

OK,但是这个场景如何()?您是否建议通过允许通过任意聚合键/值对查询事件存储来智能化(复杂化)事件存储?您当然需要能够从事件存储中重建聚合,以便能够验证业务规则-这就是命令模型的全部内容。当然,这比使用ORM时要复杂一些——这是您在选择ES时所做的权衡。您在我的评论中没有回答这个问题。对于引用的SO问题,存在一个
订单
AR和一个
客户
AR。更新
客户
邮寄地址
时,saga必须检索属于该客户的所有未发货的
订单
,以便更新订单的
交付地址
(这是SQL术语中的一对多关系,即使它们在DDD术语中都是ARs)。在不访问read模型的情况下,您如何让saga做到这一点?我确实回答了您的评论问题:您需要能够加载这些聚合(客户和所有订单)作为命令模型的一部分。由于在这种情况下只有几个订单,我可能会逐个加载它们。如果有可能有很多订单需要更新,那么你会有一种设计的味道:你应该一次只更新一个聚合-所以在这种情况下重新评估你的聚合边界。但是如果我们不更新呢不关心数据是否最终一致,即值是否有点旧?通过UI发出的所有命令都基于旧数据(自查询以来未更新的预测数据)。我们对此没有问题。就个人而言,我认为sagas可能被视为有点像客户机。PS我可以理解可能存在需要事务一致性数据的情况,那么我完全支持在saga中更多地使用事件来保持数据的最新。如果saga被视为客户机并按顺序接收事件/synchronous与其他投影一样,它使用的投影数据将始终同步。或者我是否遗漏了什么?