作為一名軟件工程師,我花了很多時間在閱讀和撰寫設計文檔上。在磨礪了數百篇文檔之后,我發現,優秀的設計文檔與項目的成功之間有著密切的聯系。
這篇文章將介紹怎樣才能寫出一份優秀的設計文檔。
為什么要寫設計文檔?
設計文檔也就是技術規范,用于描述你打算如何解決問題。已經有很多文章說明了為什么在開始編碼之前要先寫設計文檔,這里不再贅述,不過我想再補充一句:
設計文檔是確保正確完成工作最有用的工具。
設計文檔的主要目的是迫使你對軟件設計展開縝密的思考,并收集他人的反饋,以便更好地完成你的工作。人們通常認為,設計文檔的目的是讓其他人了解某個系統,或者作為參考文檔。這些只是設計文檔帶來的有益的副作用,但絕不是它們的根本目的。
從經驗來看,如果你的項目需要一個人月或更長時間,那么就應該編寫設計文檔。另外,一些小型項目也可以從迷你設計文檔中獲益。
但不同的工程團隊,甚至是同一團隊中的工程師,他們編寫設計文檔的方式存在很大差異。接下來,讓我們來談談優秀設計文檔的內容、風格和流程應該是怎樣的。
設計文檔應該包含哪些內容?
設計文檔描述了問題的解決方案。因為每個問題的性質不一樣,所以設計文檔的結構也不一樣。
下面列出了一個清單,你至少可以考慮在文檔中包含這些內容。
標題和人物
設計文檔的標題、作者(應該與計劃參與項目的人員名單相同)、文檔的評審人員(我們將在“流程”部分詳細討論),以及文檔的最后更新日期。
摘要
摘要可以幫助公司的每位工程師理解文檔的內容,并決定是否需要繼續閱讀文檔的剩余部分。摘要最多可以包含 3 段內容。
背景
描述要解決什么問題、為什么需要這個項目、人們需要哪些知識才可以評估這個項目,以及它與技術戰略、產品戰略或團隊的季度目標之間的關系。
目標和非目標
目標部分應該包括:
-
描述項目對用戶的影響——你的用戶可能是另一個工程團隊或另一個系統。
-
指定如何使用指標來度量項目的成功——如果可以鏈接到指標儀表盤那就更好了。
非目標也同樣重要,用于描述項目不會解決哪些問題,讓每個人都達成共識。
里程碑
一系列可衡量的檢查點,你的 PM 和上司可以借助它們大致了解項目的每個部分將在什么時間完成。如果項目時間超過 1 個月,我建議你將項目分解為面向用戶的里程碑。
在設定里程碑時可以使用日歷日期,把延期、假期、會議等因素都考慮進去。例如:
開始日期:2018 年 6 月 7 日
里程碑 1——以暗模式運行新系統 MVP:2018 年 6 月 28 日
里程碑 2——棄用舊系統:2018 年 7 月 4 日
結束日期:在新系統中添加新特性 X、Y、Z:2018 年 7 月 14 日
如果其中一些里程碑的 ETA 發生變化,需要在此處添加 [更新],相關人員可以很容易看到更新的內容。
當前的方案
除了描述當前的實現之外,還應該通過示例來說明用戶如何與系統發生交互以及數據是如何流經系統的。
這個時候可以使用用戶故事。請記住,你的系統可能擁有不同類型的用戶,他們的使用場景也不盡相同。
提議的方案
有人把這部分稱為技術架構。這部分也可以通過用戶故事來進行具體化,可以包含多個子部分和圖表。
先從大處著手,然后填充細節。你要做到即使你在某個荒島上度假,團隊的其他工程師也能按照你的描述來實現解決方案。
其他替代方案
在提出上述解決方案的同時,你還考慮了其他的方案了嗎?替代方案的優點和缺點是什么?你是否考慮使用第三方解決方案——或使用開源解決方案——來解決問題,而不是自己構建解決方案?
監控和警報
人們經常把這部分視為馬后炮,甚至直接忽略掉。而在發生問題后,他們就手忙腳亂,卻不知道該怎么辦,也不知道為什么會發生這些問題。
跨團隊影響
-
這樣會增加輪班待命和 DevOps 的負擔嗎?
-
它的成本是多少?
-
它會增加系統延遲嗎?
-
它會暴露系統安全漏洞嗎?
-
它會帶來哪些負面后果和副作用?
-
支持團隊該如何與客戶溝通?
討論
這部分可以包含任何你不確定的問題、你想讓閱讀文檔的人一起權衡的有爭議的決定、對未來工作的建議,等等。
詳細的范圍和時間表
這一部分的主要閱讀對象是參與該項目的工程師、技術主管和經理。因此,這部分放在文檔的最后。
從本質上講,這是項目計劃的實施方式和時間細分,可以包含很多內容。
我傾向于將這一部分視為項目任務跟蹤器,因此每當范圍估計發生變化時,我都會更新它。但這更像是個人偏好。
怎樣才能寫好文檔
在講完優秀的設計文檔應該包含哪些內容之后,現在讓我們來談談寫作風格。
盡可能保持簡單
不要把設計文檔寫成你曾經讀過的學術論文。論文是為了給期刊評論家留下深刻印象,而編寫設計文檔是為了描述你的解決方案,并從其他人那里獲得反饋。你可以通過以下方式讓文檔變得更清晰:
-
用詞簡單
-
使用短句
-
使用符號列表和編號列表
-
提供具體的示例
添加圖表
圖表便于對幾種選項進行比較,而且通常比文本更容易理解。我經常用 Google Drawing 來創建圖表。
請記得在截圖下方添加一個指向圖表源文件的鏈接,以便在發生變更時可以更新圖表。
包含數字
問題的規模通常決定了解決方案的規模。為了更好地幫助評審人員了解情況,請在文檔中使用實際的數字,例如數據庫行數、用戶錯誤數、延遲,以及這些數據與使用量之間的關系。(還記得大 O 表示法嗎?)
加入趣味性
記住,技術規范不是學術論文。另外,人們喜歡閱讀有趣的東西,但也不要為了趣味性而偏離了核心思想。
自審
在將設計文檔發給其他人評審之前,自己先假裝是評審人員。你對這份設計文檔有什么疑問?然后在發出文檔之前把這些問題解決掉。
假期測試
如果你在獨家,無法訪問網絡,那么團隊中的其他人是否可以讀懂這份文檔,并按照你的意圖實現文檔中的內容?
設計文檔的主要目的不是為了知識共享,但這是一種評估清晰度的好辦法,讓其他人可以為你提供有用的反饋。
流程
設計文檔可以幫你在浪費大量時間實現錯誤的解決方案或解決錯誤的問題之前獲得反饋。獲得良好反饋是一門藝術,但那是后話了。現在,讓我們來討論下如何為設計文檔獲取反饋。
首先,參與項目的每個人都應該參與軟件設計過程。即使有很多決定是由技術主管做出的,那也沒關系,至少每個人都應該參與討論,并接收他們的設計。
其次,設計的過程并不一定是盯著白板,在上面畫出各種想法。你可以動起手來,建立各種可能的解決方案原型。這與在寫好設計文檔之前就開始寫代碼是不一樣的。你完全可以隨意寫一些一次性的代碼來驗證你的想法。為了確保你的代碼只是用于概念驗證,原型代碼都不能合并到 master 上。
在你了解了如何進行項目之后,請執行以下步驟:
-
請你團隊中經驗豐富的工程師或技術負責人來評審你的文檔。理想情況下,評審人員應該是一個受到尊重并且對問題邊緣情況已經很熟悉的人。
-
在有白板的會議室里進行評審。
-
向評審人員描述你正在解決的問題(這是非常重要的一步,不要跳過它!)。
-
然后向評審人員解釋你想要怎樣實現你的想法,并說服他們這是正確的解決方案。
在開始正式編寫設計文檔之前完成所有這些步驟,可以讓你在投入更多時間并敲定解決方案之前盡快獲得反饋。通常情況下,即使實現方式可以保持不變,評審人員仍然會指出一些需要你覆蓋到的極端情況,或者指潛在的不明確的地方,并預測你以后可能會遇到的困難。
然后,在你為設計文檔寫了粗稿之后,讓之前的評審人員再次閱讀它,并在設計文檔的“標題和人物”部分寫下他們的名字,作為對評審人員的鼓勵,也表示他們是有責任對自己的評審行為負責的。
在添加評審人員名字時,可以考慮為特定的問題添加不同的評審人員(例如 SRE 和安全工程師)。
在完成評審之后,請將設計文檔發給你的團隊,以便獲得額外的反饋。我建議把這個時間限制在 1 周左右,以避免延期。盡量在一周內解決他們留下的問題。
最后,如果你和評審人員及其他閱讀該文檔的工程師之間存在爭議,我強烈建議你將這些爭議放在文檔的“討論”部分。然后,與各方召開會議討論這些分歧。
如果一個主題超過了 5 條評論,那么進行面對面討論往往會更有效率。請記住,即使無法讓每個人都達成共識,你仍然可以拍板。
在最近與同事談論此事時,我了解到團隊組有一個類似的過程,只是除了讓團隊中經驗豐富的工程師或技術負責人來充當評審人員之外,他們還建議讓不同團隊的工程師評審設計文檔。我沒有嘗試過這個,但可以肯定的是,這樣有助于從擁有不同視角的人那里獲得反饋,從而進一步提高文檔的質量。
在完成上述所有步驟之后,接下來就可以開始實現了!在實現設計的過程中,可以將設計文檔視為活動的文檔。在對實現方案做出調整時,也一并更新文檔,這樣你就不需要向所有利益相關者反復解釋這些變化。
那么,我們如何評估一份設計文檔成功與否?
我的同事對這個問題的回答是:如果能夠獲得正確的投資回報率(ROI),那么設計文檔就是成功的。也就是說,一份成功的設計文檔可能會導致:
-
你花了 5 天時間編寫設計文檔,迫使你對技術架構的不同部分進行了充分的思考。
-
你從評審人員那里獲得反饋,知道架構中某些部分具有較高的風險。
-
你決定先解決這些問題,以便降低項目的風險。
-
3 天后,你發現這些問題要么不可能發生,要么比你原先想象的要困難得多。
-
你決定停止這個項目去做其他工作。
在本文開頭,我們說設計文檔的目的是確保正確地完成工作。在上述的示例中,因為有了軟件設計文檔,你只花了 8 天時間而不是浪費了幾個月才決定要中止項目。在我看來,這似乎也是一個非常成功的結果。