August 19 22:56~August 20 00:29
背景說明
昨天Teddy在【搞笑談軟工Facebook社群】提到在DDD中應該是不需要使用Unit of Work (UoW) 設計模式,鄉民A問在DDD不合適使用UoW的原因是什麼?今天談一下這個問題。
***
Unit of Work設計模式
依據Martin Fowler在《Patterns of Enterprise Application Architecture》的解釋,Unit of Work:
Maintains a list of objects affected by a business transaction and coordinates the writing out of changes and the resolutions of concurrency problem. (Google 翻譯:維護受業務交易影響的物件列表,並協調更改的寫入和並發問題的解決方案。)
感覺有一點抽象,Teddy舉一個ezKanban系統的例子來說明Unit of Work。
***
範例說明:ezKanban與看板遊戲
ezKanban是一個採用DDD與Clean Architecture架構所開發的線上同時多人使用看板系統,圖1展示ezKanban的五個使用案例:Create Board、Create Workflow、Create Stage、Create Swimlane、Crate Card。其中Create Board操作Board Aggregate,Create Card操作Card Aggregate,另外三個使用案例則是操作Workflow Aggregate。
▲圖1
由於在DDD中Aggregate就是一個交易邊界(transaction boundary),所以每一個使用案例都在各自的交易中處理。從這個角度來看,Aggregate本身就已經是Unit of Work,如果還需要額外套用Unit of Work,就代表有某種需求,需要在Aggregate之外再加上一層,把多個Aggregate放在一個更大的Unit of Work。
***
最近Teddy與ezKanban團隊使用ezKanban系統開發一個新的看板遊戲功能,新寫了Create Kanban Game這個使用案例,請參考圖2。
▲圖2
Create Kanban Game的實作方式只是呼叫原本寫好的那五個使用案例,此時有鄉民可能會認為:「是不是應該把Create Board、Create Workflow、Create Sage、Create Swimlane、Create Card放在同一個交易中處理以便確保資料的一致性?」如果真的要這麼做,就有可能套用Unit of Work設計模式。
Unit of Work是把原本不同的工作放在同一個交易(transaction)來處理,這在傳統的CRUD系統(集中式系統)是很常見的需求。但是,在DDD中,不同的Aggregate是透過領域事件(domain event)達到狀態的「最終一致性」(eventual consistency),而不是將這些不同的Aggregate放在另一個Unit of Work中達到ACID。
在DDD中,如果你願意,Aggregate是可以變成一個最小的部屬單位,也就是說Board、Workflow、Card可能被部署成微服務,因此自然也不適合將它們放在同一個Unit of Work(同一個交易)來處理。
***
如果是同一個Aggregate…
後來鄉民B進一步問:「如果是在同一個Aggregate的話,是不是就可以套Unit of Work?」
例如,假設在ezKanban系統中有一個使用情境是要一次新增一百張卡片,實作方式如果是連續呼叫Create Card 使用案例一百次,這樣都是操作同一個Card Aggregate,是不是就可以把這些對於Create Card使用案例的一百次呼叫放在Unit of Work中?
如果是這種需求,乍看之下覺得要用Unit of Work是很合理的。但是,再仔細思考一下,在DDD中「Aggregate形成交易邊界」這個特性,雖然都是相同型別的Aggregate(都是Card),但這一百張卡片是一百個不同的aggregate instance,所以嚴格講起來每一個aggregate instance應該都只管自己的交易。
但是,這樣一來「資料正確性」怎麼辦?Teddy覺得在DDD這頂「大帽子」之下,應該儘量朝向分散式處理、最終一致性、交易補償(錯誤處理)的角度來思考系統的行為與狀態,長期而言會比較能夠得讓系統從分析、設計到實作,保持一致性與完整性。
一旦在DDD裡面採用「Unit of Work將多個Aggregate打包處理」,Teddy大膽假設團隊中就會有人的想要在DDD中做到「分散式交易處理」或是「二段式提交(Two-Phase Commit)」的效果,如此一來思考模式又回到傳統的ACID與集中式系統的模式。
那麼,回到根本的問題,為什要要DDD勒?
***
友藏內心獨白:沒有一定不行,真的想用就用,用了也不用有警察來開罰單。