手把手教你落地 DDD
钟敬
Thoughtworks 首席咨询师、数字化转型与运营团队 DDD 负责人
19697 人已学习
新⼈⾸单¥59
登录后,你可以任选4讲全文学习
课程目录
已完结/共 45 讲
AIGC特别策划 (2讲)
结束语&结课测试 (2讲)
手把手教你落地 DDD
15
15
1.0x
00:00/00:00
登录|注册

31|CQRS(上):实现查询功能有什么诀窍?

你好,我是钟敬。
前面几节课我们讲完了限界上下文。接下来的两节课,我们将学习一个和查询功能相关的模式——CQRS。虽然 《领域驱动设计》原书里没有这个模式,但近年来,CQRS 常常和 DDD 结合使用。
不过也有人对 CQRS 有不同意见。这是因为,CQRS 实际上也有不同的变化,这就造成了不同的人对 CQRS 的理解也不太一样。学完这两节课,我想你就知道怎么分辨了。
CQRS 是 Command Query Responsibility Segregation 的简称,中文是 “命令查询职责分离”。这个名字乍听起来也不太好理解,咱们还是从业务需求开始,一步一步地理解。

查询功能遇到的问题

在第三个迭代中,在工时管理上下文,增加了更多的查询和统计需求。
我们先看一个简单的需求,给定一个工时项,要求查询出这个工时项下的所有工时记录,并显示在屏幕上。要求每条返回记录的字段包括“员工号”“员工姓名”“日期”“工时”和“备注”,并根据员工号和日期升序排序。为了简化问题,我们先不考虑“不在本级报工时”以及“父子工时项”的问题。
我们回忆一下工时项管理的领域模型。
根据之前学习的数据库设计以及上下文映射的方法,假定我们选择的是在本地建立员工表,并从“基础信息管理”上下文映射员工信息的策略。那么本地数据库会有员工(emp)表和工时记录(effort_record)表。
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结

CQRS(Command Query Responsibility Segregation)是一种重要的模式,旨在解决领域模型中查询功能的繁琐和性能问题。本文首先介绍了查询功能的挑战,以及CQRS的概念和重要性。作者强调了命令和查询的不同职责,以及采用不同方式处理的必要性。 文章分析了CQRS的不同理解层面,包括代码结构分离和数据库结构分离。在数据库结构分离方面,作者介绍了通过反规范化设计创建适用于查询的表,以解决性能问题。另外,还介绍了“查询模型图”,用于系统化设计查询模型。 总的来说,本文通过讲解查询功能的问题和CQRS的概念,引出了CQRS模式的重要性和实现方式。读者可以从中了解到CQRS的核心思想,以及在实际应用中的不同策略和权衡。文章内容涵盖了CQRS模式的重要性、实现方式以及相关策略,对于想要深入了解CQRS的读者具有很高的参考价值。

仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《手把手教你落地 DDD》
新⼈⾸单¥59
立即购买
登录 后留言

全部留言(10)

  • 最新
  • 精选
  • 虚竹
    还有一种常用方式,是写到mysql里,异构到mongo里一份用来查询,

    作者回复: 是的

    2023-02-24归属地:北京
    4
    5
  • 赵晏龙
    好多人都觉得CQRS就一定是EventSourcing,就一定是两个库。我也是去年的时候突然顿悟,其实CQRS的本质就是冗余。 1、我会考虑进一步抽象,甚至查询模型直接记录统计的最终数据。 2、分表能够分离变与不变的东西,但会增加额外的数据同步开发工作和认知负载,如果加上历史数据的迁移,工作量会越来越多。不分表会影响领域的相对不变性,但是认知负载可能会相对较低。这将会是一个权衡,没有银弹。

    作者回复: CQRS的本质,除了冗余,还有一个是否绕过领域模型的问题,或者说,在领域模型之外,是否专门考虑“查询模型”的问题。 第一题,是个不错的思路 第二题,还有一个角度供您参考,如果分开两套表,由于各自比较单纯,是否反而降低了认知负载?

    2023-03-10归属地:湖南
    3
    3
  • 南山
    查询的代码中 repository放在了application层,依赖dto,这里的repository跟领域层的那个是什么关系?或者是两个吗?

    作者回复: 首先,课程里没有说查询代码的repository依赖DTO。 其次,查询的repository用来直接查出客户端需要的DTO,领域层的查出聚合,这一点是不同的。两者的名字一样,只是为了方便。也可以起不同的名字。

    2023-03-04归属地:江苏
    2
  • Fredo
    1. 单独搞一张宽表,冗余存用来查询呢。如果是报表可能会这样做 2. 直接在原先的表上弄会有一定的风险,数据一致性要特别关注;维护两套的话,关注点分离,职责清晰,但维护成本上去了。

    作者回复: 不错

    2023-03-02归属地:广东
    2
    2
  • aoe
    我们大部分让人头疼的统计数据,就是独立一张表存储的,单表查询出结果,遇到数据有问题时,重新计算一遍。 相比复杂的连表查询,这种方式轻松愉快,实现简单,额外支出的存储空间值了:空间换时间

    作者回复: 是的,这已经是CQRS思想的运用了。

    2023-03-01归属地:浙江
    1
  • 周昌武
    如果后续查询需求变化,需要新增显示字段,冗余的 emp_effort_record是不是就变得鸡肋了?这种情况有哪些解决方案? 1. 提前考虑emp_effort_record表多冗余些字段(存在未来变化不确定性,虽然是降低了) 2. 需求变化时emp_effort_record添加新字段,同时修改同步方案(可能需要补历史数据,根据对历史数据显示要求而定) 钟老师还有其他好的方案吗

    作者回复: 第二种比较好

    2024-03-05归属地:广东
  • 无问
    cqrs的模型转换要另外在弄一套builder了嘛

    作者回复: 不太理解您的问题,您说的模型转换指什么?

    2023-10-10归属地:上海
  • + 糠
    cqrs没有领域层,会不会以后服务根据聚合拆分,改起来也比较麻烦?

    作者回复: 服务不应该根据聚合拆分,应该根据限界上下文拆分。

    2023-06-30归属地:广东
    2
  • 问题1:先查询出符合条件的父子工时项id,再用多个工时项id进行查询 问题2:原来领域模型表反规范化的方式避免了2套数据源同步的复杂度,增加了写逻辑的复杂度,另外一套表的方式关注点清晰,能实现业务层的读写分离,但需要保证数据同步的稳定性及时效性 还请老师答疑,谢谢

    作者回复: 问题1:也可以单独建一个符合查询架构的表,预先把数据处理好,之后直接查询。 问题2: 补充一点,如果一套表的话,设计更容易腐化。

    2023-05-16归属地:北京
  • 神经蛙
    除了博主这篇文章的观点之外,我还有一种理解,修改会对一个对象产生影响,属于业务。而查询没有业务属性,它只是查询出某一时刻内某个领域实体对象的状态。所以把他们分离能更好的让开发关注到业务上去。但是我觉得cqrs这样拆好繁琐。ddd本身落地就够繁琐的了。。

    作者回复: 假如觉得CQRS带来的麻烦大于收益,就不要用。直到某一天发现情况逆转,再用。

    2023-03-03归属地:广东
收起评论
显示
设置
留言
10
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部