14

搞笑談軟工

 3 years ago
source link: http://teddy-chen-tw.blogspot.com/2020/09/clean-architecturecqrs-pattern.html?showComment=1619513823537
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

Clean Architecture之CQRS Pattern

September 10 14:20~15:20

ACtC-3cdaRE_qqaIGKwfpPdfPYrb7EVjV2AI2M0scPfofRgwAIqyReTJnQl4AcbEFnphFixwxcV_6lut63VaL3M5bugUzw4wAbxMF-56SJAQpBjmMXskbSMSKRsh4J2PG8rGcykdQMgTvrbCwU_ARa4DJXO0FQ=w1278-h1022-no?authuser=0

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

緣起

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

ACtC-3epJz3NYMCvn87Tw4_kHkj6gOlpSBmUJtwvHFJGZnmzKjOlaMqgOE7x2Nk1LdzXNa8HqL8rdE3agBZEsGlP_qoalC888rdmOOsDzZ9OH8ObdfoEb3crVuwyWdDxGpTYJAoqUJ6pnDfLbj5qxj2g9_ux8Q=w1654-h1254-no?authuser=0

▲圖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這段文字:

ACtC-3f9XCU9miFpkS6CQ7CoePfMgLfKDmsCTlm_elctf3Rg7_kWEhT6WvPeNhYDKJinpVaaRJOM0mVaPQ8gh09qgjG9Gw3cq2dolQHJCaTwLT5MUEmIMKHxYLJoWrd3ZpH7758ixObu3DAu2_5A4cszV_h2uQ=w2992-h1012-no?authuser=0

▲圖2:《Clean Architecture》 311頁。

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

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

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

▲圖3:節錄自《CQRS

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

ACtC-3fnrZlmhQj2DBhFtUvYmaSfo7RYUUAeZUVnR5kh_OdF4q_YR8Zqt5mwoqOfJyUjm-eGeeXENdK3fO6Zg2CfGhdSB1JF2BmNZxOeoGfN71iIWKRQhJ955y0MMjSb8UDxMCA7HOmrwBwO8P44xhXNoeZCLQ=w886-h1224-no?authuser=0

▲圖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的問題。

ACtC-3cr6ce6cGeBVqo8cyUJokqVkqmBlnD-rWH4Kl5T69-pZXWvRORzFO3PUAXODTLpAeisqeLrcLFZ0O8qirobhAhgbBvxFdivuk4EwC8nwLdvuoNIuqpWprCWpOtpCJerUjClDQRJ80pjAPf21A-wX_oSNA=w1642-h826-no?authuser=0

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

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


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK