l
顯示具有 盡信書不如無書 標籤的文章。 顯示所有文章
顯示具有 盡信書不如無書 標籤的文章。 顯示所有文章

2020年9月10日 星期四

Clean Architecture之CQRS Pattern

September 10 14:20~15:20

▲跳出盒子思考,有時候跨層存取也是OK滴


緣起

前幾天Teddy在讀《Domain Modeling Made Functional: Tackle Software Complexity with Domain-Driven Design and F#》,看到第3章有一個段落談Code Structure Within a Bounded Context。這是一個很有趣的議題但談得人並不多,既使是這本書也沒有講得很詳細,但其中有一張如圖1所示的圖引起我的注意。


▲圖1:每一個end-to-end功能橫切軟體架構的每一層,圖片節錄自《Domain Modeling Made Functional: Tackle Software Complexity with Domain-Driven Design and F#》,53頁。

***

Clean Architecture

看到圖1讓Teddy想起《Clean Architecture》第34章談到四種區分package的方法,回頭把這一章又讀了一次,看到圖2這段文字:


▲圖2:《Clean Architecture》 311頁。


當年Teddy在讀這段文字的時候並沒參透這個問題:為什麼在CQRS架構中就特意允許跨層參考?」雖然Teddy知道CQRS架構模式但自己沒有實際實作過,但這次讀懂了。

前陣子讀了一本奇書:《CQRS》。如圖3所示,書中明白建議:

  • 領域驅動設計(Domain-Driven Design;DDD)只需要應用在那些會改變系統狀態的Command。換句話說,只需要在Command套用DDD與Clean Architecture。
  • 針對不會改變系統狀態的Query不需要套用DDD,甚至根本也不要設計領域物件,直接讀取資料庫然後產生前端需要的View Model即可,這樣速度更快。


▲圖3:節錄自《CQRS


看完這本書之後Teddy就把ezKanban的use case改成Command與Query。昨天進一步和ezKanban團隊把帳號管理專案的package改用package by feature的方式來管理,如圖4所示。

▲圖4:ezKanban的帳戶管理專案採用package by feature


在重構成package by feature的過程中,GetUserUseCase這個Query與其它會改變系統狀態的use case分別放到不同的package。此時GetUserUseCase已經完全沒有對於User這個領域物件的依賴,如圖5所示它直接透過新的UserQueryRepository查詢資料庫並回傳UserDto給前端。換句話說,CQRS的Query端,故意省略domain model與資料庫之間的轉換,跳過domain model直接讀取資料庫。也就回答了圖2的問題。


▲圖5:直接操作資料庫並回傳DTO給前端


***

友藏內心獨白:繞了一大圈啊。

2020年9月7日 星期一

PoEEA之Server Layer

September 07 22:36~23:20

▲PoEAA書中提到四種表達領域邏輯的模式


緣起

好一陣子沒幫部落格文章增加新分類,今天這一篇開啟【盡信書不如無書】這個分類,紀錄Teddy讀書時看到一些自己覺得怪怪的地方。

***

哪裡怪
前幾天Teddy在準備Asian PLoP 2020的演講題目:〈Pattern-Based Problem Solving: One Pattern at a Time〉,翻到《Patterns of Enterprise Application Architecture》第九章Domain Logic Patterns,看到Service Layer這個模式,如圖1所示。


▲Service Layer模式,節錄自《Patterns of Enterprise Application Architecture (PoEAA)》,133頁。


這本書2003年出版至今已有17年,當年Teddy讀到這個模式、看到這張圖,並沒有什麼感覺。但因為這幾年學了Clean Architecture,前幾天再次看到這張圖,當下就覺得不對勁:「Data Source Layer怎麼會畫在軟體架構的最核心?」。

***

資料庫是細節

Clean Architecture四層架構如圖2,資料庫屬於最外層,並非如PoEAA所畫的位於最核心。軟體架構的核心應該是Entity Layer,也就是Domain Model Layer。


▲圖2:《Clean Architecture》建議的四層架構,畫成同心圓(圖片來源在此


在階層式架構中,把資料庫畫成底層或是核心層,在N年前也算是常見的畫法。但以現在的角度來看,對照圖1與圖2,應該可以很清楚看出來,圖2的觀點比較正確。資料庫、使用者介面、框架、驅動程式等,都屬於細節,屬於階層式架構的外層,並非是核心部分。

其次,傳統階層式架構所說的Service Layer,就是Clean Architecture裡面的Use Case Layer。Teddy現在覺得Use Case Layer比較具體,因為Service這個字有很多種含意,因此用Service Layer來代表應用程式所提供功能或服務的邊界,好像有點那麼不是很直覺(就跟這句話一樣XD)。

***

讀書不是照單全收

PoEAA是一本很棒的書,書中所整理的模式很多到今日依然適用且日久彌新。但也有一些模式的內容,因為時代演進需要稍微修正,像今天介紹的Service Layer就是一個例子。

讀書不是照單全收,有時候同意,有時候疑惑,有時候反對。理論上,除非這本書有問題,否則同意的時候應該居多。疑惑時可能是自己離作者太遠,尚無法理解書中的微言大義,但也能不排除內容有誤的能性。

反對,代表自己有看法,這個看法與書中不同。自己的看法可能是錯的,也可能是對的。能夠說出不同,也算是一種讀書的層次。

***

友藏內心獨白:挑毛病也要講出個道理。