【DDD】CQRS 與規約模式的對比

     在軟件開發這個行業中,將開發工作外包是個常見的舉措。因爲軟件工程師對專業性程度要求非常高,而且薪酬普遍高出平均水平(工具人慚愧地拖了後腿),企業爲了節省成本和提高效率,在沒有軟件研發團隊的情況下,將開發工作外包給第三方公司或人員,是種行之有效的做法。

     而某些傳統金融公司,則非常壕氣。雖然持有着珍貴無比的架構師,卻整天用牛刀殺雞,讓架構師去做項目管理,讓架構師去寫需求文檔,讓架構師充當 PPT 架構師。

      工具人就很納悶了,偌大一個公司,連一個會寫需求的採購師都沒有麼? 工具人想了想,其實原本是有的,嫌工資低,跑了~

     好了,接下來進入正題:今天將討論兩種相互矛盾的 DDD 設計模式:CQRS 模式以及規約模式。

CQRS vs 規模模式

    這兩種 DDD 設計模式,從本質上講,有着巨大的不同。

      首先,我們先簡要的描述下這兩種模式的含義:CQRS 模式主張將一個統一的領域模型,拆分成一個讀模型,一個寫模型,這個看似簡單的方式,給開發者帶來了相當大的好處,其中最重要的是簡單。

       一般來說,應用程序的命令端和查詢端的需求截然不同。爲了解決這種顯著差異,爲這兩種不同場景分別引入單獨的模型是種很自然的方式。這同時,又大大降低了我們代碼的複雜性。

通過命令與查詢模型的分離,我們不必擔心用相同的代碼處理兩個完全不同的用例。因此,我們可以爲每個特定的場景,提供獨立的解決方案。這可以被認爲是單一職責原則在架構層次的一種體現。最後,你會得到兩個模型,每個模型只做一件事,而且做得很好。

       規約模式的主旨是將一段領域知識封裝到一個獨立的單元中,然後在不同的場景中重用,其場景主要分爲如下三種:數據檢索、內存驗證和創建新對象。

圖片

       其中,使用規約模式創建新對象的場景非常罕見,這裏先不做討論。而數據檢索是從數據庫中獲取數據,並查找到符合規約的數據記錄。內存驗證是指檢查某個對象是否符合規約中描述的標準。

       規約模式的有用之處在於可以讓開發人員避免領域知識的重複編寫,相同的規約定義既可用於驗證輸入數據,又可以從數據庫中過濾出需要顯示的用戶數據。

      而 CQRS 的主旨在於,將數據輸入與用戶數據查詢,切割成兩部分:

圖片

數據的數據校驗屬於命令端。因爲我們總在數據變更前,校驗入參的合理性。而數據檢索屬於讀取端。往往由客戶端發起後,系統查詢系統或數據庫中的數據內容。

CQRS 和規約模式在這裏有一個明顯的矛盾。其中,規約模式主張爲這兩個關注點使用一個域模型。而 CQRS 主張將領域模型一分爲二,並分別處理這些問題。

這裏我們可以發現了一個經典的爭議之處——DRY 原則(Don't Repeat Yourself)和松耦合原則之間的矛盾。這兩個原則都是非常基礎性的,它們都是軟件開發中的核心原則。

圖片

那麼,那種方式更好呢?

在絕大多數情況下,松耦合是成功的。

當在高耦合和領域知識複製之間進行取捨時候,我們往往應該兩害相權取其輕!複製領域知識確實給我們帶來了一定的冗餘,但是與問題相比,相對更容易被接受。

而高耦合——則可能是毀滅性的。在高度耦合的情況下,開發人員的會束手無策,因爲開發者不僅要考慮滿足組件自身內部的需求,還要考慮組件外部以及相關依賴方的訴求。

在數據校驗和用戶查詢兩種場景中,往往後者是比較難以被滿足的,如果要強行使得領域知識通用化,則會導致兩者皆不能被很好的滿足。

其實,規範模式僅適合在簡單的情況下使用——業務不需要複雜的查詢邏輯。在這種情況下,使用這種模式可能會很好。

在大型系統中,推薦儘可能地選擇鬆散耦合,適當容忍讀寫之間的領域知識重複,爲面臨的問題選擇最合適的解決方案的自由勝過 DRY 原則。

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/-XM01bf2O5kXneYQFc4qwg