l

2021年9月10日 星期五

領域驅動設計學習筆記(22):貧血模型與充血模型(下)

September 10 03:38~04:58

▲ezKanban的Board Aggregate套用DCI之後,可以動態指派新的角色給它,以便獲得新的行為能力。


阿嬤的物件導向

DCI架構(Data, Context, Interaction)由Trygve Reenskaug和James O. Coplien所提出,這兩位都是軟體界的名人,前者是MVC(Model-View-Controller)架構發明人,後者是模式與敏捷領域的大師。Teddy今年6月曾介紹過DCI並應用它來重構DDD Aggregate:

***

傳統認為好的領域模型應該設計成充血模型(Rich Domain Model),物件身上封裝著資料與操作該資料的商業邏輯,程式比較容易閱讀與維護。貧血模型(Anemic Domain Model)則被認為是不好的物件導向設計,它將商業邏輯從物件身上抽離出來,物件行為被降級成單純的資料庫操作,因此導致商業邏輯不清、系統難以維護。

Coplien 在介紹DCI的演講中曾說過:「傳統物件導向將資料與行為封裝在一起的做法,是你阿公時代的物件導向技術。」他建議採用DCI架構,將系統區分為DataContextInteraction。DCI架構主張物件的行為,必須要放在特定的使用案例(Use Case)裡面來解讀,才能夠理解其意義。

舉個例子,「人」這個物件,具備「唱歌」的行為。但當一個人在唱歌的時候,到底代表什麼意義,必須從使用案例中去理解。你在KTV唱歌、在學校朝會唱歌、在當兵的時候唱歌、在求婚的時候唱歌、在失戀的時候唱歌、在遊覽車上唱歌、在無人的海邊唱歌、在選秀節目中唱歌、在監獄裡面唱歌,意義可能完全不同。在DCI架構中,將這些不同的使用案例稱為Context(情境、脈絡、上下文)

人這個物件,只需具備資料(Data)即可。至於人到底具備哪些行為,則是在某一個特定Context中,由Context將所需行為動態「注入」到人身上。一個Context經常需要協調多個物件一起工作,這個協調的動作在DCI架構中就稱為Interaction(互動)。

***

何處惹塵埃

上一集,Teddy將「Object is a poor man’s closure, and closure is a poor man’s object.」改寫成「貧血模型是富人的充血模型,充血模型是富人的貧血模型 。」不少鄉民不知道Teddy在瞎說什麼。

為什麼說貧血模型是富人的充血模型?從DCI(富人)的角度來看,貧血模型就是資料物件(Data Object),物件的真正行為延後到執行期間再由Context指派給它。所以,你希望物件有什麼行為,沒問題,爸爸(Context)都可以指派給你。這麼豐富的行為,領域物件還能不「充血」嗎!

為什麼說充血模型是富人的貧血模型?充血模型最佳代表,就是DDD的領域模型(Domain Model)。在DDD中,領域模型主要由一堆充滿行為的Entity、Domain Service、Value Object所構成。其中若干個Entity與Value Object依據商業規則被迫「群聚在一起」形成Aggregate(聚合),並從中找一個Entity出來當「大股頭」(Aggregate Root)號令這個「部落」(聚合)。

客戶端(漢人、老外)只可透過Aggregate Root存取內部的Entities或Value Objects,因此Aggregate Root身上會有很多行為,更是充血到爆。為什麼Teddy會說這些充滿行為的領域模型是「富人的貧血模型」?因為這些行為都是在編譯期間(Compile Time)就已經決定了,因此雖然從傳統物件導向的角度來看它們的血量都很足夠,但從DCI(富人)的角度來看,它們也只是另類的貧血模型罷了。

***

結論

世事無絕對,端看造化而定。

***

友藏內心獨白: 統領埔到底要租給誰,搞得我好亂啊 XD。

沒有留言:

張貼留言