Communitygithub.com

pedro-oscar/shorts-ai

設計深度模組的共享詞彙。當使用者想要設計或改善模組介面、尋找深化機會、決定接縫位置、讓程式碼更易於測試或供 AI 導航,或其他技能需要深度模組詞彙時使用。

shorts-ai 是什麼?

這個技能提供了一套精確的共享詞彙,用於設計深度模組:行為豐富但介面簡潔的模組。它專注於幫助開發者或 AI 代理(如 Cline、Cursor、Claude Code)在設計或重構程式碼時,使用一致的語言來溝通模組的介面、實作、深度、接縫和轉接器。透過應用這些原則,開發者可以提升程式碼的可測試性、為呼叫方提供槓桿效應,並為維護者帶來局部性。此技能強調介面是測試的切入點,並透過具體的設計原則(如刪除測試、依賴注入、返回結果而非副作用)來指導如何建立易於測試的模組。它支援多種程式碼設計平台,並透過標準化的詞彙促進程式碼設計討論。

相容平台~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/pedro-oscar/shorts-ai/tree/HEAD/.claude/skills/codebase-design

在你喜歡的 AI 中提問

開啟一個已預先載入此 Agent Skill 的新對話。

說明文件

程式碼設計

設計深度模組:在一個簡潔的介面背後隱藏大量行為,放置在乾淨的接縫處,並透過該介面進行測試。無論在設計或重構程式碼時,都應使用此語言和這些原則。目標是為呼叫方提供槓桿效應,為維護者提供局部性,並為所有人提供可測試性。

詞彙表

請準確使用這些術語:不要替換為「元件」、「服務」、「API」或「邊界」。一致的語言是重點。

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

介面 (Interface):呼叫方必須知道的所有資訊,才能正確使用模組:包括型別簽名,但也包含不變量、順序約束、錯誤模式、所需配置和效能特性。避免使用:API、簽名(這兩者太狹隘,僅指型別層級的表面)。

實作 (Implementation):模組內部的東西,其程式碼主體。與轉接器 (Adapter) 不同:一個東西可以是一個小型轉接器但擁有大型實作(例如 Postgres 儲存庫),也可以是一個大型轉接器但擁有小型實作(例如記憶體中的假物件)。當討論重點是接縫時,使用「轉接器」;否則使用「實作」。

深度 (Depth):介面所提供的槓桿效應。呼叫方(或測試)每學習一個單位的介面,所能運用的行為量。當大量行為隱藏在一個小型介面背後時,該模組就是深度的;當介面幾乎與實作一樣複雜時,就是淺薄的。

接縫 (Seam) (Michael Feathers):可以在不修改該處程式碼的情況下改變行為的地方;模組介面所在的位置。將接縫放在哪裡本身就是一個設計決策,與接縫背後放什麼是分開的。避免使用:邊界 (boundary)(與 DDD 的限界上下文 (bounded context) 過度重疊)。

轉接器 (Adapter):一個在接縫處滿足介面的具體東西。描述的是角色(它填補了哪個槽位),而不是本質(裡面是什麼)。

槓桿效應 (Leverage):呼叫方從深度中獲得的東西。每學習一個單位的介面,就能獲得更多能力。一個實作在 N 個呼叫點和 M 個測試中得到回報。

局部性 (Locality):維護者從深度中獲得的東西。變更、錯誤、知識和驗證集中在一個地方,而不是分散在呼叫方之間。修復一次,到處都修復。

深度 vs 淺薄

深度模組 = 小型介面 + 大量實作:

┌─────────────────────┐
│    小型介面         │  ← 方法少,參數簡單
├─────────────────────┤
│                     │
│    深度實作         │  ← 隱藏複雜邏輯
│                     │
└─────────────────────┘

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

┌─────────────────────────────────┐
│         大型介面                │  ← 方法多,參數複雜
├─────────────────────────────────┤
│    薄實作                       │  ← 僅傳遞資料
└─────────────────────────────────┘

設計介面時,請問:

  • 我可以減少方法數量嗎?
  • 我可以簡化參數嗎?
  • 我可以在內部隱藏更多複雜性嗎?

原則

  • 深度是介面的屬性,而非實作的屬性。 一個深度模組內部可以由小型、可模擬、可替換的零件組成;但它們並不是介面的一部分。一個模組可以擁有內部接縫(對其實作私有,由其自身的測試使用)以及在其介面處的外部接縫。
  • 刪除測試。 想像刪除這個模組。如果複雜性隨之消失,它只是一個傳遞層。如果複雜性重新出現在 N 個呼叫方之間,那麼它物有所值。
  • 介面就是測試介面。 呼叫方和測試穿越同一個接縫。如果您想要測試越過介面,那麼該模組的形狀很可能錯了。
  • 一個轉接器意味著一個假設性的接縫。兩個轉接器意味著一個真正的接縫。 除非某事物實際上會跨接縫變化,否則不要引入接縫。

設計可測試性

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

  1. 接受依賴,不要建立它們。

    // 可測試
    function processOrder(order, paymentGateway) {}
    
    // 難以測試
    function processOrder(order) {
      const gateway = new StripeGateway();
    }
    
  2. 返回結果,不要產生副作用。

    // 可測試
    function calculateDiscount(cart): Discount {}
    
    // 難以測試
    function applyDiscount(cart): void {
      cart.total -= discount;
    }
    
  3. 小表面積。 方法越少 = 需要的測試越少。參數越少 = 測試設定越簡單。

關係

  • 模組 擁有恰好一個 介面(它向呼叫方和測試呈現的表面)。
  • 深度 是 模組 的屬性,針對其 介面 衡量。
  • 接縫 是 模組 的 介面 所在的位置。
  • 轉接器 位於 接縫 處並滿足 介面。
  • 深度 為呼叫方產生 槓桿效應,為維護者產生 局部性。

被拒絕的框架

  • 深度作為實作行數與介面行數的比例 (Ousterhout):獎勵填充實作。我們改用深度即槓桿效應。
  • 「介面」作為 TypeScript 的 interface 關鍵字或類別的公開方法:過於狹隘;此處的介面包含呼叫方必須知道的所有事實。
  • 「邊界」:與 DDD 的限界上下文過度重疊。請說 接縫 或 介面。

更深入

  • 根據依賴關係深化一個集群,請參閱 DEEPENING.md:依賴類別、接縫紀律,以及取代而非分層測試。
  • 探索替代介面,請參閱 DESIGN-IT-TWICE.md:啟動多個並行子代理以多種截然不同的方式設計介面,然後根據深度、局部性和接縫位置進行比較。

Individual skills in this repo

This repo contains 3 individual skills — each has its own dedicated page.

相關技能