《Domain-Driven Design 領域驅動設計》Podcast 準備稿:綁定模型與實作
書名: 領域驅動設計 Domain-Driven Design(Tackling Complexity in the Heart of Software) 作者: Eric Evans 系列: 啃一本大書(恩普拉氏) 公開標題建議: 啃一本大書|Domain-Driven Design.模型和程式碼不能脫節 (3/13) 涵蓋範圍: Part I 第3章 綁定模型與實作(Binding Model and Implementation)
背景速覽
Part I 的收尾集。前兩集講了「消化知識」和「統一語言」,這集解決一個致命問題:很多團隊有漂亮的分析模型、也有能跑的程式碼,但兩者對不上。Evans 提出 Model-Driven Design(模型驅動設計)——拒絕「分析模型」和「設計模型」的二分法,堅持用一個模型同時當分析工具和實作基礎。這集也會講到一個很多人忽略的主張:建模的人必須動手寫程式。
一句話重點
模型和程式碼必須緊密綁定——程式碼就是模型的表達,改程式碼等於改模型;一旦兩者脫節,模型淪為沒人看的文件,程式碼也失去概念清晰度,DDD 整套就垮了。
值得討論的重點
1. Analysis Model 的陷阱:知識在交接中流失
常見但有問題的做法:分析師建一個「分析模型」,開發者再另外建一個「設計」,兩者只有鬆散對應。後果很慘:
- 知識流失:分析階段消化知識得到的洞見,進實作時大量蒸發,因為開發者被迫重建自己的抽象。
- 模型過時:一開始寫程式,分析模型就被丟掉,因為它沒考慮實作可行性。
- 洞見斷裂:實作中總會有意外發現,但這些發現回不到分析模型。
Evans 的判決:如果設計(或其核心)對應不到領域模型,那模型幾乎沒價值,軟體的正確性也可疑。
2. Model-Driven Design:一個模型,兩種用途
MDD 的核心主張是放棄二分法,追求一個同時滿足分析和設計的單一模型:每個設計物件都扮演模型裡描述的概念角色,程式碼成為模型的表達,建模和設計合併為單一的迭代循環。這對模型的要求更高——它必須同時是好的分析工具、又是可行的實作基礎。當模型不適合實作、或無法忠實表達領域關鍵概念時,都得換模型。
3. 為什麼物件導向適合 MDD
Evans 解釋:OOP 的真正突破不是「用物件組織程式碼」,而是程式碼能表達模型的概念——物件確實存在於記憶體、有關聯、被組織成 class、提供可呼叫的行為,這跟概念物件模型直接類比。相對地,純程序式語言(如 C)難以支援 MDD,因為程式只是一連串技術性的資料操作步驟,捕捉不到領域的「主動面向」。(Evans 也提到 Prolog 同樣適合——重點不是特定語言,而是語言有沒有支援某種「建模典範」。)
4. PCB Bus 的例子:從程序式腳本到模型驅動
很具體的對照。PCB 上有上萬條 net,工程師想以 bus(一組 net)為單位指派規則,但工具沒有 bus 概念。
- 程序式做法:寫腳本排序 net、靠命名慣例解析、把規則逐條展開寫檔。問題:只是檔案操作、沒有明確的 bus 概念、換個檔案格式就重來、只能端對端比對測試。
- 模型驅動做法:把 Bus 變成一個明確的領域物件(AbstractNet 持有規則,Net 和 Bus 都繼承它),配上 Import/Export Service、Net/Bus Repository、Inferred Bus Factory。優勢:Bus 概念明確、每個元件可單元測試、易擴展、與檔案格式無關。
注意事項
⚠️ Hands-On Modelers(動手的建模者)這條,是 Evans 對「製造業隱喻」的正面開戰。 他親身經歷過一個慘案:管理層認為「建模的人就該建模、寫程式是浪費技能」,禁止他碰實作。結果他和專家提煉出的精良模型從未被真正落實——意圖在交接中流失(UML 圖傳達不了那些敏感的細節),回饋太慢(模型在某平台效率極差的問題,幾個月後才傳回來,那時開發者早就拋棄模型自己寫了)。
⚠️ 所以 Evans 的結論是:任何寫程式的人都必須某種程度參與建模,任何建模的人也必須碰程式碼。 這不代表不能有分工角色,問題出在「把建模和實作這兩個緊密耦合的任務強行切開」。脫離實作的建模者會失去對實作限制的直覺,產出不切實際的模型。這對「架構師只畫圖不寫 code」的組織是當頭棒喝。
⚠️ 「Letting the Bones Show」這段提醒:模型一致性不只對開發者重要,對使用者也重要。Evans 用 IE 的「我的最愛」當反例——使用者以為 Favorite 是一串網站名稱清單,實際上它是一個檔名就是顯示名的檔案,於是網頁標題含 : 之類非法字元時就跳出莫名其妙的錯誤。當設計基於反映使用者關切的模型時,可以放心把「骨架」露給使用者,行為才會一致可預測。
專家補充
💡 「程式碼就是模型」這句話,後來在 DDD 社群演化出一個常見爭論:要不要讓 ORM、資料庫 schema 牽著模型走?Evans 在後面第6章會更深入講,但這集已經埋了態度——別讓技術機制(持久化、框架)淹沒模型。這也是為什麼六角架構(Hexagonal / Ports and Adapters)和 Clean Architecture 後來這麼受 DDD 社群歡迎:它們的核心訴求就是「把領域模型保護在中心,技術細節推到外圈」。
💡 Hands-On Modelers 這條,今天看更有共鳴。在「架構師 vs 工程師」分層的大公司,DDD 很容易變成「架構師畫一堆 Aggregate 圖、工程師照抄」,然後失敗。Evans 早在 2003 就警告過這個坑。如果你的團隊有「建模會議」和「實作會議」是兩批人開的,這集要特別敲這一點。
💡 補一個落地建議:MDD 不是要你一次設計到位。Evans 自己說 PCB 那個漂亮設計「不會一步到位,需要多次迭代的重構和消化知識」。這正好接上 Part III「重構邁向深層理解」——模型驅動設計是一個持續演化的過程,不是前期一次性的架構決策。
討論問題
🎙️ 開場鉤子:「你們公司有沒有那種——架構師畫了一大張漂亮的 UML,貼在 Confluence 上,然後工程師寫 code 時根本沒在看?那張圖,就是 Evans 說的『沒價值的模型』。」
🎙️ 自問自答:「為什麼分析模型和設計模型分開是壞事?」——因為知識會在兩者交接時流失,而且兩邊各自演化、越走越遠,最後分析模型變成沒人維護的化石。
🎙️ 帶走的一題:「想想你最近寫的某個類別——它的名字和結構,真的反映了業務概念嗎?還是只是『能跑的資料容器』?如果是後者,那你正在累積『模型和程式碼脫節』的債。」
更大範圍關聯
- Part I 收尾:消化知識(EP1)+ 統一語言(EP2)+ 綁定模型與實作(本集),合起來就是「讓領域模型運作」的完整方法論——這是 DDD 的世界觀地基,後面的戰術和戰略全長在這上面。
- 連到 Clean Architecture / 六角架構:「把領域模型保護在中心、技術細節推到外圈」是 DDD 和 Clean Architecture 共同的訴求。Uncle Bob 的 Clean Architecture 可以看成 DDD「綁定模型與實作」在架構層面的工程化落地。
- Hands-On Modelers vs 象牙塔架構師:這個張力會在全書最後一章(EP13)以「策略設計該由誰來定」的形式再次出現。Evans 一以貫之地反對「最聰明的人去架構團隊、不碰應用程式碼」。
- 程式碼設計三本:本集的「程式碼就是模型的表達」,正是把 GoF 設計模式和 Fowler 重構手法用在領域層的前提——只有當你相信 code 該表達概念,模式和重構才不只是技術技巧。
錄製建議
- 建議時長:約 20 分鐘。配比:Analysis Model 陷阱+MDD 核心約 8 分、PCB Bus 對照約 5 分、Hands-On Modelers 約 7 分(這段是本集最有觀點、最容易引共鳴的,留多一點時間)。
- 討論策略:用「貼在牆上沒人看的 UML 圖」這個畫面開場,幾乎每個工程師都中過招。中段 PCB Bus 例子可以簡化講(程序式腳本 vs 明確的 Bus 物件),重點放在「概念有沒有被明確表達」。結尾把 Hands-On Modelers 拉到聽眾自己的組織,問「你們的建模和寫 code 是同一批人嗎」。
- 這集講完 Part I 就結束了,可以花 30 秒做 Part I 小結(消化知識→統一語言→綁定實作),預告 Part II 要進到大家最熟悉的「戰術模式」。