非程式碼的重構
前面幾章我們重構的對象都是程式碼:提取函式、消除魔法數字、分離配置。但你有沒有想過,文件也會腐敗?
當一份規則文件從 50 行長到 450 行,閱讀者要在腦中同時追蹤的概念數量跟第一章提到的那個 858 行 Python 檔案沒有本質區別。認知負擔不只存在於程式碼中——任何需要人類閱讀和理解的東西都受它影響。
問題:文件膨脹
v0.28.0 到 v0.31.0 之間,專案的規則文件經歷了 9 個版本的迭代。每次迭代都在解決真實的問題:補充遺漏的邊界情況、新增流程步驟、記錄決策理由。每一次修改都合理,但累積的結果是:
1parallel-dispatch.md 280 行 ← 原本是「什麼時候可以並行」的簡單指南
2task-splitting.md 230 行 ← 原本是「怎麼拆任務」的清單
3ticket-lifecycle.md 220 行 ← 原本是「Ticket 狀態怎麼轉」的流程
4version-progression.md 180 行 ← 原本是「什麼時候推進版本」的判斷
5incident-response.md 170 行 ← 原本是「出錯了怎麼辦」的流程
6query-vs-research.md 130 行 ← 原本是「查資料要不要派人」的二選一
7plan-to-ticket.md 100 行 ← 原本是「計畫怎麼變成 Ticket」的流程
8decision-tree.md 452 行 ← 核心決策樹,每次都在「補一個分支」問題不是內容不正確——每一行都有存在的理由。問題是讀不動。
一個新加入的代理人需要閱讀 parallel-dispatch.md 來決定能不能並行派發任務。它真正需要的資訊是:觸發條件(5 行)、安全檢查清單(6 行)、決策流程圖(5 行)。但它必須在 280 行中找到這些——剩下的 264 行是 5W1H 格式範例、分析任務的並行原則、Agent Teams 場景表、進度追蹤模板。
這就像在一個 500 行的函式裡找那 20 行核心邏輯。
膨脹的過程
文件膨脹的方式和程式碼膨脹幾乎一模一樣。回顧 parallel-dispatch.md 的成長軌跡:
| 版本 | 行數 | 新增原因 |
|---|---|---|
| v1.0 | 60 行 | 初始版本:觸發條件 + 決策流程 |
| v1.1 | 90 行 | 補充:安全檢查清單(因為有人忘記檢查檔案衝突) |
| v1.2 | 130 行 | 新增:Agent Teams 派發方式(新功能) |
| v2.0 | 180 行 | 新增:5W1H 格式範例(因為有人不知道怎麼寫) |
| v2.3 | 230 行 | 新增:分析任務並行原則、進度追蹤模板 |
| v2.5 | 280 行 | 新增:並行派發後驗證流程(因為有人忘記驗證) |
每一次新增都在解決真實問題。沒有人故意讓文件變長。但六個版本之後,一個簡單的「能不能並行」判斷指南變成了包羅萬象的操作手冊。
這和程式碼中的「上帝函式」成因一樣:每次「加一點」都合理,但沒有人停下來問「這個函式是不是該拆了」。
解決方案:Progressive Disclosure
程式碼重構有 Extract Method——把函式內部的細節提取到獨立函式中。文件重構有對應的技巧:Progressive Disclosure(漸進式揭露)。
核心思想:常駐只保留決策入口和強制規則,細節放到參考文件中按需載入。
這和函式設計的道理一樣。你不會把排序演算法的完整實作放在 main() 裡面,你會呼叫 sort()。同樣地,規則文件的讀者不需要在判斷「能不能並行」時看到「Agent Teams 的 3-4x 成本計算方式」。
精簡原則
我們制定了四條原則來指導文件重構,和程式碼重構的原則一一對應:
| 程式碼原則 | 文件原則 | 說明 |
|---|---|---|
| 單一責任 | 一個文件回答一個問題 | 常駐文件只回答「怎麼判斷」,不回答「細節怎麼做」 |
| 資訊層級 | 決策入口 → 強制規則 → 參考細節 | 讀者按需深入,不強制閱讀全部 |
| DRY | 細節只寫一次,放在 references/ | 多個文件引用同一份參考,不複製貼上 |
| 量化驗證 | 精簡前後行數對比 | 有數字才知道改善了多少 |
具體做法
以 parallel-dispatch.md 為例,精簡過程分三步:
Step 1:識別「決策入口」和「參考細節」
閱讀 280 行內容,對每一段問:「讀者在做『能不能並行』這個決策時需要這段嗎?」
- 觸發條件表格 → 需要(決策入口)
- 安全檢查清單 → 需要(強制規則)
- 決策流程圖 → 需要(快查表)
- 數量原則 → 需要(簡短規則)
- 不適用場景 → 需要(負面清單)
- 5W1H 格式範例 → 不需要(移出)
- Agent Teams 場景表 → 不需要(移出)
- 進度追蹤模板 → 不需要(移出)
Step 2:提取到參考文件
1# 精簡前
2parallel-dispatch.md (280 行,所有內容混在一起)
3
4# 精簡後
5parallel-dispatch.md (98 行,決策入口 + 強制規則)
6 └→ references/parallel-dispatch-details.md (剩餘細節,按需查閱)Step 3:加入連結
1## 並行派發後驗證(強制)
2
3所有並行代理人回報完成後,**必須**執行 `git diff --stat` 驗證。
4
5> 詳細驗證步驟和常見原因:.claude/references/parallel-dispatch-details.md讀者看到這段就知道:「驗證是強制的,具體步驟在那個連結裡。」它可以選擇深入閱讀,也可以先完成手邊的決策。
精簡前後對比
看看 incident-response.md 精簡前後的結構差異:
1# 精簡前 (170 行)
2
3## 強制流程
4(流程圖 + 說明)
5
6## 強制觸發條件
7(觸發表格)
8
9## 派發對應表
10(代理人對應表)
11
12## 多視角分析原則 ← Level 3
13(詳細的分析方法論)
14
15## 安全等級分類 ← Level 3
16(安全等級表格 + 處理流程)
17
18## 報告格式範例 ← Level 3
19(完整的報告模板)
20
21## 禁止行為
22(禁止清單) 1# 精簡後 (64 行)
2
3## 強制流程
4(流程圖 + 說明)
5
6## 強制觸發條件
7(觸發表格)
8
9## 派發對應表
10(代理人對應表)
11
12## 禁止行為
13(禁止清單)
14
15## 相關文件
16> 詳細規則:.claude/references/incident-response-details.mdLevel 3 的內容(多視角分析、安全等級、報告格式)整段移到 references/ 目錄。常駐文件只剩下做決策需要的資訊。
實際成果
7 個規則文件的精簡結果:
| 文件 | 精簡前 | 精簡後 | 縮減 |
|---|---|---|---|
| parallel-dispatch.md | 280 行 | 98 行 | -65% |
| task-splitting.md | 230 行 | 93 行 | -60% |
| ticket-lifecycle.md | 220 行 | 70 行 | -68% |
| version-progression.md | 180 行 | 69 行 | -62% |
| incident-response.md | 170 行 | 64 行 | -62% |
| query-vs-research.md | 130 行 | 46 行 | -65% |
| plan-to-ticket.md | 100 行 | 43 行 | -57% |
| 合計 | 1310 行 | 483 行 | -63% |
核心決策樹 decision-tree.md 也從 452 行精簡到 286 行(-37%)。它的縮減幅度較小,因為決策樹本身就是「決策入口」——大部分內容都是必要的分支判斷。
後記:上面的數字是 v3.0.0 精簡完成時的快照。精簡後不到兩週,
plan-to-ticket.md因為新增「執行中額外發現」流程從 43 行長回 87 行,decision-tree.md因為新增 TDD Phase 路由從 286 行長回 434 行。這不代表精簡失敗——新增的內容都是必要的新功能。但它提醒我們:文件重構和程式碼重構一樣,是持續的紀律。
通用原則
從這次文件重構中,我們提煉出四個可複用的原則:
原則 1:單一責任
每份文件應該只回答一個核心問題。
| 文件 | 核心問題 | 不該包含 |
|---|---|---|
| parallel-dispatch.md | 能不能並行? | Agent Teams 的完整操作手冊 |
| incident-response.md | 出錯了怎麼處理? | 每種錯誤的詳細分析範例 |
| ticket-lifecycle.md | Ticket 狀態怎麼轉? | Hook 的技術實作細節 |
判斷方式和函式一樣:如果描述這份文件的用途需要「和」這個字,它可能需要拆分。
原則 2:資訊層級
按讀者的需求深度分層:
1Level 0: 快查表(一眼就能找到答案)
2Level 1: 強制規則(必須遵守的約束)
3Level 2: 決策流程(判斷邏輯)
4Level 3: 參考細節(範例、模板、歷史記錄)常駐文件只包含 Level 0-2,Level 3 放在 references/ 目錄下。
對比程式碼的資訊層級:
1# Level 0: 函式簽名(一眼就知道做什麼)
2def can_dispatch_parallel(tasks: list[Task]) -> bool:
3 # Level 1: Guard clauses(強制規則)
4 if len(tasks) < 2:
5 return False
6 if has_dependency(tasks):
7 return False
8
9 # Level 2: 核心邏輯(判斷邏輯)
10 return not has_file_overlap(tasks)
11
12# Level 3: 實作細節(在被呼叫的函式裡)
13def has_file_overlap(tasks):
14 # 50 行的具體實作...同一個概念,同一個結構。
原則 3:DRY
文件之間也會出現重複。同一段「Wave 獨立性原則」如果在 parallel-dispatch.md、task-splitting.md、version-progression.md 三個地方都寫了,修改時就要改三處。
解決方式和程式碼一樣:抽到共用的參考文件,其他文件用連結引用。
原則 4:量化驗證
沒有數字的重構是自我感覺良好。精簡前後一定要量化比較:
1# 文件行數統計
2wc -l .claude/rules/flows/*.md .claude/rules/guides/*.md
3
4# 前後對比
5echo "精簡前: 1310 行"
6echo "精簡後: 483 行"
7echo "縮減率: 63%"和程式碼重構的 -65% 行數對比一樣,行數本身不是目標,但它是認知負擔降低的代理指標。
常見錯誤
文件重構也有自己的陷阱:
錯誤 1:過度精簡
把所有細節都移走,常駐文件只剩下標題和連結。讀者每做一個決策都要點開參考文件,跳轉次數太多反而增加認知負擔。
1# 錯誤:過度精簡
2## 並行派發
3> 詳見:references/parallel-dispatch-details.md
4
5## 任務拆分
6> 詳見:references/task-splitting-details.md這等於一個函式裡全是 call_other_function(),讀者什麼都看不到。常駐文件至少要包含決策入口(判斷邏輯)和強制規則(不可違反的約束)。
錯誤 2:按「章節」拆分而非按「層級」拆分
把文件按目錄拆成多個小文件,但每個小文件仍然混合了決策入口和參考細節。這只是把一個大問題變成了多個小問題。
正確的拆分維度是資訊層級,不是主題章節。
錯誤 3:沒有更新連結
精簡後忘記在常駐文件中加入參考文件的連結。讀者需要細節時找不到入口。這和重構後忘記更新 import 一樣危險。
程式碼 vs 文件重構對照表
程式碼重構和文件重構的手法其實是同一套思維的不同實踐:
| 維度 | 程式碼重構 | 文件重構 |
|---|---|---|
| 壞味道 | 函式太長、巢狀過深 | 文件太長、層級不分 |
| 核心手法 | Extract Method | Progressive Disclosure |
| 單一責任 | 一個函式做一件事 | 一份文件回答一個問題 |
| DRY | 提取共用模組 | 提取共用參考文件 |
| 量化指標 | 行數、認知負擔指數 | 行數、常駐 vs 參考比例 |
| 驗證方式 | 測試通過 | 讀者能在 30 秒內找到答案 |
| 失敗的重構 | 過度拆分導致跳轉太多 | 過度精簡導致資訊不足 |
| 觸發條件 | 函式超過 30 行 | 文件超過 100 行且混合多個層級 |
| 典型比例 | 858 行 → 296 行 (-65%) | 280 行 → 98 行 (-65%) |
最後一行不是巧合。兩個案例的縮減率接近,是因為底層原理相同:大約 1/3 的內容是核心邏輯(決策入口),2/3 的內容是支撐細節(參考資料)。
什麼時候該重構文件
和程式碼一樣,不是所有文件都需要重構。觸發條件:
| 指標 | 閾值 | 行動 |
|---|---|---|
| 文件長度 | > 100 行且混合多層級 | 評估是否需要分離 |
| 讀者反饋 | 「找不到需要的資訊」 | 重新組織資訊層級 |
| 更新頻率 | 每次更新都在不同段落 | 考慮按變更頻率拆分 |
| 重複內容 | 同一段話出現在 2+ 份文件 | 提取到共用參考 |
思考題
- 你的專案有沒有「什麼都寫在 README」的情況?如果有,試著用 Progressive Disclosure 原則拆分它。
- 為什麼
decision-tree.md的縮減幅度(-37%)比其他文件(-57% 到 -68%)小?這說明了什麼? - 文件重構有一個程式碼重構沒有的風險:「過度精簡導致讀者找不到需要的資訊」。你會怎麼驗證精簡後的文件仍然足夠完整?
實作練習
練習 1:評估文件健康度
找一份超過 150 行的文件(你自己的專案 README、API 文件、團隊 Wiki),回答以下問題:
- 這份文件回答幾個核心問題?(如果超過 1 個,考慮拆分)
- 讀者能在 30 秒內找到最常需要的資訊嗎?
- 有沒有段落只在特定情境下才需要閱讀?
練習 2:執行 Progressive Disclosure
對那份文件執行三步精簡:
- 標記每一段的資訊層級(Level 0-3)
- 將 Level 3 的內容提取到獨立的參考文件
- 在原文件中加入連結
練習 3:量化驗證
計算精簡前後的行數和縮減率。如果縮減率低於 30%,思考是否原本的結構就已經不錯。如果超過 70%,檢查是否過度精簡了。
參考範圍
根據本章的實際案例,健康的縮減率大約在 55%-68% 之間。核心決策類文件(如 decision-tree)的縮減率通常較低(30%-40%),因為它本身就是決策入口。
小結
重構不只是程式碼的事。任何需要人類閱讀的東西——規則文件、操作手冊、架構文件——都會隨著時間膨脹,累積認知負擔。
核心手法是 Progressive Disclosure:常駐只保留讀者當下需要的資訊,細節放到參考文件中按需載入。這和 Extract Method 的道理完全一樣:呼叫端只需要知道函式名稱和參數,不需要看到完整實作。
程式碼壞味道有 code smell,文件壞味道也有——只是比較少人談論。