您的位置 首页 golang

Golang领域模型-CQRS

前言: CQRS 一词随着 DDD 一同被大众所熟悉,但是你有没有想过 CQRS 一词其实并非 DDD 独有,非 DDD 设计项目也能用,或许你正在用,但你不知道而已。本文介绍了一下 CQRS 是什么,在 DDD 中的作用,以及在项目中使用 CQRS 的好处。

一、什么是CQRS?

先从概念开始, CQRS Command Query Responsibility Segregation 的缩写,译成中文就是“命令与查询职责分离”。

顾名思义在我们写CRUD代码的时候,其实是有可分为两类操作,一类是 query (查询),一类是 command (增删改)。

记住以下几点:

  • 这个从分离关注点的角度来看,一个 对数 据无修改,一个则对数据有修改,二者的关注点是不同的,可以将其分离。
  • 二者从代码结构上看,能够将聚合根的臃肿程度降低。
  • 从性能上看,可以分别最大化读写的性能。

二、要不要用CQRS?

2.1 举例说明分层实践中的常规操作

不管你是否在进行DDD项目,其实你或多或少已经在接触或者使用 CQRS 了。

常规操作.png

上图的操作方式是不是很熟悉,相当常规的开发操作, Model 包里面建个 model ,然后在 DAO 层或者说 Repository 层中对改 model 进行增删改查操作。

一般而言这种操作是没有问题,或者说大家都是这么干的。那么我举个 栗子 ,看看大家是否又能找到这种开发中熟悉的感觉!

例如:电商项目,商品(Goods)服务中的订单操作,开始只需要实现两个方法:

 商品Repository
type GoodsRepository interface {
    Save(ctx context.Context, order *model.Goods) error
    GetByID(ctx context.Context, id int) (order *model.Goods, error)
}  

好了,开启迭代模式:

  1. 需要展示商品详情,但是所需字段比 model.Goods 中的字段要少。
  2. 需要展示 Goods 列表,列表中所需要的信息比商品详情中更少。
  3. 根据时间、商品种类,标签、售价、利润···等维度对商品进行筛选展示。
  4. 展示商品的供应商,而 供应商管理 属于另一个业务服务
  5. 。。。
    。。。

当你迭代完成,回头看你的代码,有没有发现:

  1. 你的 GoodsRepository 里面居然全是查询的操作代码。
  2. 为了应对不同的业务数据要求,需要将 model.Goods 中的数据进行裁剪与转换,这部分繁多的代码是放在 Service 中,还是在 Repository 中?是不是犯迷糊了,想想咱们 DDD 系列的第二篇文章《六边形架构》,或许你会有所收获。

CQRS 通过单独读模型解决上面的问题

2.2 CQRS的不同模式

CQRS 中的 读写分离 可以分为两个层次:

  1. 代码层面的读写分离。相同存储-读写模型分离.png

该模型的数据存在相同的 DateBase 中,通过在业务代码中使用不同的分离后的读写模型,减少了繁多且又没法避免的数据转换操作。

  1. 存储层面的读写分离。存储分离-模型分离.png该 CQRS 模型分离的更为彻底,不仅仅分离了读写模型,底层数据存储也一并分离了。读写操作分别写入 不容 的存储中,然后通过消息机制进行数据同步。

总结:

  1. 并不是项目中所有的 model 都需要进行 CQRS 改造,并不是所有的 CQRS 一定要将读写数据进行分离。
  2. 代码层面进行的 CQRS 有利于分离关注点,让代码层次结构更清晰,容易维护。
  3. 存储层次的 CQRS 应用于高性能查询场景,经常见于大型项目中 MySQL 存储商品,然后用 ES 查询商品等需要快速响应的场景。

项目代码

文章来源:智云一二三科技

文章标题:Golang领域模型-CQRS

文章地址:https://www.zhihuclub.com/100249.shtml

关于作者: 智云科技

热门文章

网站地图