这个问题源于不断发展的体系结构中的一种生存危机。从本质上讲,这要问-当读取模型是命令模型时,命令处理程序或事件处理程序应该更新数据存储吗?
我特别想知道是否有一种可以接受的方法来解决这个问题,如果沿着一条路线或另一条路线走会导致众所周知的问题。
详细地说,我们从域模型和一些存储库开始,这些存储库通过ORM读取和更新数据存储。这些存储库查询现有的域模型,然后将结果映射到DTO-我们目前尚未考虑创建单独的读取模型。该体系结构已经演变为使用CQRS方法,因此我们现在发布命令来创建域对象,并且在处理命令时引发事件。
至此,我们有了一些相当复杂的模型对象,并进行了各种计算,并且(最终)意识到,如果我们坚持这些计算,则读取速度会快得多。到目前为止,出乎意料。
有一种想法可以通过将字段添加到当前数据存储表中来持久化这些计算,从而使我们的命令模型更像是读取模型。因此,有人争辩说,我们应该在事件处理程序中更新数据存储,因为该模式表示应该修改读取模型。
也就是说,如果我们发出CreateItemCommand
由aCreateItemCommandHandler
引起的an ItemCreatedEvent
,由a引起的an ,然后由some处理ItemCreatedEventHandler
,CreateItemCommandHandler
则应简化为仅验证命令,并且对数据存储的实际修改应在ItemCreatedEventHandler
逻辑似乎很合理,但它似乎也产生了违反直觉的体系结构。我以为CQRS模式要求命令处理程序中的成功事件表明域模型中确实发生了某些变化?
我可以理解,不希望在命令处理程序中更新读取模型,而是根本不做任何事情,这似乎是错误的,特别是因为那样我们将无法信任ItemCreatedEvent
说实话。
这最终是主观的吗,还是有其他具体原因可以选择一种方法?
我认为您在CQRS论坛上遇到这样的问题可能会更好,因为这可能需要更多的来回讨论。再加上真正的答案可能是“取决于”。
就是说,听起来您正在将CQRS的“严格”定义与模式的更多“可接受”定义混合在一起。前者仅仅是读逻辑和写逻辑(及其结构)的分离。后者通常被定义为具有高度非规范化的读取模型,并且通常涉及某种形式的事件驱动的体系结构(在某些情况下包括事件源)。
听起来您是这两种想法的结合。我的第一个问题是:如果事件处理程序未创建非规范化的读取模型,它们将如何处理?他们只是在通知订户使缓存无效并重新获取数据吗?
但最重要的是,我认为您的直觉是正确的-该事件是在数据成功更新后发布的。如果一个处理程序的责任是更新(命令/写端)数据库,则已经通知其他订阅者发生了这种情况,如果数据库更新失败,则可能不正确。
因此,您的命令端应该更新数据库,并且读取的内容应该是查询标准化数据存储并将结果投影到非标准化结果集上。同样,事件(如果使用了所有事件)可能仅用于通知数据已更新,并且订户可能需要重新查询(同样,类似于缓存无效)。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句