# 用 mattpocock-skills 以三項測試進行修剪 — 讓 Fowler 異味與 codebase-design 保持分開

> Matt Pocock 的 mattpocock-skills 外掛教的是如何為智能體寫作：修剪、密集詞彙，以及為什麼 Fowler 異味與 Ousterhout 模組要分開。

- Source: https://oharu121.com/zh-tw/blog/matt-pocock-skills-fowler-smells-ousterhout-deep-shallow-modules/
- Published: 2026-08-25T00:15:36+09:00
- Tags: Claude Code

---
**重點摘要**

- Matt Pocock 的 skill 刻意寫得精簡，原因是一個叫 `writing-for-agents` 的 meta-skill 定義了確切的測試準則：刪掉不會改變模型預設行為的句子，用一個密集的預訓練詞彙取代寫得詳盡的說明，把參考資料推到指標背後而不是內嵌。
- Fowler《Refactoring》裡的異味（Shotgun Surgery、Feature Envy、Data Clumps，另外還有 9 項）住在叫 `code-review` 的 skill 裡，而不是 `codebase-design`；後者用的是另一套 Ousterhout 系的深層／淺層模組詞彙，並且明確拒絕 Ousterhout 本人的深度指標。
- 讀了實際原始碼後，糾正了一支影片在被複述之前就提出的兩個具體說法：`grill-me` 是一個 7 行的包裝，包住一個叫 `grilling`、28 行的基礎單元，並不是單獨 5 行。
- 真正拿這套準則來用而不只是讀過，把異味基準納入既有的程式碼審查，而不是另外跑一次獨立的審查，並且在同一個 session 就抓到了一個真實的 bug。

## 引言

看了一支關於 Matt Pocock 的 [mattpocock-skills](https://github.com/mattpocock/skills) 外掛的[影片](https://www.youtube.com/watch?v=aR97E7aKEgg)。這個外掛以一個叫 `grill-me` 的 skill 為核心，影片形容它是 5 行指令，會在 agent 寫任何程式碼之前逼你把計畫講清楚。這個 repo 早在之前的 session 就裝了這個外掛，比起重複影片的摘要，更想搞清楚那種精簡背後的真正準則，所以要求做一次老實的稽核：到底有沒有真的在用 `mattpocock-skills`，還是只設定好就晾在那沒動。**讀了外掛自己的原始碼之後，影片裡兩個具體的說法在被複述到任何地方之前就先被糾正了。**`grill-me` 是包住一個 28 行基礎單元的 7 行包裝，而 Fowler《Refactoring》的程式碼異味其實住在跟大多數人猜的不一樣的 skill 裡。而且，把這套準則真正拿來用而不只是讀過，在加入的同一個 session 裡就在自己的審查流程中抓到一個真的 bug。這篇文章要講的是外掛自己的 meta-skill、`writing-for-agents`，實際上怎麼談修剪與密集詞彙，接著談它內建的兩套獨立程式碼異味系統，以及為什麼要把它們分開，而且是逐檔案對照原始碼確認的，不是對照一份改寫過的摘要。

## 影片的說法，以及為什麼需要驗證

影片的框架**具體到可以直接驗證**：`grill-me` 用 5 行程式向使用者逼問計畫，而 Fowler 的程式碼異味詞彙（Shotgun Surgery、Feature Envy、Data Clumps）住在外掛的 `codebase-design` skill 裡，也就是講深層模組設計的那個。兩個說法乍看都很合理。5 行符合一個強硬的系統提示詞可以有多短，而 `codebase-design` 聽起來就正是那種會定義「爛程式碼長什麼樣」的 skill。

**兩個說法讀了外掛自己的 repo 之後都站不住腳。** 這些 skill 分散在 5 個目錄裡，不是 1 個：`engineering`、`productivity`、`in-progress`、`misc`、`deprecated`。`grill-me` 確實只有 7 行，但它住在 `productivity/` 底下，而它實際的內容只有一個指令：呼叫 `Skill` 工具去執行 `grilling`，一個真正負責逼問的 28 行 skill。`codebase-design` 也真實存在，也確實定義了一套詞彙，但跟 Fowler 的完全是另一套。

## 撐起這種精簡文字的準則

這個外掛內建了一個叫 `writing-for-agents` 的 meta-skill，整篇主題就是怎麼寫剩下的 24 個 skill。它點出三個各自獨立的槓桿，沒有一個是「越短越好」。

### no-op 測試

**一句話能留下來，唯一的理由是它會改變模型的預設行為。** 用 skill 自己的說法：這句話會改變模型的動作，還是只是把模型反正都會做的事重講一遍？沒通過這個問題的句子會直接整句刪掉，而不是修短，因為把一個預設值的重述縮短，它仍然只是重述。

### leading word 這個概念

詞彙也不是裝飾。這個 skill 把一個緊湊、已經預訓練過的概念叫做「leading word」：一個模型從自己的訓練裡已經帶著分散式定義的 token，拿來重複使用，取代一整段說明。**`grilling` 本文之所以幾乎沒花什麼字講機制，正是因為它完全是用三個這樣的 leading word 組出來的。**「design tree」「frontier」「rounds」各自頂替一句說明，讀者一旦記住這個詞，之後每次使用就只花一個字，而不是十個字。

### 資訊層級

長度本身也不是敵人，而這正是「grill-me 只有 5 行」這種說法漏掉的部分。這個 skill 定義了一套層級：in-file step 是 agent 依序執行的動作，in-file reference 是同一份檔案裡按需查閱的內容，disclosed reference 則被移到旁支檔案、藏在一個指標背後，只有那個指標觸發時才會載入。

*Figure — InformationHierarchyLadder: writing-for-agents 的資訊層級：什麼留在檔案內，什麼移到指標背後。*

`codebase-design` 加上完整的詞彙表和 ASCII 圖總共 114 行，但**用這個測試來看沒有一行是灌水**，因為每一行都是讀者真正需要按需查閱的參考資料，而不是重述預設值。一個 15 行的 skill 和一個 114 行的 skill 都可能被正確地修剪；這套準則實際衡量的是層級結構，不是行數。

## 兩套刻意分開的程式碼異味詞彙

`code-review` 的異味清單是 Fowler《Refactoring》裡那份的 12 項版本：Mysterious Name、Duplicated Code、Feature Envy、Data Clumps、Primitive Obsession、Repeated Switches、Shotgun Surgery、Divergent Change、Speculative Generality、Message Chains、Middle Man、Refused Bequest。每一項都用同樣的方式寫：它是什麼、怎麼修。**而且兩者都受清單上方只寫過一次的兩條規則約束**：文件化的 repo 標準優先於這份基準，而且每一項異味都只是一個貼了標籤的判斷依據，從來不是硬性違規。

`codebase-design` 完全不用那套詞彙。它的詞彙表定義了 Module、Interface、Implementation、Depth、Seam（歸功於 Michael Feathers）、Adapter、Leverage、Locality，每一項都附有明確警告，提醒不要用大多數人會直覺選用的替代詞：Module 不要用「unit」或「service」，Interface 不要用「API」或「signature」，Seam 不要用「boundary」。一個深層模組把小小的 Interface 配上大量的 Implementation；淺層模組則相反，skill 說要避免這種情況。**它還指名自己的出處，然後又部分否定了它。** Ousterhout 原本的指標是用 Implementation 行數對 Interface 行數的比例來衡量 Depth，而這個 skill 指名批評這種框架，因為它會獎勵灌水 Implementation，改用「depth as leverage」來衡量。

*Figure — TwoSmellVocabularies: Fowler 異味與 Ousterhout 系模組：兩套從未合併的詞彙。*

這個外掛裡，兩套詞彙彼此完全沒有互相借用。負責跑程式碼庫健康掃描的 `improve-codebase-architecture`，被明確要求使用 `codebase-design` 的用詞，不要滑向「component」「service」「API」或「boundary」。**這兩套系統解決的是不同問題：一套是指出一份 diff 已經出了什麼錯，另一套是在任何東西出錯之前，指出該怎麼形塑一個 Interface。** 像一份簡短摘要那樣把兩者塌縮成一份清單，會丟失各自存在的理由。

## 真正拿這套準則來用，而不只是講它

**讀懂這套準則是一回事，實際拿來用是另一回事**，而這個 repo 早就有地方可以用它。它自己的發布流程在每次合併前都會跑一次程式碼審查，對照的是一份 repo 專屬的檢查清單，但那份清單從來沒有一個通用的程式碼異味面向。**agent 提出的方案，是把 `code-review` 的 12 項基準連同出處一起，折進既有的檢查清單裡當作第 8 個面向，而不是把外掛的 `code-review` skill 當成第二個獨立的審查再跑一遍。** 同一份 diff 跑出兩份審查結果，代表每次發布都要協調兩者之間的分歧；一份檢查清單多一個面向則不必。

同一次造訪也順手補上了這個 repo 一直沒有的領域詞彙表。要求立刻播下種子而不是延後，詞彙從實際的程式碼裡挑(`Article`、`Locale`、`Figure`、`Thumbnail`，另外還有 8 個)，而不是憑空發明，**每一個都在寫下來之前，對照實際定義它的檔案確認過。**

修剪測試也用在了這個 repo 自己的文字上，範圍比全面重寫窄得多。選擇只對這個 repo 裡最長的兩份 skill 檔案跑 no-op 測試和 leading word 測試，把每一段事件敘述和防護表格原封不動地留著：`writing-for-agents` 自己就說，那種素材是合理的快取：「沒寫下來的慣例、一個選擇背後的理由、沒有任何設定會招認的坑」，不是該修剪的灌水。

## 改變了什麼，又是怎麼驗證的

**這次對 repo 自己 skill 跑的修剪流程，與其說找到了灌水，不如說更確認了這套準則本身。** 把 no-op 測試和 leading word 測試套用到一份 988 行的發布 skill 和一份 609 行的風格指南上，各自只找到 3 處合理的刪減，不是幾十處。這是設計上就該低的數字，不是漏抓：兩份檔案的長度大半是從真實發布中學到的事件記憶、精確指令、精確的失敗模式，而這正是 `writing-for-agents` 自己的規則會保護、而不是標記出來的東西。

新加的審查面向，第一次真正的考驗來自一份真的動到程式碼、而不只是文件的 diff，而它真的抓到了東西。在把一段重複的 fence 解析程式合併成一個共用函式的過程中，收尾規則悄悄變鬆了：它改成只比對 fence 標記開頭的文字，而不是要求整行都只能是 fence 字元（也就是相鄰函式原本就在用的那條更嚴格的規則），而且這個新函式自己的註解還宣稱它共用了那條規則，實際上並沒有。**剛加進去的第 8 個面向，在這次 pull request 合併之前就抓到了它。** 這個 bug 是真的，當時在語料庫裡是潛伏而非已經發作，並在引入它的同一個 session 裡修好。**這份異味基準不是檢查清單上的裝飾，它改變了實際被審查的內容。**

## 總結

**Matt Pocock 的 `mattpocock-skills` 外掛之所以精簡，是因為裡面的 meta-skill 精確定義了該刪什麼、該留什麼：** 重述過的預設句被刪掉，密集的預訓練詞彙取代說明，參考資料被移到指標背後，而不是內嵌。**它內建的程式碼異味詞彙不是一套，而是兩套：** Fowler 那套，用在一份已經出錯的 diff 上；修改過的 Ousterhout 那套，用在還沒出錯之前形塑一個 Interface。那支影片把詞彙和行數這兩種區別都混在一起，而讀原始碼、不讀摘要，正是抓出這一點的方法。真正把這套準則用起來，把一套詞彙折進既有審查裡，而不是另外跑一個工具，讓這個差異變得看得見：它改動的那份檢查清單，在那次發布上線之前，抓到了自己內部的一個 bug。
