Communitygithub.com

Brians-brain/claude-skills

設計「深模組」(deep module)的共同詞彙:小介面背後放大量行為。當使用者想設計或改善模組的介面、找出可以把模組加深的地方、決定 seam(不必改程式就能替換行為的接縫)放在哪裡、讓程式碼更好測試或更容易讓 AI 理解,或其他 skill 需要這套設計詞彙時使用。

Qu'est-ce que claude-skills ?

claude-skills is a Claude Code agent skill that 設計「深模組」(deep module)的共同詞彙:小介面背後放大量行為。當使用者想設計或改善模組的介面、找出可以把模組加深的地方、決定 seam(不必改程式就能替換行為的接縫)放在哪裡、讓程式碼更好測試或更容易讓 AI 理解,或其他 skill 需要這套設計詞彙時使用。.

Compatible avec✓Claude Code~Codex CLI~Cursor
npx skills add https://github.com/Brians-brain/claude-skills/tree/HEAD/codebase-design

Demander à votre IA préférée

Ouvre une nouvelle conversation avec cette compétence d'agent déjà préchargée.

Documentation

程式碼設計

與使用者溝通使用繁體中文。下列術語第一次出現時中英並列,之後依本表統一用法。

設計 deep module:在小介面背後放大量行為,放在乾淨的 seam 上,並且能透過那個介面測試。凡是在設計或重構程式碼的地方,都使用這套語言和這些原則。目標是:給呼叫端槓桿(leverage)、給維護者局部性(locality)、讓所有人都容易測試。

術語表

精確使用以下術語:不要換成「元件」「服務」「API」或「邊界」。一致的語言正是重點所在。

模組(Module):任何有介面和實作的東西。刻意不限規模:可以是一個函式、類別、套件,或跨越多層的切片。避免使用:單元、元件、服務。

介面(Interface):呼叫端要正確使用這個模組所必須知道的一切:型別簽章,以及不變條件、呼叫順序限制、錯誤模式、必要設定、效能特性。避免使用:API、簽章(太窄,只指型別層面的表面)。

實作(Implementation):模組內部的東西,也就是它的程式碼本體。和**轉接器(Adapter)**不同:一個東西可以是有大量實作的小轉接器(例如一個 SQLite repository),也可以是只有少量實作的大轉接器(例如一個記憶體內的假物件)。討論 seam 時用「轉接器」,其他時候用「實作」。

深度(Depth):介面上的槓桿。呼叫端(或測試)每學一單位介面,能使用到多少行為。大量行為藏在小介面背後的模組是深的;介面幾乎和實作一樣複雜的模組是淺的。

Seam(Michael Feathers):一個不必修改該處就能改變行為的地方;也就是模組介面所在的位置。seam 放在哪裡本身就是一個設計決策,和 seam 背後放什麼是兩回事。避免使用:邊界(和 DDD 的 bounded context 混淆)。

轉接器(Adapter):在某個 seam 上滿足某個介面的具體東西。描述的是角色(它填哪個位置),而不是內容(裡面有什麼)。

槓桿(Leverage):呼叫端從深度得到的好處。每學一單位介面,能得到更多能力。一份實作的價值,會在 N 個呼叫處和 M 個測試中回收。

局部性(Locality):維護者從深度得到的好處。修改、bug、知識、驗證都集中在一個地方,而不是散落在各個呼叫端。修一次,處處生效。

深與淺

Deep module = 小介面+大量實作:

┌─────────────────────┐
│       小介面         │  ← 方法少、參數簡單
├─────────────────────┤
│                     │
│      深層實作        │  ← 複雜邏輯藏在裡面
│                     │
└─────────────────────┘

淺模組 = 大介面+少量實作(避免):

┌─────────────────────────────────┐
│             大介面               │  ← 方法多、參數複雜
├─────────────────────────────────┤
│  薄實作                          │  ← 只是把東西傳過去
└─────────────────────────────────┘

設計介面時,問自己:

  • 能減少方法的數量嗎?
  • 能簡化參數嗎?
  • 能把更多複雜度藏進裡面嗎?

原則

  • 深度是介面的性質,不是實作的性質。 一個 deep module 內部可以由小的、可 mock、可替換的零件組成;只是這些零件不屬於介面。模組可以有內部 seam(實作私有、供自己的測試使用),也有位於介面上的外部 seam。
  • 刪除測試。 想像把這個模組刪掉。如果複雜度消失了,它只是個傳話筒。如果複雜度在 N 個呼叫端重新出現,它就是有在發揮作用。
  • 介面就是測試面。 呼叫端和測試跨越的是同一個 seam。如果你想要越過介面去測試,這個模組的形狀很可能是錯的。
  • 一個轉接器代表假想的 seam,兩個轉接器才是真的 seam。 除非真的有東西會在 seam 兩側變化,否則不要引入 seam。

為可測試性而設計

好的介面讓測試變得自然:

  1. 接收依賴,而不是自己建立依賴。

    # 可測試
    def fetch_alternates(mpn: str, client: PartSearchClient) -> list[Part]: ...
    
    # 難以測試
    def fetch_alternates(mpn: str) -> list[Part]:
        client = DistributorClient(api_key=os.environ["DIST_API_KEY"])
    
  2. 回傳結果,而不是產生副作用。

    # 可測試
    def landed_cost(bom: Bom, freight: Freight) -> Money: ...
    
    # 難以測試
    def apply_landed_cost(bom: Bom) -> None:
        bom.total += freight_charge
    
  3. 小的表面積。 方法越少,需要的測試越少;參數越少,測試準備越簡單。

關係

  • 一個模組恰好有一個介面(它呈現給呼叫端和測試的表面)。
  • 深度是模組的性質,以它的介面來衡量。
  • Seam 是模組的介面所在之處。
  • 轉接器位於 seam 上,並滿足介面。
  • 深度為呼叫端產生槓桿,為維護者產生局部性。

不採用的框架

  • 把深度定義為實作行數與介面行數的比例(Ousterhout):這會獎勵灌水的實作。我們改用「深度即槓桿」。
  • 把「介面」等同於 Python 的 Protocol/抽象類別,或類別的公開方法:太窄了:這裡的介面包含呼叫端必須知道的每一件事。
  • 「邊界」:和 DDD 的 bounded context 混淆。請說 seam 或介面。

進一步閱讀

  • 在既有依賴下加深一群模組,見 DEEPENING.md:依賴分類、seam 紀律,以及「取代而非疊加」的測試策略。
  • 探索不同的介面設計,見 DESIGN-IT-TWICE.md:平行派出多個子 agent,用幾種截然不同的方式設計介面,再從深度、局部性與 seam 位置比較。

Skills associés