指令用途
/codebase-design 是設計深模組(deep modules)的共享紀律與詞彙來源。「深模組」出自 John Ousterhout《A Philosophy of Software Design》的核心觀念:
最好的模組是深的。它們讓大量功能透過一個簡單的介面被存取。
這個 skill 提供跨多個 skills 共用的詞彙 —— module、interface、depth、seam、adapter —— 以及把大量行為藏在乾淨接縫(seam)、放在乾淨位置、可透過介面測試的原則。
它本身不直接「做事」,而是作為其他 skills 的詞彙來源:/improve-codebase-architecture 從這裡取架構詞彙,/tdd 從這裡取介面設計指引。
核心詞彙
Module(模組)
一個有介面與實作的程式碼單元。深模組 = 大量實作 + 小介面。淺模組 = 少量實作 + 大介面(或介面與實作差不多大)。
Interface(介面)
模組對外暴露的部分 —— 呼叫者需要知道的一切(函式簽名、型別、副作用契約)。介面越小、越不滲漏實作細節,模組越深。
Depth(深度)
呼叫者透過介面取得的槓桿:單位介面學習成本背後能使用多少行為。深模組用小介面隱藏大量行為;不要用實作行數與介面行數的比例衡量深度。
Seam(接縫)
可測試、可替換的邊界。測試只打 seam,不打內部(與 /tdd 的「只在 seams 測試」呼應)。一個好的 seam 是輸入輸出明確、不滲漏實作的地方。
Adapter(介面卡)
位於 seam、用來滿足某個 interface 的具體實作。Adapter 描述的是它在接縫上的角色,不代表它一定很薄或只做翻譯。
設計原則
一、把變動藏在介面後
變動的是實作,不變的是介面。一個改動如果逼呼叫者改他們的呼叫,那介面太淺了。
二、乾淨的 seam
接縫要放在自然邊界上 —— 一個領域概念換手的地方,而不是任意切一刀。bad seam 會讓測試要準備一堆 mock;good seam 讓測試只需準備輸入。
三、可透過介面測試
如果你無法只透過介面(公開 API)測試這個模組,那介面不完整或 seam 錯了。測試打到私有細節是 seam 滲漏的訊號。
四、資訊隱藏
介面不該洩漏實作選擇(用了哪個 DB、哪個框架)。呼叫者知道得越少,你越能自由地改實作。
五、刪除測試與 adapter 判斷
- 刪除測試:假設刪掉這個模組;如果複雜度在 N 個呼叫端重新出現,它原本就在提供深度;如果只是把複雜度移走,它可能只是 pass-through。
- 一個 adapter 是假設中的 seam,兩個 adapter 才是實際變異:沒有真正變化前,不要為了預想的替換需求先加 seam。
Design It Twice
這個 skill 收錄了來自 Ousterhout 的 「Design It Twice」 技巧(在 DESIGN-IT-TWICE.md)—— 用平行子代理產生截然不同的設計:
- 針對同一個介面問題,生成兩個(或多個)根本不同的設計方向。
- 比較它們各自的 depth、seam 位置、可測試性。
- 從比較中選擇或綜合 —— 而不是一開始就鎖定第一個想到的設計。
「Design It Twice」的力量在於打破第一個設計的引力:你腦中浮現的第一個介面 rarely 是最深的,比較過替代方案才知道。
實戰對話範例
範例一:介面設計選擇
- You:
我要設一個「通知服務」,可以發 email 和 push。
- AI:
用 design-it-twice。我先給兩個截然不同的介面方向:
方向 A —— 通道導向:
notify.sendEmail(to, subject, body); notify.sendPush(userId, title, body);淺:介面直接綁死通道。新增 SMS 要改呼叫端。
方向 B —— 訊息導向:
notify.send({ to, message, channels: ['email', 'push'] });深:介面只說「發這個訊息」,通道是實作細節。新增 SMS 只在實作層加。
比較:B 的 depth 更深 —— 同樣的介面呼叫者,背後能換/加通道而不動呼叫端。B 的 seam 也更乾淨 —— 測試不用知道哪個通道。你比較傾向哪個?
範例二:seam 滲漏診斷
- You:
這個 PaymentService 很難測試,要 mock 一堆東西。
- AI:
這是 seam 滲漏的訊號。讓我用深模組詞彙診斷:
它的介面要求呼叫者傳入
dbConnection和logger和httpClient—— 等於把實作依賴都滲給呼叫者了。這讓它變淺(呼叫者要知道太多),也讓測試要準備一堆 mock。深化建議:介面只要
pay(amount, accountId),實作自己擁有 db、logger、http。seam 乾淨後,測試只要給amount和accountId。
何時應該使用
- 設計新模組的介面:design-it-twice,別鎖定第一個想法。
- 深化既有模組:把滲漏的依賴收回介面後。
- 決定 seam 放哪:讓測試不打私有細節。
- 作為
/improve-codebase-architecture與/tdd的詞彙基礎:這兩個 skill 從這裡取語言。
何時不應該使用
- 還沒到設計階段:先用
/grill-with-docs釐清要做什麼。 - 一次性原型:用
/prototype,不必講究 depth。 - 純資料結構 / DTO:沒有行為要藏的,不適用深模組觀念。
與其他技能的關係
/codebase-design 是 /improve-codebase-architecture(取架構詞彙)與 /tdd(取介面設計指引)的共享基礎。它與 /domain-modeling 互補 —— 前者管模組介面設計,後者管領域詞彙。不確定該用哪個 skill 時,用 /ask-matt 來路由。