Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Design patterns 在没有显式读取模型的CQRS体系结构中,哪个处理程序更新数据存储?_Design Patterns_Architecture_Cqrs - Fatal编程技术网

Design patterns 在没有显式读取模型的CQRS体系结构中,哪个处理程序更新数据存储?

Design patterns 在没有显式读取模型的CQRS体系结构中,哪个处理程序更新数据存储?,design-patterns,architecture,cqrs,Design Patterns,Architecture,Cqrs,这个问题产生于不断发展的体系结构中的一种生存危机。本质上,它归结为这样一个问题:当读取模型是命令模型时,命令处理程序还是事件处理程序应该更新数据存储 特别是我很想知道是否有一个公认的方法来解决这个问题,如果沿着一条或另一条路线走下去,是否会导致众所周知的问题 为了详细说明,我们从一个域模型和一些存储库开始,通过ORM读取和更新数据存储。这些存储库查询现有的域模型,我们将结果映射到DTO——此时我们没有考虑创建单独的读取模型。该体系结构已经演变为使用CQRS方法,因此我们现在发出命令来创建域对象,

这个问题产生于不断发展的体系结构中的一种生存危机。本质上,它归结为这样一个问题:当读取模型是命令模型时,命令处理程序还是事件处理程序应该更新数据存储

特别是我很想知道是否有一个公认的方法来解决这个问题,如果沿着一条或另一条路线走下去,是否会导致众所周知的问题

为了详细说明,我们从一个域模型和一些存储库开始,通过ORM读取和更新数据存储。这些存储库查询现有的域模型,我们将结果映射到DTO——此时我们没有考虑创建单独的读取模型。该体系结构已经演变为使用CQRS方法,因此我们现在发出命令来创建域对象,并且在处理命令时引发事件

在这一点上,我们现在有了一些相当复杂的模型对象,所有类型的计算都在进行,并且(最终)意识到,如果我们坚持这些计算,读取速度会快得多。到目前为止还没有预料到

有一个想法是通过向当前数据存储表中添加字段来持久化这些计算,从而使我们的命令模型更像一个读取模型。因此,有人认为,我们应该更新事件处理程序中的数据存储,因为模式认为应该在那里修改读取模型

i、 e.如果我们发出一个
CreateItemCommand
,该命令由一个
CreateItemCommandHandler
处理,该处理会引发一个
ItemCreatedEvent
,然后由一些
ItemCreateDevenHandler
处理,然后,应将
CreateItemCommandHandler
简化为仅验证命令,并且应在
ItemCreatedEventHandler

这种逻辑似乎合理,但似乎也创造了一种违反直觉的架构。我认为CQRS模式要求来自命令处理程序的成功事件指示域模型中实际发生了变化

我可以理解,不想更新命令处理程序中的读取模型但不做任何事情似乎是错误的,特别是因为我们无法相信
ItemCreatedEvent
说的是实话


这最终是主观的,还是有其他具体的原因可以这样或那样做?

我认为你在CQRS论坛上遇到这样的问题可能会更幸运,因为这可能需要更多的来回讨论。另外,真正的答案可能是“视情况而定”

这就是说,听起来您将更多的模式定义与“已接受”的模式混合在一起。前者仅仅是读逻辑和写逻辑(及其结构)的分离。后者通常被定义为具有高度非规范化的读取模型,并且通常涉及某种形式的事件驱动体系结构(在某些情况下包括事件源)


听起来你好像是这两种想法的混合体。我的第一个问题是:如果事件处理程序不创建非规范化的读取模型,它们会做什么?他们只是通知订阅者使缓存和重新蚀刻数据无效吗

但归根结底,我认为你的直觉是正确的——事件是在数据成功更新后发布的。如果一个处理程序的责任是更新(命令/写入端)数据库,那么其他订阅者已经被通知发生了这种情况,如果对数据库的更新失败,这种情况可能不是真的

因此,您的命令端应该更新数据库,您的读取应该是查询规范化数据存储并将结果投影到非规范化结果集。同样,事件(如果使用)可能只是用于通知数据已更新,订阅者可能需要重新查询(同样,如缓存失效)。

“这个问题产生于不断发展的体系结构中的一种生存危机。本质上,它归结为这样一个问题:当读取模型是命令模型时,命令处理程序还是事件处理程序应该更新数据存储?”

模型是否共享其实并不重要。在理想情况下,您可能会有单独的模型,但只要您将事件和命令的处理程序分开,您就很了不起,您当然不会从数据库优化(读/写)中受益但是你已经将关注点分开了。别忘了,现在你将使用同一个模型,但是将来呢?即使你使用同一个模型,也要保持处理程序分开,这样你就更容易更改为分开的模型。无论如何,该层应该通过使用存储库模式隐藏起来。命令始终是e引发变化的事件,而不是事件;在结构良好的域中,处理事件并发出另一个命令

更新

为了清楚起见,您可以在事件处理程序中更改存储库,但只能更改复制数据、不属于您的服务的数据或读取模型中的数据,即:

假设您有两个服务,客户机和仓库,在客户机服务中您有客户机的详细信息,例如注册和地址“服务应该是独立的,因此,如果下了新订单并且要求仓库发货,那么仓库必须已经有了地址,因此在结构良好的域中,当客户注册时,客户的服务会发布一个带有注册数据的事件,其中可能包括地址,仓库服务处理该事件,提取事件的地址部分,并将其持久化到其持久层

因此,在本例中,事件可以在存储库中执行更改,但只能对镜像数据执行更改。我认为让它变得更有意义是很重要的