第 3 / 13 部 待錄

綁定模型與實作

《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 要進到大家最熟悉的「戰術模式」。