初识DDD 之CQRS

最近在学习实践DDD,接触到一个新的概念CQRS。以前以为就是读写分离,是基础设施层数据库层面的事情。学习以后才发现,并不只是这样,更应该是App应用层面的事。

缘起从github上找了一个DDD的symfony的例子,想参考一下,用于重构目前的项目。看了介绍和代码以后,发现了他的作者的西班牙语的油管视频。结合自动字幕翻译,觉得还不错,然后看了一下他们写的书。原版要60欧,于是在github上下载了一本电子版 Domian Driven Desgin in PHP。以下是阅读的笔记。

MVC模式的缺点

MVC用了那么久了,最大问题是controller过于庞大。违反了分离原则(Separation of Concerns)。补救的办法是使用依赖倒置。由于controller包含了过多的领域内容。所以首先拿领域模型下手。很多领域模型依赖底层的基础架构,比如数据库。所以按照Bob大叔(Robert C. Martin)的依赖倒置原则,高级模块(领域)不该依赖低级模块(基础设施),而且应该让它依赖抽象,即提出Repository。然后六角形架构被提出了。所有才有后来的 CQRS Event Sourcing

初识DDD 之CQRS

写模 型 Write model.

也叫Command model, 1

被改造为基于事件的写模型。本来直接写入数据库动作,改为发布一个写入事件。

record -> apply -> publish

而且写入事件直接找领域模型里定义。

读模型 Read model

被简化为从ElasticSerach这样的缓存读取。

同步

即然读写分开了,那么两个模型如何实现同步呢。引入了新概念Projection (投射器?)。基本上就是监听事件。当符合的事件被监听到了,就会调用投射器的投射动作。

投射的过程很可能是异步的,就是说会有延迟。为了解决延迟,在Repo里的save方法内,创建一个transaction(过程),把存储,事件放在一起。然后用投射器投射保存的事件。

最终解决了读模型和写模型之间的一致性(consistencies)问题。

Evnet Sourcing 事件溯源

就是可以通过记录完整的event可以还原一个状态。有点像数据库的bin log。