CQRS(Command Query Responsibility Segregation),命令查询责任隔离。我最初听到的是Greg Young描述的一种模式。其核心思想是,可以使用与用于读取信息的模型不同的模型来更新信息。在某些情况下,这种分离可能很有价值,但请注意,对于大多数系统,CQRS会增加风险的复杂性。
人们用于与信息系统进行交互的主流方法是将其视为CRUD数据存储。我的意思是说,我们具有某种记录结构的思维模型,可以在完成处理后创建新记录,读取记录,更新现有记录以及删除记录。
在最简单的情况下,我们的交互都是关于存储和检索这些记录的。随着我们的需求变得越来越复杂,我们逐渐摆脱了这种模式。我们可能希望以与记录存储不同的方式查看信息,也许将多个记录折叠成一个记录,或者通过组合不同位置的信息来形成虚拟记录。在更新方面,我们可能会发现验证规则,这些规则仅允许存储某些数据组合,甚至可能推断出与我们提供的数据不同的数据。
发生这种情况时,我们开始看到信息的多种表示形式。当用户与信息交互时,他们使用该信息的各种表示形式,每个表示形式都是不同的表示形式。开发人员通常会构建自己的概念模型,以用来操纵模型的核心元素。如果使用域模型,则通常是域的概念表示。通常,还应使持久性存储尽可能接近概念模型。表示形式的多层结构可能会变得非常复杂,但是当人们这样做时,他们仍然将其解析为单个概念表示,该概念表示充当所有演示之间的概念整合点。 CQRS引入的更改是将概念模型拆分为单独的模型以进行更新和显示,按照CommandQuerySeparation的词汇分别称为Command和Query。这样做的理由是,对于许多问题,尤其是在更复杂的领域中,使用相同的命令和查询概念模型会导致更复杂的模型,但效果却不佳。
通过单独的模型,我们最通常地表示不同的对象模型,它们可能在不同的逻辑过程中运行,也许在单独的硬件上。一个网络示例将使用户看到使用查询模型呈现的网页。如果他们发起更改,则将更改路由到单独的命令模型进行处理,结果更改将传达给查询模型以呈现更新的状态。这里有很大的变化空间。内存中模型可以共享同一数据库,在这种情况下,数据库充当两个模型之间的通信。但是,他们也可以使用单独的数据库,从而有效地将查询方的数据库转换为实时ReportingDatabase。在这种情况下,两个模型或其数据库之间需要某种通信机制。这两个模型可能不是单独的对象模型,可能是相同的对象在其命令端和查询端具有不同的接口,就像关系数据库中的视图一样。但是通常当我听说CQRS时,它们显然是分开的模型。 CQRS自然适合其他一些建筑模式。当我们远离通过CRUD与之交互的单个表示形式时,我们可以轻松地转到基于任务的UI。 CQRS非常适合基于事件的编程模型。常见的是,CQRS系统被拆分为与事件协作进行通信的单独服务。这使这些服务可以轻松利用事件源。具有单独的模型会引发有关如何保持这些模型一致的难度,这会增加使用最终一致性的可能性。对于许多域,更新时需要很多逻辑,因此使用EagerReadDerivation简化查询侧模型可能很有意义。如果写入模型为所有更新生成事件,则可以将读取模型构造为EventPosters,使它们成为MemoryImages,从而避免大量数据库交互。 CQRS适用于复杂领域,该领域也可以从领域驱动设计中受益。何时使用它与任何模式一样,CQRS在某些地方有用,但在其他地方则没有用。许多系统确实适合CRUD思维模型,因此应采用这种风格。对于所有相关人员来说,CQRS是一次重大的思想飞跃,因此,除非收益值得实现,否则不应解决。尽管我成功地使用了CQRS,但到目前为止,我遇到的大多数情况都不是很好,因为CQRS被视为使软件系统陷入严重困境的重要力量。特别是,CQRS仅应在系统的特定部分使用