30

Golang领域模型-CQRS

 3 years ago
source link: https://studygolang.com/articles/31180
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

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

一、什么是CQRS?

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

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

记住以下几点:

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

二、要不要用CQRS?

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

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

Ury2AzM.png!mobile

常规操作.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. 代码层面的读写分离。

    UZBv2mZ.png!mobile

    相同存储-读写模型分离.png

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

  1. 存储层面的读写分离。

    B7JVBfB.png!mobile

    存储分离-模型分离.png

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

总结:

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

三、Freedom中怎么使用CQRS?

目录

  • golang领域模型-开篇
  • golang领域模型-六边形架构
  • golang领域模型-实体
  • golang领域模型-资源库
  • golang领域模型-依赖倒置
  • golang领域模型-聚合根
  • golang领域模型-CQRS
  • golang领域模型-领域事件

项目代码 https://github.com/8treenet/freedom/tree/master/example/fshop

PS:关注公众号《从菜鸟到大佬》,发送消息“加群”或“领域模型”,加入DDD交流群,一起切磋DDD与代码的艺术!

有疑问加站长微信联系

iiUfA3j.png!mobile

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK