** 本文同步發表於 FB社群-軟體設計鮮思維 **
最近在線上輔導了一位 技術職PM 結構設計的實現 (Realization)議題,他傳給我 DDD 的架構圖,覺得在「Domain Service」與「Domain Model」的責任界定上,觀念不是很清楚。
嗯,其實這所謂的 DDD (Domain Driven Development) 架構圖根本就是典型 3-tier (Presentation-Application Logic-Data Source) 分層結構呈現爲圓形的剝洋蔥層次而已,越是內層 (Domain Model) 越代表爲系統的核心。
工程師從這張圖往往會認爲「Domain Model」是最重要的核心觀念。是這樣沒錯,但對以「需求爲導向」的專案開發性質,它卻反而沒那麼重要!況且結構設計的基礎功夫要很紮實,封裝-介面-多型 諸多「虛」的設計觀念確實能充分了解並能整合活用,沒有花上 5-10 年以上功夫,是不容易應用在現實的系統開發上的。相對於此,「Domain Service」對現實的專案開發可是更切實際,且結構設計上的觀念也會比較容易入手。
界定好「Domain Service」這一層,就可以確實封裝 (encapsulate) 「資料存取」與「邏輯運算」這兩大塊,後續才得以透過重構 (refactoring) 的手段 (前提要撰寫單元測試),讓責任的歸屬更加確實,這也是系統的「延展性」議題。簡而言之,「Domain Service」這一層,是決定系統在展示層 (presentation layer)與應用邏輯層 (application logic layer)未來是否能各自有機成長卻互不影響的主要關鍵。
我們用一個很小的案例:「放入購物車」爲實作案例,第一課先讓學員專注在「PlaceShoppingCartService (簡化爲 PlaceCartService)」這個服務類別,以及爲它撰寫「PlaceShoppingCartSericeTest」所需的測試案例 (test case) 使用 C#.NET 的實作上。
果不其然,過於沉浸於實作技術的工程師,往往會馬上想到實作的細節,卻會忽略了幾個結構設計上的原則:
- 各類型類別的責任界定:如服務類別主要責任爲何 (方法、參數、回傳值)。
- 命名的學問:服務/測試/資料傳遞 類別、方法、變數等命名議題。
- 測試案例:該規劃哪些測試方法與準備測試數據。
- 資料傳遞物件 (dto, data transfer object):如何組織資料、是否會被多個 Service 類別共用等議題。
這位學員的實作能力相當不錯,有些觀念一旦取得共識,他馬上就撰寫 C# 程式碼在 Github 上傳給我 Review 並在線上討論。不過其實在寫出程式碼前,在觀念溝通的過程中,如果先能用 UML 類別 (class)圖與物件合作的循序 (sequence) 圖表達,不需要工具,在筆記本塗鴉拍照上傳就可,這樣對觀念的表達很快就可以表現出來,而且因爲先過濾掉實作細節,反而比較能突顯討論的重點。可惜絕大部分的實作開發人員還不懂得如何使用設計圖表達設計思維,這應該也是必備的技能。
一對一的線上輔導得以教學相長。從實作的細節過程中,更能了解諸多工程師的想法與問題並可以反饋到設計的思維上;同時我也從過程中學到一些雲端開發工具的使用,對未來開發輔導與教案的整理上很有幫助。
藉由這個輔導的案例,除了練習的程式碼範例 (不涉及該學員的工作隱私),後續我也會把上述所提及的幾個結構設計原則撰文討論與分享。