领域驱动设计:CQRS 和事件源的强大功能

news/2024/11/15 9:34:42/文章来源:https://www.cnblogs.com/zhaoqinyun/p/18301043

CQRS/ES 如何重新定义构建可扩展系统。

 

在过去的 15 年里,我一直在深入研究领域驱动设计 (DDD),每一步都在学习和改进。我一直很好奇,尤其是当你深入挖掘时,简单的客户请求会变得更加复杂。我特别感谢EventStorming这样的工具,它帮助揭示看似简单需求背后的真实流程和事件,不仅让我,而且让客户和领域专家都清楚一切。

大约 10 年前,我首次在业务应用程序中使用了命令查询职责分离 (CQRS) 和事件源 (ES)。这种方法让我大开眼界,尽管它确实带来了挑战。但是,对我来说,最大的改变之一是意识到 CQRS 如何自然地使数据单向流动。这种单向流动不仅仅是为了保持井然有序;它改变了我们构建、维护和扩展系统的方式。这意味着我们可以将更改数据的操作与读取数据的操作分开。这不仅消除了许多潜在的混乱;它还为我们提供了一种处理复杂系统的直接方法。

虽然我非常喜欢在项目中使用 CQRS/ES,但这并不是成功应用 DDD 的唯一方法。DDD 是一个拥有大量工具和方法的庞大领域,最好的工具和方法实际上取决于您正在从事的工作以及团队的技能水平。CQRS 非常适合我,尤其是在处理复杂系统时,将读写操作分开可以使一切更易于管理。每个项目都是独一无二的,在很多情况下,其他策略可能是更好的选择。

 

CQRS 的好处

但是什么是 CQRS?这是一个强大的概念。其核心是将写入数据(命令)和读取数据(查询)的任务分为两个不同的部分。这种分离旨在明确系统结构、界定职责并提高从系统读取数据的速度。

我注意到,由于读写存储的严格分离,CQRS 经常被视为一种性能优化策略。虽然提高性能确实是一个显著的优势,但它只是触及了好处的表面。

CQRS 提供的功能远不止这些。首先,这种方法为我们提供了一个干净、有条理的结构。这种组织结构延伸到领域关注的极佳垂直部分,这意味着我们可以专注于特定领域,而不会迷失在复杂的海洋中。

另一个巨大的优势是强制单向数据流动。这不仅仅是为了保持数据移动的整洁;它从根本上改变了我们设计和思考系统的方式。它确保我们的数据以可预测的模式移动,减少混乱和错误。

CQRS 还促使我们更多地关注行为而不仅仅是数据。这意味着我们在设计系统时会考虑现实世界的行为和后果,避免使用软件项目中常见的贫血领域模型。贫血领域模型就像没有肌肉的骨架——它可能拥有所有部分,但无法独立完成很多工作。CQRS 帮助我们避免这种情况,确保我们的模型具有丰富的行为和功能。

CQRS 中的关注点分离功能使我们能够轻松增强系统视图。由于读取模型是分开的,我们可以调整和改进它们,而无需触及应用程序的核心逻辑。这种灵活性对于不断发展的系统来说非常宝贵,可以满足新的需求或解决新的见解,而无需进行重大改革。

 

镜像数据库不是 CQRS

我看到一种趋势,即 CQRS 中的读写分离被解释为拥有两个具有相同数据模型的镜像数据库,并依靠复制进行同步。然而,这种方法可能错过了 CQRS 的真正意义。

反模式:镜像数据库不是 CQRS

问题的核心在于,写入和读取使用相同的数据模型会导致耦合度过高。CQRS 的优势在于它允许独立性,允许写入端开发丰富的行为驱动模型,而读取端则针对查询进行优化。跨数据库镜像数据模型会将两端联系得太紧密,从而限制系统的灵活性以及两端根据需要进行演进的潜力。

此外,这种设置还存在将写入模型变成围绕数据库架构的薄逻辑层而不是健壮的域模型的风险。它使我们陷入以数据为中心的思维模式,业务逻辑并没有处于应有的位置 — 嵌入域本身。

重要的是要理解写入模型与读取模型有很大不同。否则,所有的灵活性和能力都会丧失。

 

使用 CQRS/ES 实现数据行为

对我来说,将 CQRS 与事件源相结合的一个重要好处是,它将焦点转移到行为上,而不仅仅是数据模型上,从设计上来说就是如此。这种观点至关重要,因为它使我们的开发工作与我们的软件旨在代表的现实世界流程和逻辑更加紧密地结合在一起。传统的开发实践往往过于强调数据的结构——如何存储、检索和修改数据。虽然这种方法很重要,但它也可能导致我们忽视生成和使用这些数据的实际行为和交互。相信我,我见过不止一次这种情况。当 CQRS 与 ES 结合使用时,会扭转这种关注点。它鼓励我们围绕推动变革的业务事件和行动来建模我们的系统,而不仅仅是这些变化影响的数据。

这意味着我们的代码以更具表现力的方式反映了业务逻辑。我们不是简单地在表中插入、更新或删除行,而是捕获有意义的业务事件,例如“下订单”、“用户创建”或“库存更新”。这使我们的模型更加丰富和有意义。它提高了我们随着时间的推移重新思考和改进系统的能力。

CQRS/ES:单向流,有意义的模型。

 

投影的力量

CQRS 模式最重要的方面之一是投影概念,它本质上是读取模型的基础。这种方法对我们在应用程序中处理数据的方式有着深远的影响,因为最重要的是,它使我们摆脱了与在写入端表示数据相关的限制。这种分离确保了重点仍然放在准确捕获行为和域事件上,而不会增加查询或显示数据的复杂性。

CQRS/ES 投影 - 以及单向数据流。

读取端独立性提供了灵活性,可以根据各种需求定制数据投影。无论是构建数据以实现高效查询,还是针对特定视图进行优化,投影都可以根据您的需求进行设计。此功能旨在满足当今的需求,也可以轻松调整和扩展以满足未来的需求,而无需触及现有代码。

对于投影,无需修改现有结构或更改写入端的逻辑。相反,我们可以简单地创建一个新的、独立的模块,专门用于根据需要投影和分析数据。这种模块化和可扩展性是一个巨大的优势,使我们的系统能够有机地发展,而不会损害核心域逻辑的完整性。

CQRS/ES:从投影查看数据

 

结束语

CQRS 与事件源相结合,改变了我们思考和构建软件系统的方式。通过分离数据的写入和读取,我们获得了一个干净、有组织的结构,从而提高了性能和可扩展性。更重要的是,这种方法将我们的重点转移到行为和现实世界的行动上,确保我们的模型功能丰富,并与它们所代表的领域保持一致。投影还允许我们在不触及现有代码的情况下调整和扩展我们的系统,这突显了 CQRS/ES 的灵活性和稳健性。

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/743374.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

k8s简介

一、K8S 概览 1)K8S 是什么? K8S 是Kubernetes的全称,源于希腊语,意为“舵手”或“飞行员”,官方称其是:用于自动部署、扩展和管理“容器化(containerized)应用程序”的开源系统。翻译成大白话就是:“K8S 是负责自动化运维管理多个跨机器 Docker 程序的集群”。 2) K…

flutter Error: unable to locate asset entry in pubspec.yaml: assets/fonts/Lato-Regular.ttf

在pubspec.yaml中添加font的时候出现这个问题 发现是因为我放的文件夹不对,需要放在根目录下(但是我不知道为什么android studio里没有显示一些文件夹) 本来放在这里 一直不对后来在文件夹找了一下放到lib里 新建了assets文件夹

详解工单系统

工单系统在人类早期的行为活动中就一直存在的理念,是人类关于工作流程的管理和记录。随着计算机软件的不断发展,工单系统由线下转为线上,提升了问题传达的准确性、处理效率以及数据的长久留痕可追溯等,应用领域也日渐广泛。本文将着重介绍工单的概念、不同领域工单系统简介…

Vue 3 后端错误消息处理范例

前端如何存储处理后端返回的错误信息,并按不同来源绑定到页面,例如显示在不同输入框的周围。这样即可实现清晰的错误显示。1. 错误消息格式 前后端消息传递时,我们可以通过 json 的 errors 字段传递错误信息,一个比较好的格式范例为: {errors: {global: ["网络错误&q…

OpenDiary 24.7

致敬传奇耐拖王现在是,7 月 13 日。距离上一次写日记过去了 58 天 致敬传奇耐拖王 xiwon那么,在鼠鼠肘赢牢大之前的这段时间,what happened, on earth?五月下旬,前去了西安邀请赛,打的一坨。回来之后写了一点游记,但是居然还没有写完 那么到底为什么没有写完呢?这要从很…

我用cpca 截取地址中的省市区,突然就乱了,这是什么原因

大家好,我是Python进阶者。 一、前言 前几天在Python钻石交流群【逆光】问了一个Python数据处理的问题,问题如下:请问一下 我用cpca 截取地址中的省市区,突然就乱了,这是什么原因? 二、实现过程 这里【瑜亮老师】给了个思路如下:看着好像是行弄乱了。 【不上班能干啥!】…

k8s字段选择器

目录一、概述二、基本语法三、支持的字段1、错误示例2、支持的字段列表四、支持的操作符1、示例五、跨多种资源类型使用字段选择器 一、概述 在Kubernetes中,字段选择器(Field Selectors)和标签选择器(Label Selectors)是两种不同的查询机制,用于过滤和选择特定的资源。字…

three.js+vue污水处理厂数字孪生平台智慧城市web3d

案例效果截图如下: 主场景三维逻辑代码如下:<template><div class="whole"><!-- threejs画布 --><div id="threejs" ref="threejs"></div><!-- 污水厂模型加载进度条 --><a-progress:stroke-color=&quo…

反射DLL注入原理解析

反射 DLL 注入又称 RDI,与常规 DLL 注入不同的是,它不需要 LoadLibrary 这个函数来加载 dll,而是通过 DLL 内部的一个函数来自己把自己加载起来,这么说可能会有一点抽象,总之这个函数会负责解析DLL文件的头信息、导入函数的地址、处理重定位等初始化操作,先不用理解这个函…

Neo4j:图数据库的革命性力量

Neo4j 首席技术官 @prathle 撰写了一篇出色的博文,总结最近围绕 GraphRAG 的热议、我们从一年来帮助用户使用知识图谱 + LLM 构建系统中学到的东西,以及我们认为该领域的发展方向。Neo4j一时间又大火起来,本文将带你快速入门这神奇的数据库。前言 Neo4j是一款符合ACID标准的…