技術文件的失敗方式非常具體,也非常好預測。有人在兩週清閒的時間裡寫下一大堆,接著系統變了,沒有人回頭更新,一年之內那份文件就開始信心十足地講著錯誤的內容。到了那個時候,它比什麼都沒有還要糟,因為相信它的讀者會依據早已不成立的資訊去動手。

常見的反應是號召大家多寫一些,而這只會讓同樣的失敗來得更快。有用的反應是少寫,並且認真挑選寫什麼,因為真正的瓶頸不是寫作的工夫,而是維護的工夫。文件從寫完那一刻起,就開始被現實甩在後面。

判斷一份文件該不該存在,唯一經得起時間的檢驗是: 當它變錯的時候,會不會有人察覺?部署指南天天有人用,錯誤立刻就會浮出來。一份二十頁的子系統說明只會被讀一次,它的錯誤要等到十八個月後,有人照著它動手時才浮出來。沒有人真正使用的文件只會悄無聲息地腐爛,而恰恰是這一類文件應該一開始就不要寫。


文件為什麼會過期

有三種機制,其中只有一種可以叫做懶惰。

文件住在它所描述的東西之外。 改程式碼並不等於改一個維基頁面,所以兩者要保持一致,全靠有人記得。那份記性會穩定地失效,而且文件離程式碼越遠,失效得越快。它在另一個工具裡、另一套權限後面、另一個介面上,僅僅是這點距離就已經足夠。

它寫的是實作而不是意圖。 一份解釋某個元件目前如何運作的文件,每一次重構都會讓它失效。而一份解釋這個元件為什麼存在、滿足了什麼限制的文件能活下來,因為原因變化的頻率遠低於程式碼。

沒有人是它的主人。 屬於所有人的文件其實不屬於任何人,它的正確性從來不會在某個時刻變成某個具體的人的問題。

對策直接從原因推出來:把它放在程式碼旁邊,寫意圖而不是機制,並且給每一份文件指定一位有名有姓的負責人,再給它一個真正會被拿出來使用的場合。

值得維護的技術文件

四份文件涵蓋了大部分價值。其餘的都必須自己證明存在的理由。

一份能讓你把系統跑起來的 README。 這是什麼、怎麼設定、怎麼跑測試、怎麼發布。它一直在被使用,所以錯誤很快就會暴露。這是任何儲存庫裡回報最高的一份文件,同時也是最常被原封不動留成專案範本、誰都沒有編輯過的那一份。

一份架構概覽。 主要的幾塊是什麼、它們之間如何溝通、為什麼被分開。一頁文字加一張圖,描述形狀而不是細節。它很少變動,卻能回答那個問題:如果沒有它,每一位新同事都得自己把所有程式碼讀一遍再重新拼出答案。

決策記錄。 簡短的筆記,記下一個決定、考慮過的替代方案,以及做出選擇的理由。業界通常稱之為架構決策記錄,簡稱 ADR。它們只增不改,永遠不需要更新,並且能防止最昂貴的一類重工:把已經有結論的問題重新拿出來草率地爭一遍,只因為沒有人還記得當初拍板的那個限制。

針對會壞的東西的維運手冊。 維運手冊也就是 runbook,是故障處理的操作步驟:怎麼診斷、怎麼修復那些你真的遇過的故障。它寫於事故剛剛過去、記憶還新鮮的時候,並在下一次事故中接受檢驗。一份還沒有人照著走過的維運手冊,只是草稿。

請注意,這四份文件沒有一份是在描述程式碼如何運作。那是程式碼自己的職責,任何用文字覆述程式碼的段落都會變成第二個事實來源,遲早會和第一個互相矛盾。

為又累又趕時間的人寫

大部分技術文件是在壓力下被讀到的,讀者帶著一個非常具體的問題,而且常常是在下班之後。請為這樣的讀者寫,而不是為一個悠閒的讀者寫。

先給答案,再講解釋。 凌晨兩點讀你維運手冊的人,需要的是指令,理由排在後面。把背景放在答案前面,這種結構只對作者方便,對其他任何人都不方便。

寫得具體。 真實的指令、真實的路徑、真實的範例值。「請設定合適的環境變數」不是一條指示,它只是對一條指示的描述。讀者打開這一頁,恰恰就是想知道合適指的是什麼。

寫清楚哪裡會出錯。 失敗的形態以及它們看起來是什麼樣子,往往是整頁裡最有價值的內容,因為那正是讀者此刻正在經歷的東西。

短到足以保持正確。 每多一句話,就多一筆維護債務。一頁只涵蓋常見情況、並且坦白承認自己邊界的文件,勝過一份涵蓋了所有情況卻在三處出錯的文件。

讓一個頁面容易被檢索系統引用的那套紀律,同樣能讓它對一位精疲力盡的同事好用,這正是我們那篇談為什麼你的內容有排名卻從不被引用的文章在公開寫作上想說的意思。

如何讓它保持存活

把它放進儲存庫。 與程式碼一起移動的文件,會在與程式碼同一次審查裡被改動,這是唯一能可靠讓兩者保持一致的機制。

在程式碼審查裡一併檢查。 如果某次改動讓一份文件變錯了,那就是一條和其他意見沒有區別的審查意見。這是所有可用習慣裡槓桿最大的一個,而且不花一分錢。

能測的就測。 能在管線裡真正跑起來的安裝步驟,就不再是一廂情願。如果你的 README 聲稱三條指令就能得到一個可執行的系統,那就讓一個工作去證明它。

該刪就刪。 一份錯誤的文件比一份缺失的文件更糟,因為人們會信任它。當某樣東西過時了而且沒有人會去修,就把它移走,並記下丟掉了什麼。

給會過期的東西標上日期。 任何帶著版本號、價格或外部相依的內容都應該帶上日期,好讓讀者自己判斷還能不能相信它。

這件事到底為了什麼

文件是讓知識不再依賴某幾個人的機制。全部好處就在這裡,所以主張寫文件是一件生意上的事,而不是美感上的事。

一個只有一個人會部署的系統,它的復原時間等於那個人的可用時間。一個沒有人能說清理由的元件,要麼被重建,要麼被當作迷信保留下來。兩者都會出現在技術盡職調查的問題清單裡,兩者都會拉長開發者到職上手的時間,而且兩者其實是同一個問題換了身衣服。

Mecanik 在每一個專案的交接環節都會寫下這些文件,這是我們軟體開發工作的一部分。而最終真正被用起來的那份文件,幾乎總是比當初要求的那份更短。



常見問題

技術文件為什麼會過期? 因為它住在程式碼之外,兩者是否一致全靠有人記得;因為它寫的是實作而不是意圖,每一次重構都會讓它失效;也因為沒有人是它的主人,它的正確性從來不是某個具體的人的問題。把它放進儲存庫,並在程式碼變更的同一次審查裡檢查,可以同時解決這三個原因。

軟體團隊應該維護哪些文件? 四樣東西涵蓋了大部分價值:一份能把系統跑起來的 README,一頁說明形狀與理由的架構概覽,只增不改、記錄當初為什麼這麼選的決策記錄,以及針對你們真的遇過的故障的維運手冊。至於描述程式碼如何運作的內容,不在這份清單上。

什麼是決策記錄? 一段簡短的筆記,記下一個決定、考慮過的替代方案,以及做出選擇的理由。因為它記錄的是某個時刻而不是目前狀態,所以永遠不需要更新,也能防止已經有結論的問題被那些不再記得當初限制的人草率地重新爭論一遍。

技術文件應該怎麼寫? 為一個疲憊、有壓力、只想找到某一件具體事情的人而寫。先給答案再作解釋,用真實的指令和真實的路徑而不是對它們的描述,寫清楚哪裡會出錯以及它看起來是什麼樣,並且短到足以保持正確。

過期的文件應該刪掉嗎? 如果沒有人會去修,就應該刪。一份錯誤的文件比一份缺失的文件更糟,因為讀者會信任它並照著行動。刪掉它,記下丟掉了什麼,同時給任何包含版本號、價格或外部相依的內容標上日期,讓讀者自己判斷。