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的,那麼從數據裏直接查詢單表的數據就能夠拿到頁面須要的數據,大大提高讀取數據的性能,同時代碼也會極其的簡化,開發讀這一段代碼的開發人員甚至都不須要對業務有太多瞭解。