CQRS是Command Query Responsibility Seperation(命令查询职责分离)的缩写。 世上不少事情都比较复杂,可是咱们只要进行一些简单的分类后,那么事情就简单了不少,好比咱们把人分为男人和女人,也能够把人分为大人和小孩,还好比,咱们说国内和国外,城市和农村。通过一些相似这样的划分,咱们的对不一样的类就有不一样的关注。 这样咱们就会有妇女儿童医院专门让女人生孩子,而不会建一个医院让男女都生孩子。数据库
CRUD (Create, Read, Update, Delete) 增查改删,咱们不少系统都是对数据的增查改删。过去咱们不少系统比较简单,基本上增长的数据就是你要查询的数据,因此不少时候其实一个简单的Excel就能搞定。 并且增删改查也足够的简单,因此咱们不少系统分层后在数据层Repository里还是对单表的增删改查,这样对很多的系统都符合。异步
可是,系统规模稍微大一点,咱们都知道咱们的数据库里的数据模型很难和咱们业务层须要的模型一致。 因而咱们引入了Domain Model, Repository里就会作Domain Model的来回转换性能
同时咱们在UI层要的数据,每每又和具体的Domain不一样,这个时候咱们又要定义一个ViewModel. 而这些ViewModel又是组合不一样的DomainModel得来。优化
传统的代码里的问题:orm
重要的原来把数据混在一块儿,复杂的查询至关难以优化。 尤为是数据库出现大量的Join 系统性能极速降低。blog
最重要的是咱们把读写都放在了一块儿,显得责任不够清晰,代码也更复杂了一些,好比读数据是不太关心事物的,读数据是不须要验证的,只有写的时候才须要作数据校验,这也比较符合SRP(单一职责),可是用CRUD的思惟是咱们全都混在了一块儿。排序
咱们仔细看CRUD, 其实能够更简单的分为读(R)和写(CUD), 咱们想一想大部分状况都是,一个方法要么是执行一个Command完成一个动做,要么就是查询返回数据。 好比咱们回答问题的人不该该去修改问题。内存
当咱们读写分离后,咱们对应的代码也会分离。开发
写的一端须要保证事物,因此通常数据存储为第三范式,
读的一端通常都是反范式能够避免Join操做,这样咱们只须要把数据存储为第一范式it
大部分的系统里写数据要远远少于读数据,而且通常都是每次修改不多的一部分数据,因此在写这端扩展都不是特别紧迫,读数据基本都远大于写数据的次数, 因此扩展就更重要。 咱们很难创建同一个Model 既能给写数据和读数据公用并且可以保证性能都比较好的。
查询端因为只是读数据,那么全部的方法应该都是返回数据,并且返回的数据就是界面直接须要的DTO, 这样能够减小传统的方法中把DomainModel映射为ViewModel或者DTO. 同时能够减小传统的领域里的一些混乱。
因为把读分离出去,因此咱们就只关注写,那么咱们写这一段须要保证事物,数据输入的验证,另一般写这一端都不须要及时的看到结果,因此大部分都须要一个void方法就能够,那么让咱们系统异步就更加方便。这样使系统的扩展性大大加强。
当我在一些系统中使用CQRS后,不少地方代码大大简化,好比我全部的写操做都是一个Command, 那么我定义一个UICommand, 让全部的Command集成这个,那么我能够在这个UICommand里作一些通用的处理,好比Validation
同时我只须要定义一个CommandBus, 而后把对应的CommandBus分发到对应的Handler里(我前面几篇有实例代码),那么代码的耦合度大大下降。
因为读这一端直接读数据,并且对数据库没有任何操做,那么咱们能够根据UI定义对应的DTO, 那么开发的时候咱们能够用Mock数据,至于数据怎么存的,那么咱们随后只要添加一层Thin Data Layer便可,实际上当咱们使用CQRS后,不少时候咱们把数据保存的时候都直接保存为Denormalize的,那么从数据里直接查询单表的数据就能够拿到页面须要的数据,大大提高读取数据的性能,同时代码也会极其的简化,开发读这一段代码的开发人员甚至都不须要对业务有太多了解。