如何寫好技術文檔——來(lái)自Google十多年的(de)文檔經驗
很多技術人(rén)自己非常輕視技術文檔的(de)書寫,然而(ér)又時(shí)常抱怨文檔不(bù)完善、質量差、更新不(bù)及時(shí)…… 這(zhè)種在(zài)程序猿間普遍存在(zài)的(de)矛盾甚至已經演變成了(le/liǎo)一(yī / yì /yí)個(gè)段子(zǐ)。
文檔的(de)重要(yào / yāo)性
高質量的(de)文檔對于(yú)一(yī / yì /yí)個(gè)組織或團隊來(lái)說(shuō)有非常多的(de)益處,比如讓代碼和(hé / huò)API更容易理解、錯誤更少;讓團隊成員更專注于(yú)目标;也(yě)可以(yǐ)讓一(yī / yì /yí)些手工操作更容易;另外如果有新成員加入的(de)話有文檔也(yě)會讓他(tā)們更快融入……
寫文檔有比較嚴重的(de)收益滞後性,不(bù)像測試,你跑一(yī / yì /yí)個(gè)測試case,它能立即告訴你是(shì)對還是(shì)錯,它的(de)價值馬上(shàng)就(jiù)體現出(chū)來(lái)了(le/liǎo)。而(ér)寫一(yī / yì /yí)份文檔,随着時(shí)間的(de)推移,它的(de)價值才會逐漸體現出(chū)來(lái)。 你可能隻寫一(yī / yì /yí)次文檔,将來(lái)它會被閱讀上(shàng)百次、上(shàng)千次,因爲(wéi / wèi)一(yī / yì /yí)份好的(de)文檔可以(yǐ)在(zài)未來(lái)替你向别人(rén)回答類似下面這(zhè)些問題。
爲(wéi / wèi)什麽當時(shí)是(shì)這(zhè)麽決策的(de)?
爲(wéi / wèi)什麽代碼是(shì)這(zhè)樣實現的(de)?
這(zhè)個(gè)項目裏都有哪些概念?
……
寫文檔同樣對于(yú)寫作者也(yě)有非常大(dà)的(de)收益:
幫你構思規範化API: 寫文檔的(de)過程也(yě)是(shì)你審視你API的(de)過程,寫文檔時(shí)會讓你思考你API設計是(shì)否合理,考慮是(shì)否周全。如果你沒法用語言将API描述出(chū)來(lái),那麽說(shuō)明你當前的(de)API設計是(shì)不(bù)合理的(de)。
文檔也(yě)是(shì)代碼的(de)另一(yī / yì /yí)種展現: 比如你兩年後回過頭來(lái)看你寫過的(de)代碼,如果有注釋和(hé / huò)文檔,你可以(yǐ)很快速理解代碼。
讓你的(de)代碼看起來(lái)更專業: 我們都有個(gè)感覺,隻要(yào / yāo)文檔齊全的(de)API都是(shì)設計良好的(de)API,雖然這(zhè)個(gè)感覺并不(bù)完全正确,但這(zhè)兩者确實是(shì)強相關的(de),所以(yǐ)在(zài)很多人(rén)眼裏,文檔的(de)完善度也(yě)成爲(wéi / wèi)衡量一(yī / yì /yí)個(gè)産品專業度的(de)指标。
避免被重複的(de)問題打擾: 有些問題你隻需要(yào / yāo)寫在(zài)文檔裏,這(zhè)樣有人(rén)來(lái)問你的(de)時(shí)候你就(jiù)可以(yǐ)讓他(tā)直接去看文檔了(le/liǎo),而(ér)不(bù)是(shì)又給他(tā)解釋一(yī / yì /yí)遍。
爲(wéi / wèi)什麽大(dà)多數人(rén)都不(bù)喜歡寫文檔?
關于(yú)文檔的(de)重要(yào / yāo)性,每個(gè)技術人(rén)或多或少都知道(dào)一(yī / yì /yí)些,但很多人(rén)還是(shì)沒有寫文檔的(de)習慣,爲(wéi / wèi)什麽? 除了(le/liǎo)上(shàng)文中提到(dào)的(de)文檔的(de)收益滞後性外,還有以(yǐ)下幾點原因:
很多工程師習慣将寫代碼和(hé / huò)寫作割裂開,不(bù)僅僅是(shì)在(zài)工作上(shàng),而(ér)且在(zài)思想上(shàng)就(jiù)認爲(wéi / wèi)它們是(shì)完全不(bù)相關的(de)兩項工作,這(zhè)就(jiù)導緻好多人(rén)重代碼不(bù)重文檔。
也(yě)有很多工程師認爲(wéi / wèi)自己不(bù)善寫作,索性就(jiù)不(bù)寫了(le/liǎo)。 這(zhè)實際是(shì)個(gè)偷懶的(de)借口,寫文檔不(bù)需要(yào / yāo)華麗的(de)辭藻、生動的(de)語言,你隻需要(yào / yāo)将問題講清楚即可。
有時(shí)候工具不(bù)好用也(yě)會影響的(de)文檔寫作。如果沒有一(yī / yì /yí)個(gè)很好的(de)寫作工具将寫文檔嵌入到(dào)開發工作流程中的(de)話,寫作确實會增加工作的(de)負擔。
大(dà)多數人(rén)将寫文檔看做是(shì)工作的(de)額外負擔。 我代碼都沒時(shí)間寫,哪有時(shí)間寫文檔!,這(zhè)其實是(shì)錯誤的(de)觀念,文檔雖然前期有投入,但能讓你代碼的(de)後期維護成本大(dà)幅降低,磨刀不(bù)誤砍柴工這(zhè)個(gè)道(dào)理相信大(dà)家都還是(shì)能理解的(de)。
如何産出(chū)高質量文檔
既然理解了(le/liǎo)好文檔的(de)重要(yào / yāo)性,我們如何保證在(zài)時(shí)間的(de)長河中維護好一(yī / yì /yí)份文檔,這(zhè)裏有些相關的(de)方法論,大(dà)家可以(yǐ)參考下。
像管理代碼一(yī / yì /yí)樣管理文檔
對于(yú)如何寫出(chū)好代碼,整個(gè)技術圈已經有好多經驗的(de)總結了(le/liǎo),比如書籍《重構》《代碼簡潔之(zhī)道(dào)》…… 針對各種編程語言,也(yě)有相關的(de)規範,比如國(guó)外的(de)Google C++規範,國(guó)内的(de)阿裏Java開發規範等…… 但對于(yú)文檔 似乎相關的(de)資料卻很少。但實際上(shàng),不(bù)應該把文檔和(hé / huò)代碼割裂開來(lái),你可以(yǐ)簡單粗暴地(dì / de)認爲(wéi / wèi)文檔其實就(jiù)是(shì)用一(yī / yì /yí)種特殊語言書寫的(de)代碼,這(zhè)種語言就(jiù)是(shì)人(rén)類的(de)語言。這(zhè)麽想的(de)話,實際上(shàng)我們很多在(zài)代碼和(hé / huò)工程中總結出(chū)來(lái)的(de)經驗,也(yě)可以(yǐ)直接用在(zài)文檔中,比如:
有統一(yī / yì /yí)的(de)規範
有版本控制
有明确的(de)責任人(rén)維護
有變更Review機制
有問題的(de)反饋和(hé / huò)更新機制
定期更新
有衡量的(de)指标(比如準确性,時(shí)效性)
明确你的(de)讀者是(shì)誰
寫文檔有一(yī / yì /yí)個(gè)很常見的(de)錯誤,那就(jiù)是(shì)很多人(rén)文檔都是(shì)寫給自己看的(de),這(zhè)種情況下就(jiù)會導緻你的(de)文檔隻有自己或者和(hé / huò)你有相似知識背景的(de)人(rén)才能看懂,團隊較小時(shí)這(zhè)種問題還好,你們都做着類似的(de)工作,所以(yǐ)也(yě)都能看懂文檔。但當團隊逐漸壯大(dà)後,問題就(jiù)會凸顯出(chū)來(lái),新人(rén)有時(shí)候有着和(hé / huò)你不(bù)同的(de)工作背景,甚至現在(zài)都做着不(bù)同的(de)工作内容,這(zhè)時(shí)候你之(zhī)前寫的(de)文檔他(tā)們就(jiù)很難讀懂了(le/liǎo)。
所以(yǐ)在(zài)寫文檔之(zhī)前請明确你文檔可能的(de)讀者會是(shì)哪些人(rén),然後針對他(tā)們的(de)特點着重關注如何才能讓他(tā)們理解。當然,文檔也(yě)不(bù)一(yī / yì /yí)定要(yào / yāo)非常嚴肅和(hé / huò)完美,隻要(yào / yāo)能向你潛在(zài)的(de)讀者說(shuō)明問題即可。 記住文檔是(shì)寫給别人(rén)看的(de),不(bù)是(shì)給自己看的(de)。
根據專業水平可以(yǐ)大(dà)緻将讀者分爲(wéi / wèi)三種 新手、老手和(hé / huò)專家,針對不(bù)同水平的(de)人(rén)寫作需要(yào / yāo)有側重點。比如針對新手,你需要(yào / yāo)重點介紹下裏面涉及到(dào)的(de)術語和(hé / huò)概念,然後詳細講解具體的(de)的(de)實現。相反,針對專家 你可以(yǐ)省去這(zhè)些額外的(de)信息。注意,這(zhè)裏沒有嚴格的(de)标準,因爲(wéi / wèi)有些文章新手會看,專家也(yě)會看, 這(zhè)裏還是(shì)需要(yào / yāo)具體情況具體分析。
另外一(yī / yì /yí)種對讀者分類的(de)方式就(jiù)是(shì)根據讀者閱讀文檔的(de)目的(de)來(lái)分類,比如有人(rén)知道(dào)自己遇到(dào)了(le/liǎo)什麽問題,就(jiù)是(shì)來(lái)找解決方案的(de)。還有一(yī / yì /yí)批人(rén)隻有一(yī / yì /yí)個(gè)簡單的(de)想法,但不(bù)知道(dào)具體的(de)問題。舉個(gè)例子(zǐ),以(yǐ)讀數據庫慢爲(wéi / wèi)例,前者已經知道(dào)數據庫慢可能是(shì)因爲(wéi / wèi)數據量巨大(dà)且沒有加索引,解決方案很簡單 加索引,這(zhè)時(shí)候他(tā)可能需要(yào / yāo)知道(dào)的(de)是(shì)如何正确地(dì / de)加索引。而(ér)後者可能着重關注的(de)是(shì)爲(wéi / wèi)什麽讀數據庫會慢,這(zhè)時(shí)候你可能需要(yào / yāo)額外重點介紹下數據庫相關的(de)原理。
清晰的(de)分類
文檔大(dà)緻可以(yǐ)分爲(wéi / wèi)以(yǐ)下幾種類型,每種類型也(yě)有自己不(bù)同的(de)特點和(hé / huò)寫作側重點。
參考文檔
參考文檔也(yě)是(shì)大(dà)部分開發人(rén)員日常會使用和(hé / huò)書寫的(de)文檔,比如我們使用某個(gè)框架或者工具,都會有API說(shuō)明文檔,這(zhè)就(jiù)屬于(yú)參考類文檔。 它并沒有太多的(de)要(yào / yāo)求,隻要(yào / yāo)能向讀者展示清楚如何使用即可,但無需向讀者講明具體的(de)實現。
注:參考文檔并不(bù)僅限于(yú)API文檔,還包括文件注釋、類注釋、方法注釋,要(yào / yāo)求都是(shì)能準确說(shuō)明其用法。
設計文檔
很多公司或者團隊在(zài)項目開始前都要(yào / yāo)求有設計文檔,設計是(shì)項目實施的(de)第一(yī / yì /yí)步,所以(yǐ)在(zài)設計文檔書寫的(de)過程中要(yào / yāo)求盡可能考慮周全,例如該項目的(de)存儲、交互、隐私……
好的(de)設計文檔應該包含以(yǐ)下幾個(gè)部分:
設計目标
實現的(de)策略
各種利弊權衡和(hé / huò)具體決策
替代方案
各種方案的(de)優缺點
寫設計文檔的(de)過程也(yě)你對整個(gè)項目做規劃、思考可能出(chū)現問題的(de)過程,設計的(de)越詳細、思考的(de)越多,未來(lái)遇到(dào)問題的(de)可能性就(jiù)會越小。
引導類文檔
引導類文檔也(yě)很常見,一(yī / yì /yí)般都是(shì)Step by Step的(de)形式。比如我們在(zài)使用某個(gè)框架或者工具的(de)時(shí)候,一(yī / yì /yí)般都會有個(gè)引導類的(de)文檔一(yī / yì /yí)步一(yī / yì /yí)步幫助你快速上(shàng)手。 大(dà)家寫引導類文章大(dà)家非常容易犯的(de)一(yī / yì /yí)個(gè)錯誤就(jiù)是(shì)預設了(le/liǎo)很多背景知識。 一(yī / yì /yí)般使用文檔都是(shì)有開發者寫的(de),他(tā)們都非常了(le/liǎo)解這(zhè)個(gè)工具的(de)相關的(de)知識,所以(yǐ)習慣性的(de)會認爲(wéi / wèi),啊 這(zhè)個(gè)知識點很簡單 用戶也(yě)肯定會吧,實際上(shàng)用戶不(bù)一(yī / yì /yí)定會。這(zhè)本質上(shàng)就(jiù)是(shì)一(yī / yì /yí)種認知偏差,這(zhè)種現象在(zài)跨團隊協作 尤其是(shì)多端協作的(de)時(shí)候也(yě)非常明顯。
這(zhè)類型的(de)文檔寫作中,要(yào / yāo)求寫作者盡可能站在(zài)用戶的(de)視角上(shàng)思考,極力避免出(chū)現和(hé / huò)用戶的(de)認知偏差,力争每個(gè)步驟做到(dào)明确無歧義,每兩個(gè)步驟之(zhī)間做到(dào)緊密銜接。
概念性文檔
當參考文檔無法解釋清楚某些東西的(de)時(shí)候,就(jiù)需要(yào / yāo)概念性文檔了(le/liǎo),比如某個(gè)API的(de)具體實現原理。其主要(yào / yāo)是(shì)爲(wéi / wèi)了(le/liǎo)擴充參考文檔,而(ér)不(bù)是(shì)替代參考文檔。有時(shí)候這(zhè)和(hé / huò)參考文檔會有些内容重複,但主要(yào / yāo)還是(shì)爲(wéi / wèi)了(le/liǎo)更深層次的(de)說(shuō)明某些問題、解釋清楚某個(gè)概念。
概念性文檔也(yě)是(shì)所有文檔中寫作最難的(de),也(yě)是(shì)被閱讀最少的(de),所以(yǐ)很多情況下工程師最容易忽視。而(ér)且還有另外一(yī / yì /yí)個(gè)問題,沒合适的(de)地(dì / de)方放,參考文檔可以(yǐ)寫代碼裏,落地(dì / de)頁可以(yǐ)寫項目主頁裏,概念性文檔似乎也(yě)隻能在(zài)項目文檔裏找個(gè)不(bù)起眼的(de)角落存放了(le/liǎo)。
這(zhè)類文檔的(de)受衆會比較廣,專家和(hé / huò)新手都會去看。另外,它需要(yào / yāo)強調概念清晰明了(le/liǎo),因此可能會犧牲完整性(可以(yǐ)由參考文檔補齊),也(yě)有可能會犧牲準确性,這(zhè)不(bù)是(shì)說(shuō)一(yī / yì /yí)定要(yào / yāo)犧牲準确性,隻是(shì)應當分清主次,不(bù)重要(yào / yāo)的(de)就(jiù)沒必要(yào / yāo)說(shuō)了(le/liǎo)。
Landing pages(落地(dì / de)頁)
Landing pages就(jiù)先簡單翻譯成落地(dì / de)頁了(le/liǎo),沒想到(dào)啥恰當的(de)翻譯詞。比如一(yī / yì /yí)個(gè)團隊或者項目的(de)導航頁,雖然沒啥具體的(de)内容,但應該包含其他(tā)頁面的(de)鏈接。 比如你新入職一(yī / yì /yí)個(gè)團隊,比較成熟的(de)團隊都會扔給你一(yī / yì /yí)個(gè)文檔,這(zhè)個(gè)文檔裏包含常用的(de)工具、文檔鏈接,這(zhè)就(jiù)是(shì)這(zhè)個(gè)團隊的(de)落地(dì / de)頁。 落地(dì / de)頁的(de)問題就(jiù)是(shì)随着時(shí)間的(de)推移,頁面可能會變的(de)越來(lái)越亂,而(ér)且有些内容會失效,不(bù)過這(zhè)些問題都好解決,做好定期的(de)維護和(hé / huò)整理就(jiù)行。 落地(dì / de)頁的(de)技術難度不(bù)高,但要(yào / yāo)求内容的(de)有效性、完整性和(hé / huò)分類清晰。
文檔Review
在(zài)一(yī / yì /yí)個(gè)組織内,光靠個(gè)人(rén)去維護文檔是(shì)不(bù)行的(de),必須得借助群體的(de)智慧。在(zài)一(yī / yì /yí)個(gè)組織内部,文檔的(de)變更也(yě)應該像代碼的(de)變更一(yī / yì /yí)樣,需要(yào / yāo)被其他(tā)人(rén)Review,以(yǐ)提前發現其中的(de)問題并提升文檔的(de)質量。
如何Review文檔:
專業的(de)視角來(lái)保證準确性: 一(yī / yì /yí)般由團隊裏比較資深的(de)人(rén)負責,他(tā)們關注的(de)核心點是(shì)文檔寫的(de)對不(bù)對,專不(bù)專業。如果Code Review做的(de)好的(de)話,文檔的(de)Review也(yě)屬于(yú)Code Review的(de)一(yī / yì /yí)部分。
讀者視角保證簡潔性: 一(yī / yì /yí)般由不(bù)熟悉這(zhè)個(gè)領域的(de)人(rén)來(lái)Review,比如團隊的(de)新人(rén),或者文檔的(de)使用者。這(zhè)部分主要(yào / yāo)是(shì)關注文檔是(shì)否容易被看懂。
寫作者視角保證一(yī / yì /yí)緻性: 由寫作經驗豐富或者相關領域比較資深的(de)人(rén)承擔,主要(yào / yāo)是(shì)爲(wéi / wèi)了(le/liǎo)保證文檔前後是(shì)否一(yī / yì /yí)緻,比如對同一(yī / yì /yí)個(gè)專業術語的(de)使用和(hé / huò)理解是(shì)否有歧義。
寫文檔的(de)哲學
上(shàng)面部分站在(zài)組織和(hé / huò)團隊的(de)視角來(lái)看如何提高文檔質量,我們接下來(lái)看看站在(zài)個(gè)人(rén)寫作者的(de)視角上(shàng)如何寫出(chū)高質量的(de)文檔。
5W法則
5W法則相信大(dà)家已經聽的(de)多了(le/liǎo),分别是(shì)Who What When Where Why,這(zhè)是(shì)一(yī / yì /yí)個(gè)廣泛被用在(zài)各行各業的(de)法則,寫文檔當然也(yě)能用(5W法則堪稱萬金油,啥地(dì / de)方都能用)。
WHO: 前面已經說(shuō)過了(le/liǎo),文檔是(shì)寫給誰看的(de),讀者是(shì)誰。
WHAT: 明确這(zhè)篇文檔的(de)用途,有時(shí)候,僅僅說(shuō)明文檔的(de)用途和(hé / huò)目的(de)就(jiù)能幫你搭建起整個(gè)文檔的(de)框架。
WHEN: 明确文檔的(de)創建、Review和(hé / huò)更新日期。因爲(wéi / wèi)文檔也(yě)有時(shí)效性,明确相關日期可以(yǐ)避免閱讀者踩坑。
WHERE: 文檔應該放在(zài)哪! 建議一(yī / yì /yí)個(gè)組織或者團隊有統一(yī / yì /yí)的(de)永久文檔存放地(dì / de)址,并且有版本控制。最好是(shì)方便查找、使用和(hé / huò)分享。
WHY: 爲(wéi / wèi)什麽要(yào / yāo)寫這(zhè)篇文檔, 你期望讀者讀完後從文檔中獲得什麽!
三段式寫作
寫文章一(yī / yì /yí)般都會有三個(gè)部分,專業寫作者也(yě)講究鳳頭、豬肚、豹尾,這(zhè)三個(gè)詞概括出(chū)了(le/liǎo)好文章三部分應有的(de)特點。技術文檔也(yě)算是(shì)文章的(de)一(yī / yì /yí)種,所以(yǐ)一(yī / yì /yí)般也(yě)都會有這(zhè)三部分,每個(gè)部分有其自己的(de)作用,比如第一(yī / yì /yí)部分闡述問題,中間部分介紹具體的(de)解決方案,第三部分總結要(yào / yāo)點。 但這(zhè)也(yě)并不(bù)以(yǐ)爲(wéi / wèi)着文檔應該有三個(gè)部分,如果文檔内容比較多,可以(yǐ)将其做更細緻的(de)拆解,可以(yǐ)适當增加一(yī / yì /yí)些冗餘的(de)信息幫助讀者理解文檔内容。雖然很多工程師都讨厭冗餘 極力追求簡潔,但寫文檔和(hé / huò)寫代碼不(bù)同,适當的(de)冗餘反而(ér)可以(yǐ)幫助讀者理解,很簡單,舉個(gè)例子(zǐ),比如寫作中經常舉例子(zǐ),舉的(de)例子(zǐ)本質上(shàng)就(jiù)是(shì)冗餘信息,生動的(de)例子(zǐ)肯定是(shì)能幫助讀者理解抽象内容的(de)(我想這(zhè)就(jiù)是(shì)自舉 吧)。
結語
目前看到(dào)比較好的(de)一(yī / yì /yí)個(gè)現象就(jiù)是(shì)大(dà)家越來(lái)越重視文檔了(le/liǎo),但和(hé / huò)測試相比 重視的(de)程度還不(bù)夠。測試已經是(shì)工作流程中不(bù)可或缺的(de)一(yī / yì /yí)部分了(le/liǎo),而(ér)文檔依舊還不(bù)是(shì)。當然這(zhè)可能和(hé / huò)文檔本身的(de)特性相關,測試很容易被自動化,也(yě)有非常多的(de)客觀指标來(lái)評估。文檔卻做不(bù)到(dào),首先文檔的(de)書寫需要(yào / yāo)人(rén)手動介入,而(ér)文檔的(de)質量也(yě)沒有太多客觀的(de)指标評估,提升文檔的(de)數量和(hé / huò)質量隻能從文化和(hé / huò)工作流程上(shàng)去逐漸改變。
最後總結下本文幾個(gè)關鍵點:
随着時(shí)間的(de)推移和(hé / huò)組織規模的(de)壯大(dà),文檔會越來(lái)越重要(yào / yāo)。
文檔也(yě)應該是(shì)開發流程的(de)一(yī / yì /yí)部分。
一(yī / yì /yí)篇文檔隻專注在(zài)一(yī / yì /yí)件事上(shàng)。
文檔是(shì)寫給讀者看的(de),而(ér)不(bù)是(shì)給你自己看的(de)。