上一篇把 DDD 講得跟武功秘笈一樣,結果秘笈裡到底寫了什麼,一個字都沒提。
這篇想把我自己理解到的部分,好好整理出來。
先自首:標題說的那些誤解,我自己全都有過。這篇就是把我從懵懵懂懂,到慢慢感受到 DDD 魅力的這一路,做個整理與分享。
我對 DDD 的第一印象,跟你可能一樣
很多人第一次接觸 DDD,是看到某個專案的資料夾長這樣:domain/、application/、infrastructure/,裡面放著 Entity、Repository、UseCase。
所以很自然會覺得:DDD 是一種資料夾結構、一種架構風格。
也常聽到把 DDD 和微服務放在一起講的說法:DDD 就是在教你服務怎麼拆、邊界怎麼切。
這些理解都沒有錯,我自己也是這樣入門的。只是後來慢慢發現,它們比較像是表層的呈現。
分層架構、資料夾怎麼擺、服務怎麼拆——這些都是手段,是為了承載核心思想才存在的東西。有點像蓋房子時的鷹架:你看得到它,它也真的有用,但它不是房子本身。
順序其實是反過來的:先有核心思想,才需要這些手段來配合;架構長成那樣,只是思想落地之後的其中一小部分結果。當年的我只搬了結果、沒學到思想,現在回頭看,就是得其形,不得其神。
至於那一大堆名詞——聚合、值物件、防腐層、限界上下文——我也是先硬背起來的。但老實說,背完還是不知道 DDD 在幹嘛。名詞只是招式的名字,重要的是每一招背後想解決的問題。
那 DDD 的核心思想到底是什麼?
以我目前的理解,一句話:把商業邏輯的脈絡,精煉、濃縮之後,映射成程式碼。
這裡我特別想用「映射」,而不是「翻譯」。因為翻譯是有轉譯過的,中間必然有損耗、有走樣;而映射期望的是——商業上的語意、商業上的邏輯脈絡,理想情況下,一比一地對應到程式碼上。業務的規則長什麼樣子,程式碼就長什麼樣子。
回頭想想,很多系統慢慢走味的原因,其實不是工程師不會寫 code,而是程式講的話,跟業務講的話,是兩種語言。
業務說「這個會員要停權」,程式裡卻是 user.status = 3。時間一久,沒人記得 3 是什麼;哪天有人把 3 拿去當「待審核」用,問題就變得很難追了。
DDD 想解決的,就是這件事。我自己習慣把它整理成三個層次:心法、身法、拳法。
心法:讓程式和業務講同一種語言
DDD 的心法,我認為就是一句:通用語言(Ubiquitous Language)。
意思是:業務怎麼講,程式就怎麼寫。
業務說「停權」,程式裡就有一個方法叫 Suspend(),而不是 updateStatus(3)。
業務說「訂單出貨之後,就不能取消了」,Cancel() 裡就真的有這麼一條守衛,讀起來就是這句話。
這件事的價值在於:溝通不再需要翻譯。
PM 講的、工程師寫的、程式跑的,是同一套語言。需求討論時發現的規則,可以直接對照到程式碼;程式碼裡的邏輯,也能直接拿去跟業務對答案。
很多「我以為你說的是這個意思」的誤會,其實都是消耗在翻譯這一層。
而我覺得 DDD 最被低估的價值,也在這裡:它把商業領域的知識,一路映射進程式碼裡,慢慢化解「程式歸程式,業務歸業務」那道牆。做得夠深的團隊,甚至會發現商業團隊和工程團隊之間的藩籬也在鬆動——大家是在同一個模型上討論,而不是隔著需求文件喊話。
更妙的是,你仔細想想:把商業知識建成一個個模型,落到程式碼上,不就是物件導向設計嗎?每個模型只管自己的事、規則收在自己家裡,不就是高內聚、低耦合嗎?
搞懂業務的過程,和寫出好程式的最佳實踐,在 DDD 裡剛好是同一件事。完美契合。
EventStorming 的發明人 Alberto Brandolini 有句話講得很透:
Software development is a learning process, working code is a side effect.
軟體開發是一場學習的過程,能動的程式碼只是副產物。
我第一次看到也覺得太誇張。但真的照著做過一輪就會發現:最有價值的不是那份程式碼,是團隊在建模過程中一起搞懂的那些事。
身法:邊界,邊界,還是邊界
心法有了,接下來是身法:限界上下文(Bounded Context)。
名字聽起來很學術,概念其實很日常:同一個詞,在不同場景下,意思不一樣。
拿「會員」來說。
對行銷來說,會員是「一個可以推播、有標籤、有消費輪廓的對象」。
對金流來說,會員是「一個有付款方式、有交易紀錄、要做風控的帳戶」。
對客服來說,會員是「一個有工單歷史、有聯絡方式的人」。
同一個詞,三種完全不同的關注點。
常見的做法,是做一張很大的 users 表,每個部門的需求都往裡面加欄位。我自己也維護過這樣的表——改一個欄位要先確認三個部門會不會受影響,時間一久,它就變成大家都不太敢動的地方。
DDD 給的答案是:承認它們是三個不同的模型,畫出邊界,讓它們各自住在自己的上下文裡。行銷的會員、金流的帳戶、客服的聯絡人,各管各的,需要溝通時再透過明確的介面往來。
邊界切得好,每個模組就小、就純粹、就好懂。
改行銷的邏輯,不會影響到金流。這剛好也是上一篇提到的——AI 改 A 壞 B,缺的正是這種邊界。
拳法:實作層的招式
心法和身法都是思維層面的東西,落到程式碼,才輪到那些常聽到的名詞:
實體(Entity):有身分的東西。訂單編號 A123 就是 A123,內容再怎麼改,它還是同一張訂單。
值物件(Value Object):沒有身分、只有值的東西。「NT$500」就是 NT$500,兩個 NT$500 之間沒有誰是誰的問題。順便把「金額不能是負的」這種規則直接放進型別裡,就不需要在很多地方重複檢查。
聚合(Aggregate):一組必須一起變動的東西,由其中一個當對外的入口。訂單和訂單明細就是一組——你不會希望明細被繞過訂單直接改掉。所有修改都經過訂單本身,規則才守得住。
領域事件(Domain Event):把「發生過的事」變成一等公民。「訂單已付款」不只是一個 flag,而是一個事件——庫存要扣、通知要發、發票要開,都是聽到這個事件之後各自去做的事。
招式還有很多,但它們有一個共通點:
每一招,都是在把業務規則從「散落各處的 if-else」,收攏成「有名字、有邊界、有守衛的結構」。
所以,這跟 AI 有什麼關係?
回到上一篇的結尾。
你有沒有發現,DDD 一路做下來的產出——通用語言、上下文邊界、模型、規則——剛好就是一份給 AI 看的完美規格書?
跟 AI 說「幫我做一個會員系統」,它缺乏足夠的 context,只能自己腦補。腦補出來的,往往就是之前那篇寫過的、一改就壞的系統。
但如果你給它的是:這裡有三個上下文、會員在各自上下文裡是什麼、訂單聚合的規則有哪些、付款完成會發出什麼事件——
它就不是在腦補了,它是在照圖施工。
以前做 DDD 最大的成本,是建模完還要自己一磚一瓦把系統蓋出來。現在蓋房子的成本趨近於零,剩下的成本,只有畫圖的能力。
換句話說,看懂業務、找出規則、抽出模型、切好邊界,最後把這一切變成 AI 能照著施工的圖——這些系統分析與系統設計的功夫,不但沒有因為 AI 而貶值,反而更值得花時間累積。
說到底,這篇想做的事很單純:我遇到了一套讓我很驚艷的方法論,想把這份驚艷分享出來。它跟敏捷有點像——聽過的人很多,被誤解、誤用的機會,卻可能比被好好理解的機會還多。這麼好的東西被埋在誤解裡,我覺得很可惜。
而我自己,也是一路磕磕碰碰走過來的:抱著錯誤的觀念繞了不少遠路,說不定也曾在無意間誤導過別人。還好這一路遇到許多厲害的前輩,無私地分享他們的理解,我才慢慢把觀念修正過來。所以也想把這份幸運,接著傳下去。
AI 時代的節奏很快,大家多少都有點焦慮、心浮氣躁。這篇沒有要製造什麼焦慮,就只是一份經驗的整理與分享。如果它能讓你對 DDD 少一點誤解、多一點好奇,願意把這本秘笈親自翻開來看看,那就是我最開心的事了。



