文件的職責數從修改紀錄讀出:長度當拆分訊號的誤判、加段落之前的檢查與拆完之後的外部引用
單一職責原則把職責定義成改變的理由。放在版本控制裡的文件,每一次修改都留下一筆紀錄,所以一份文件承擔幾種職責,可以從它被哪些主題修改過直接讀出來:git log --follow --format='%h %s' -- <檔案> 列出修改,依 commit 標題歸類,類數就是職責數。作者預測「這份文件會因為什麼事件更新」的變動理由測試適用於還沒有歷史的新文件;有歷史的文件用紀錄,兩者可以互相對照。
長度當拆分訊號的兩種誤判
長度與職責數是兩個量,以長度當拆分的觸發條件會在兩個方向上判錯。一份 600 行的設定參數表只描述同一份設定的欄位,讀者逐列查詢,長度觸發了拆分而它只有一種職責,切開之後讀者要在幾份檔案之間找一個欄位。一份 80 行的 README 寫了安裝、貢獻規則、發版流程與聯絡窗口,長度沒有觸發,它留在原地繼續累積主題。程式碼有同樣的兩個方向:200 行的產生器被六個不相干的需求改過,900 行的解析器只屬於同一個需求的連續演進。
集中登記型文件是例外:CHANGELOG、索引頁、術語表的職責就是集中登記所有主題,被許多主題修改是它的設計目的。依職責拆它不會降低修改的衝突,處置改成每個項目一個片段檔;不想改成片段檔的逐行清單,可以在 .gitattributes 設 merge=union,兩邊追加的行都保留、不產生衝突,代價是真正的衝突也不出標記。
加段落之前的檢查
一份文件多出一種職責,發生在有人往裡面加一節的那一次修改。每一次加段落單獨看都有理由,累積起來就是一份什麼都管的文件,而事後拆分的成本比加的當下選對位置高得多。加之前問一句:這一節的修改理由,在不在這份文件既有的修改理由裡——既有理由從修改紀錄讀,不從標題猜。不在的話,先找承接它的那一份文件;找不到才考慮開新檔,原檔留一句連結。
規則類文件(專案規範、agent 指令、skill 檔)最需要這一問。它們的讀者照著執行,每一條規則都有人在某一次出事之後補上,所以它們累積段落的速度比文章快,也最少人回頭整理。
規則類文件的職責稽核
累積式的規則檔適合定期跑一次職責稽核:讀修改紀錄、依主題歸類、對照每一類落在哪幾節。主題數多、而且某幾類只集中在少數幾節時,那幾節是拆出去的候選。稽核的產出是一張表(主題 / 修改次數 / 落在哪幾節 / 處置),處置分留在原處、移到承接它的檔案、拆成新檔三種。
修改紀錄讀不出主題時,稽核的精度跟著降:「docs: update」這類標題要改看 diff 落在哪幾節;squash merge 把多個主題壓成一筆;改過檔名的文件要加 --follow 才看得到改名之前的紀錄。
拆完之後的外部引用與原檔
拆分之後檔與檔之間的交界缺陷(兄弟檔互指不對稱、定義與使用分屬兩檔、散文計數過期)見 #343。那一組檢查的對象是新檔彼此之間,另有兩件事落在新檔以外:
- 指向原檔的外部引用:其他文件、腳本、agent 指令與書籤引用的是原檔路徑與原段標錨點。段落搬走之後,連到原段標錨點的連結仍然打得開原檔,只是停在頁面頂端;站內的連結檢查若會比對錨點就會報出來,而 skill 目錄、其他 repo 與 agent 指令裡的引用多半不在那道檢查的範圍內,失效時沒有任何訊號。拆完要用
grep -rl '<原檔路徑>'與grep -rn '<原檔名>#'找出來逐一改。 - 原檔保留成導覽表:原檔的路徑已經被引用,刪掉它等於把上一條的失效全部觸發一次。原檔改成一張表,每一列寫一種讀者需求、對應的新文件與那份文件涵蓋什麼。
為什麼既有的檢查沒擋住
寫作 skill 判斷該不該拆篇的觸發條件寫的是「一篇文章越寫越長、懷疑塞了兩個主題」,文件撰寫的決策表用的是約 500 行這類行數門檻。兩者都以長度啟動,所以短而混雜的文件不會進入變動理由測試;而變動理由測試本身是作者的預測,作者對自己剛加的那一節總是預測得出它屬於這裡。拆完之後的交界檢查列的全是新檔之間的位置,原檔與外部引用不在清單上。
論述基礎與限制
本卡的方法寫在語言無關的設計原則教材從修改紀錄畫模組邊界與 record 方法論依職責拆分文字文件,還沒有拿任何一份實際的規則檔跑過稽核,主題數多到什麼程度該拆沒有量過,所以本卡不給門檻。修改紀錄當量測工具的前提是 commit 標題寫得出主題,這一點在不同專案差異很大。
跟其他抽象層原則的關係
- #376 段落的範圍由標題與所屬分類共同限定——同一個 case 的另一個成因:那一張處理題目範圍檢查只比標題,本卡處理單一職責測試以長度為觸發條件而沒有啟動。
- #343 拆分產生的缺陷落在檔與檔的交界,每一份單獨讀都是對的——本卡在它的交界檢查之外補上新檔以外的兩件事:外部引用與原檔。
- #231 案例文章跟跨公司比較是兩個分析責任——那一張是文章層的單一職責拆分;本卡把同一個判斷換成可以量的紀錄。
- #263 同一個對象被兩篇各自分解一次時,不相容會長得像互補——依職責拆與依資訊層級精簡是兩種切法,同一批文件被兩篇各切一次時,要先寫出兩者各自處理什麼。
判讀徵兆
- 一份文件的最近幾筆修改,commit 標題講的是幾件互不相干的事。
- 兩個人同時改同一份文件的不同段落,仍然撞到合併衝突。
- 要加的一節,在這份文件的修改紀錄裡找不到同類的修改。
- 拆完之後,有人回報某個連結打開了文件卻沒有跳到該去的段落。
Case
2026-10-19,從修改紀錄畫模組邊界的使用者審閱要求另寫一篇文字文件的拆分,並分析如何把它的原則加進寫作 skill 與多輪審查。盤點時看到寫作 skill 判斷拆篇的觸發條件與文件撰寫的決策表都以長度啟動,與那兩篇文章的論點相反;拆完之後的交界檢查沒有涵蓋原檔與外部引用。使用者決定把這幾項全部改進 skill。