领域驱动设计-CQRS
CQRS 代表命令查询职责分离。这是我第一次听到Greg Young描述的模式。其核心概念是,您可以使用与用于读取信息的模型不同的模型来更新信息。在某些情况下,这种分离可能很有价值,但请注意,对于大多数系统,CQRS 会增加风险的复杂性。
人们用于与信息系统交互的主流方法是将其视为 CRUD 数据存储。我的意思是,我们有一些记录结构,我们可以心智模式 ç reate新纪录,[R EAD记录,ü PDATE现有记录,并ð elete记录时,我们与他们所做的。在最简单的情况下,我们的交互都是关于存储和检索这些记录。
随着我们的需求变得更加复杂,我们逐渐摆脱了这种模式。我们可能希望以不同于记录存储的方式查看信息,可能将多个记录合并为一个,或者通过组合不同位置的信息来形成虚拟记录。在更新方面,我们可能会发现验证规则只允许存储某些数据组合,甚至可能推断要存储的数据与我们提供的数据不同。
当这种情况发生时,我们开始看到信息的多种表示。当用户与信息交互时,他们使用此信息的各种表示形式,每一种表示形式都不同。开发人员通常会构建自己的概念模型,用于操作模型的核心元素。如果您使用域模型,那么这通常是域的概念表示。您通常还会使持久存储尽可能接近概念模型。
这种多层表示的结构可能会变得非常复杂,但是当人们这样做时,他们仍然将其分解为单个概念表示,作为所有表示之间的概念整合点。
CQRS 引入的更改是将该概念模型拆分为单独的模型以进行更新和显示,在CommandQuerySeparation词汇表之后分别将其称为 Command 和 Query 。基本原理是,对于许多问题,尤其是在更复杂的领域中,具有相同的命令和查询概念模型会导致更复杂的模型两者都做不好。
分离模型通常是指不同的对象模型,可能运行在不同的逻辑进程中,也可能运行在不同的硬件上。Web 示例将看到用户查看使用查询模型呈现的网页。如果他们发起更改,将更改路由到单独的命令模型进行处理,则将产生的更改传达给查询模型以呈现更新的状态。
这里有相当大的变化空间。内存模型可能共享同一个数据库,在这种情况下,数据库充当两个模型之间的通信。然而,它们也可能使用单独的数据库,有效地使查询端的数据库成为实时ReportingDatabase。在这种情况下,两个模型或其数据库之间需要某种通信机制。
这两个模型可能不是单独的对象模型,可能是相同的对象在其命令端和查询端具有不同的接口,就像关系数据库中的视图一样。但通常当我听到 CQRS 时,它们显然是独立的模型。
CQRS 自然适合其他一些架构模式。
- 当我们远离通过 CRUD 与之交互的单一表示时,我们可以轻松地转向基于任务的 UI。
- CQRS 非常适合基于事件的编程模型。通常会看到 CQRS 系统拆分为与Event Collaboration通信的单独服务。这允许这些服务轻松利用事件溯源。
- 拥有单独的模型会引发关于保持这些模型一致性有多难的问题,这增加了使用最终一致性的可能性 。
- 对于许多域,更新时需要很多逻辑,因此使用EagerReadDerivation来简化查询端模型可能是有意义的 。
- 如果写入模型为所有更新生成事件,您可以将读取模型构建为EventPosters,允许它们成为MemoryImages从而避免大量数据库交互。
- CQRS 适用于复杂的领域,也可以从领域驱动设计中受益。
何时使用
与任何模式一样,CQRS 在某些地方很有用,但在其他地方则不然。许多系统确实适合 CRUD 心智模型,因此应该以这种方式完成。CQRS 对所有相关人员来说都是一次重大的精神飞跃,因此除非带来的好处值得一试,否则不应解决。虽然我遇到了 CQRS 的成功使用,但到目前为止,我遇到的大多数情况都不是很好,CQRS 被视为使软件系统陷入严重困境的重要力量。
特别是 CQRS 应该只用于系统的特定部分(DDD 术语中的BoundedContext)而不是整个系统。按照这种思维方式,每个有界上下文都需要自己决定如何对其进行建模。
到目前为止,我看到了两个方向的好处。首先,使用 CQRS 可能更容易处理一些复杂的域。然而,我必须强调,CQRS 的这种适用性在很大程度上是少数情况。通常在命令和查询端之间有足够的重叠,共享模型更容易。在不匹配的域上使用 CQRS 会增加复杂性,从而降低生产力并增加风险。
另一个主要好处是处理高性能应用程序。CQRS 允许您将负载与读取和写入分开,从而允许您独立扩展每个负载。如果您的应用程序发现读取和写入之间存在很大差异,这非常方便。即使没有,您也可以对两端应用不同的优化策略。这方面的一个示例是使用不同的数据库访问技术进行读取和更新。
如果您的域不适合 CQRS,但您有要求增加复杂性或性能问题的查询,请记住您仍然可以使用ReportingDatabase。CQRS 对所有查询使用单独的模型。使用报告数据库,您仍然使用主系统进行大多数查询,但将要求更高的查询卸载到报告数据库。
尽管有这些好处,但您在使用 CQRS 时应该非常谨慎。许多信息系统非常符合信息库的概念,信息库的更新方式与读取方式相同,向此类系统添加 CQRS 会显着增加复杂性。我当然见过这样的案例,它严重拖累了生产力,给项目增加了不必要的风险,即使是在一个有能力的团队手中。因此,虽然 CQRS 是一种很好的工具箱模式,但请注意,它很难很好地使用,如果处理不当,很容易砍掉重要的部分。
-摘自 https://martinfowler.com/bliki/CQRS.html
领域驱动设计-CQRS的更多相关文章
- IDDD 实现领域驱动设计-一个简单的 CQRS 示例
上一篇:<IDDD 实现领域驱动设计-CQRS(命令查询职责分离)和 EDA(事件驱动架构)> 学习架构知识,需要有一些功底和经验,要不然你会和我一样吃力,CQRS.EDA.ES.Saga ...
- IDDD 实现领域驱动设计-CQRS(命令查询职责分离)和 EDA(事件驱动架构)
上一篇:<IDDD 实现领域驱动设计-SOA.REST 和六边形架构> 阅读目录: CQRS-命令查询职责分离 EDA-事件驱动架构 Domin Event-领域事件 Long-Runni ...
- [.NET领域驱动设计实战系列]专题十:DDD扩展内容:全面剖析CQRS模式实现
一.引言 前面介绍的所有专题都是基于经典的领域驱动实现的,然而,领域驱动除了经典的实现外,还可以基于CQRS模式来进行实现.本专题将全面剖析如何基于CQRS模式(Command Query Respo ...
- DDD领域驱动设计:CQRS
1 前置阅读 在阅读本文章之前,你可以先阅读: DDD领域驱动设计是什么 DDD领域驱动设计:实体.值对象.聚合根 DDD领域驱动设计:仓储 MediatR一个优秀的.NET中介者框架 2 什么是CQ ...
- DDD 领域驱动设计-看我如何应对业务需求变化,愚蠢的应对?
写在前面 阅读目录: 具体业务场景 业务需求变化 "愚蠢"的应对 消息列表实现 消息详情页实现 消息发送.回复.销毁等实现 回到原点的一些思考 业务需求变化,领域模型变化了吗? 对 ...
- 初探领域驱动设计(2)Repository在DDD中的应用
概述 上一篇我们算是粗略的介绍了一下DDD,我们提到了实体.值类型和领域服务,也稍微讲到了DDD中的分层结构.但这只能算是一个很简单的介绍,并且我们在上篇的末尾还留下了一些问题,其中大家讨论比较多的, ...
- 领域驱动设计实战—基于DDDLite的权限管理OpenAuth.net
在园子里面,搜索一下“权限管理”至少能得到上千条的有效记录.记得刚开始工作的时候,写个通用的权限系统一直是自己的一个梦想.中间因为工作忙(其实就是懒!)等原因,被无限期搁置了.最近想想,自己写东西时, ...
- 一缕阳光:DDD(领域驱动设计)应对具体业务场景,如何聚焦 Domain Model(领域模型)?
写在前面 阅读目录: 问题根源是什么? <领域驱动设计-软件核心复杂性应对之道>分层概念 Repository(仓储)职责所在? Domain Model(领域模型)重新设计 Domain ...
- [转]DDD领域驱动设计基本理论知识总结
领域驱动设计之领域模型 加一个导航,关于如何设计聚合的详细思考,见这篇文章. 2004年Eric Evans 发表Domain-Driven Design –Tackling Complexity i ...
随机推荐
- 【LeetCode】871. Minimum Number of Refueling Stops 解题报告(Python)
作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 贪心算法 日期 题目地址:https://leetc ...
- 【LeetCode】219. Contains Duplicate II 解题报告(Python)
作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 使用set 使用字典 日期 题目地址:https:/ ...
- 「算法笔记」BSGS 与 exBSGS
一.离散对数 给定 \(a,b,m\),存在一个 \(x\),使得 \(\displaystyle a^x\equiv b\pmod m\) 则称 \(x\) 为 \(b\) 在模 \(m\) 意义下 ...
- java-git 暂存
在接到需求以后,直接在master上开发了,到提交的时候才想起来忘记新建版本分支了,直接提交到master会影响到其他人. 这时候就想着将本地编辑的代码,没有提交的代码暂存起来,然后新建一个新分支,再 ...
- 读书笔记markdown模板
读书笔记 书名 作者 出版社 阅读日期 书籍背景 书摘/ 笔记 批注 总结& 收获 读完每一本书,把书中的知识转化为「自己的智慧」,才是最扎实的收获- 他山之石 摘录相关精彩书评-
- Java初学者作业——分别计算两个整数加、减、乘、除的结果并显示,要求除法保留两位小数。
返回本章节 返回作业目录 需求说明: 分别计算两个整数加.减.乘.除的结果并显示,要求除法保留两位小数. 实现思路: 接收用户控制台输入的两个整数. 实现两个整数的加.减.乘.除的运算并输出结果. 除 ...
- MySQL基础操作指南
启动停止MySQL服务 1.Windows服务窗口启动:开始 → 运行 → services.msc → 找到MySQL 56服务 2.MySQL命令启动:开始 → 运行 → 管理员权限运行cmd → ...
- TortoiseGit使用ssh-keygen生成的私钥
1.说明 使用TortoiseGit自带的PuTTY Key Generator工具, 把ssh-keygen生成的私钥转换为Putty使用的.ppk文件, 然后在拉取Git代码时, 加载对应的.pp ...
- LDAP客户端安装
安装环境: 10.43.159.7 客户端 使用ldap客户端验证登陆: 用户为10.43.159.9服务端上面创建的ldap:zdh1234 1.安装LDAP client认证需要的pam包 yum ...
- Jenkins_创建任务以及定时启动(2)
一.创建任务 1.点击New Item 2.输入用户,单击Freestyle project,点击OK 3.填写构建步骤,因为是安装在linux上的,所以我们选择Execute shell,随意输入一 ...