Google 如何寫設計文檔

來源:技術瑣話
作者:Malte
時間:2023-01-29
1550
Google 軟件工程文化中關鍵元素之一,是使用設計文檔來定義軟件設計。這些文檔通常不是非常正式,主要是軟件系統(tǒng)或應用程序的作者在著手寫代碼之前編寫的。這些設計文檔記錄了 high-level 的實現(xiàn)策略和關鍵的設計決策,而后者重點描述了決策過程中思考的權衡。

作為軟件工程師,我們的工作并不是生產(chǎn)代碼本身,而是解決問題。非結構化的文本,例如以設計文檔的形式,在項目早期或許是解決問題更適宜的工具。因為設計文檔可能更簡明、更容易被理解,相比代碼能在更高的層面溝通問題及解決方案。

除了用作軟件設計的原始文檔記錄,設計文檔還在軟件研發(fā)生命周期中實現(xiàn)了下述功能:

在修改成本還比較低的時候,盡早地識別設計缺陷。

在組織中圍繞設計達成共識。

確保橫切關注點(Cross-cutting concern)得到充分考慮。

在組織中傳播資深工程師的知識。

就設計決策形成組織記憶基礎。

成為軟件設計者技術資產(chǎn)中的一個摘要性制品。

1. 設計文檔的構成

設計文檔是非正式的文檔,因此其內(nèi)容不需要遵循嚴格的準則。因此首要原則就是:在特定的項目中,用任何最合理的形式編寫。

在此原則之外,Google 也建立了一種頗有效果的設計文檔結構。

1.1 上下文和范圍(Context and scope)

這一小節(jié)給讀者展現(xiàn)一個有關這個系統(tǒng)在哪里被構建,以及什么會被構建的非常粗的概覽。這不是需求文檔。保持言簡意賅!這里的目標是讓讀者快速進入狀態(tài),可以假設讀者知道一些前置的知識,相關詳情可以給到鏈接。這一節(jié)內(nèi)容應該完全關注在客觀的背景事實。

1.2 目標和非目標(Goals and non-goals)

給出一個簡單的列表,講述系統(tǒng)的目標是什么。有時候更重要的是講述非目標是什么。注意,非目標不是對目標的否定,例如“系統(tǒng)不應該 crash”,而是顯示地挑選出來的不是目標的內(nèi)容。一個好的例子是 “遵循 ACID”,當設計一個數(shù)據(jù)庫的時候,你必然想要知道這是目標還是非目標。進一步的,你仍然可以選擇一個方案來實現(xiàn)非目標,只要它不會給實現(xiàn)目標帶來不必要的權衡。

1.3 實際設計(The actual design)

這一部分應該以一個概述開頭,然后逐漸展開細節(jié)。

  設計是文檔是在你設計軟件的過程中,記錄設計取舍的地方。應該關注這些取舍,以產(chǎn)出一個具備長期價值的文檔。具體就是,在既定的上下文(事實),目標和非目標(需求)下,設計文檔應該提出解決方案,并闡明為什么某個特定的解決方案是滿足這些目標的最佳方案。

相較于更為正式媒體形式,編寫文檔的意義在于可以用合適的方式靈活地表述手頭的問題集合。因此,如何描述設計并沒有顯式的指引。

話雖如此,對于大多數(shù)設計文檔來說,一些最佳實踐和重復出現(xiàn)的主題還是有意義的:

1.3.1 系統(tǒng)上下文圖(System-context-diagram)

對于很多文檔來說,系統(tǒng)上下文圖是很有用的。這類圖展示了當前系統(tǒng)是更大技術圖景的一部分,能讓讀者在一個他們已經(jīng)熟悉的上下文環(huán)境中去理解新的設計。

系統(tǒng)上下文圖的例子

1.3.2 APIs

如果設計的系統(tǒng)會暴露 API,那么草擬出 API 通常是好想法。不過,在大多數(shù)情況,我們應該克制住把正式接口和數(shù)據(jù)定義復制粘貼到文檔中的沖動,因為這么做會導致文檔過于冗長,包含不必要的細節(jié),并很快過期。相對應的,我們應當關注和設計及取舍相關的那部分 API。

1.3.3 數(shù)據(jù)存儲(Data storage)

需要存儲系統(tǒng)的系統(tǒng)應該討論數(shù)據(jù)是如何以何種形式,如何被存儲的。和前面描述 API 的建議一樣,基于相同的理由,應該避免復制粘貼完整的 schema 定義,正確的做法是關注在那些和設計取舍相關的部分。

1.3.4 代碼和偽代碼(Code and pseudo-code)

設計文檔應當很少包含代碼或偽裝代碼,除非有一些情況需要描述新的算法。合理的做法是給到設計原型實現(xiàn)的鏈接。

1.3.5 約束條件(Degree of constraint)

軟件設計形態(tài)(因此設計文檔)的主要影響因素是解決方案空間(solution space)中的約束條件。

一個方向的極端情況是 “綠地軟件項目(greenfield)”,在這種情況下我們知道所有的目標,解決方案只要是合理的,沒什么限制。這樣的文檔可能就會顯得很寬泛,但是也應該快速定義一組規(guī)則,以便讓大家盡快把目光收斂到一組可控的解決方案中。

另一個方向的極端情況是,所有可能的解決方案都被定義得很清楚了,但是如何把它們結合起來以達成目標,卻毫不清晰。這往往是因為遺留系統(tǒng)難以改動,或者遺留系統(tǒng)不是被設計用來解決當前所面臨的問題的,又或者是一個類庫的設計要求我們在它的宿主編程語言限制下工作。

在這種情況下,你或許可以遍歷所有可行的簡單方法,但更需要創(chuàng)新地把所有這些方法整合起來以完成目標。也許存在多種方案,每一種方案都不是特別出色的,因此文檔應該關注在如何從已經(jīng)識別的各項取舍中,選擇最合適的方案。

1.4 候選設計(Alternatives considered)

這一小節(jié)列出那些同樣可以實現(xiàn)類似產(chǎn)出的可選設計。這里關注的應該是各種方案各自的取舍,以及這些取舍的對比如何引向最終的設計 —— 文檔的核心主題。

雖然描述候選設計可以簡潔一些,但是這一小節(jié)實際上非常核心的,因為這里非常清晰地展示了,在給定的項目目標和所有可選方案下,為什么選擇了最終方案,在給定目標下權衡的判斷是如何做出的,而這正是文檔的讀者所關注的核心。

1.5 橫切關注點(Cross-cutting Concerns)

在這里組織可以確保一些橫切關注點如安全,隱私,可觀測性,總是被考慮到。這部分內(nèi)容通常相對較短,只是用來解釋設計會如何影響到橫切關注點,以及相關影響如何得到解決。團隊應該標準化在他們場景下的關注點。

例如,由于隱私非常重要,Google 的項目就必須寫一個專門的隱私設計文檔,這個文檔會別專門用來 Review 隱私和安全。雖然 Review 只要在項目啟動前完成,但通常最好是盡早讓隱私和安全團隊介入,確保設計從一開始就重視他們的意見。關于這部分內(nèi)容更專門的細節(jié),核心文檔不一定要全部包含,有時候給到這些專門文檔的引用即可。

1.6 設計文檔的長度(The length of a design doc)

設計文檔應該具備充分的細節(jié),但同時足夠簡短以能夠被忙碌的人閱讀。對于一個大型項目來說,最佳的長度似乎是 10 到 20 頁。如果你的內(nèi)容超過這個大小,更合理的做法可能是把這個問題劃分成更易管理的子問題。當然,需要注意的是,編寫 1-3 頁的“迷你設計文檔”完全是可能的。這類文檔對于敏捷項目中的增量改進或者子任務尤其有用 —— 但你仍然需要和編寫長文檔一樣執(zhí)行一樣的步驟,區(qū)別只是讓內(nèi)容更精煉,并且只關注有限的問題集合。

2. 什么時候不要編寫設計文檔(When not to write a design doc)

編寫設計文檔是需要成本的。關于是否編寫設計文檔的決定,實際上是在做權衡。權衡的一邊是圍繞設計、文檔、高層評審等工作形成組織共識的益處,權衡的另一邊是這塊工作投入的精力成本。決策的核心在于設計問題的解決方案是否模糊 —— 這往往是因為問題復雜度,或者解決方案的復雜度引起的(或者兩者皆有)。如果不存在這個問題,那么走一個設計文檔編寫的流程價值就有限。

設計文檔可能沒有必要的一個明顯征兆是:設計文檔實際上是實現(xiàn)手冊。如果文檔基本上說的是“這是我們將如何實現(xiàn)之”,而沒有深入討論取舍、可選方案、沒有解釋決策(或者說解決方案太明顯了以致于沒什么取舍可討論),那么很有可能直接編寫真實代碼是更好的選擇。

最后,創(chuàng)建和評審設計文檔的投入可能與快速制作原型并迭代理念并不相容。但是大多數(shù)軟件項目都是有一組實際上已知的問題。擁抱敏捷方法不應該成為不花時間去尋找已知問題正確解決方案的借口。此外,原型本身可能就是創(chuàng)建設計文檔過程的一部分。“我試過了,這么做可行” 就是選擇一種設計最好的論據(jù)之一。

3. 設計文檔的生命周期(The design doc lifecycle)

一份設計文檔的生命周期包括如下階段:

1.創(chuàng)建和快速迭代

2.審查(可能有多輪)

3.實現(xiàn)和迭代

4.維護和學習

3.1 創(chuàng)建和快速迭代(Creation and rapic iteration)

你編寫文檔,有時候是和幾個合作者一起編寫。

這一階段快速演進成為快速迭代的時期,文檔被分享給一些同事,他們擁有關于問題空間(problem space)的最多的知識(通常屬于同一個團隊),通過他們不斷澄清問題并提出建議,文檔逐漸形成第一個相對穩(wěn)定的版本。

你會發(fā)現(xiàn)很多工程師和團隊更偏向于使用版本控制和代碼審查工具來管理文檔,但是 Google 的大多數(shù)文檔是使用 Google Docs 創(chuàng)建的,并重度使用了協(xié)作特性。

3.2 評審Review)

在評審階段,設計文檔被分享給原始作者和緊密協(xié)作者之外更廣范的一批受眾。評審可以給文檔增加很多價值,但是也有可能是危險的投入成本陷阱,因此要明智對待。

評審可以有很多形式:最輕量的版本就是簡單把文檔發(fā)給更大范圍的團隊,讓大伙有機會可以看一眼。隨著而來的討論主要就發(fā)生在文檔的評論區(qū)。而形式較重的評審,就是發(fā)起正式的設計文檔評審會議,在會議中作者面向通常是較為資深的工程師聽眾演示文檔(通常是專門的演示)。Google 有很多團隊為此目的排了周期性的會議,工程師可以注冊用來發(fā)起設計評審。自然的,等待此類會議來評審設計文檔會大幅降低研發(fā)速度。工程師可以通過直接向同事獲取最關鍵的反饋,同時也不阻塞更廣泛的評審,進而降低這一風險。

Google 是一個小一些的公司的時候,大家習慣上會把設計發(fā)到一個中心的郵件列表中,在這里資深的工程師會抽空進行評審。這種方式對公司來說可能就不錯。這種方式一大好處是,它在整個公司層面建立了一種相對一致的軟件設計文化。但是隨著公司逐漸增長細形成一個較大的工程師團隊,維護這種中心化的方法就不可行了。

設計評審增加的主要價值是,它形成了一個讓組織的綜合經(jīng)驗可以融合到設計中的機會。如何讓設計能夠充分考慮橫切關注點如可觀測性、安全性、以及隱私,這一點就能夠非常一致地在評審階段得到保障。評審的主要價值不是問題被發(fā)現(xiàn)本身,而是讓問題在軟件研發(fā)階段相對早期的時候,也就是修復成本相對較低的時候被發(fā)現(xiàn)。

3.3 實現(xiàn)和迭代(Implementation and iteration)

當事情獲得了充分的進展,看起來進一步的評審不太會要求設計做重大的改變,那就是時候開始實現(xiàn)了。當計劃和現(xiàn)實沖突,不可避免的會發(fā)現(xiàn)設計的缺陷,未被充分考慮的需求,或者基于經(jīng)驗的推測實際上錯誤的,進而發(fā)現(xiàn)需要對設計做修改。在這種情況下強烈推薦更新設計文檔,一般說來:如果系統(tǒng)還沒有上線,那么很確定應該更新文檔。在實踐中,我們普通人在更新文檔方面都做得不好,以及因為一些其他的實際因素,更新還通常會落到新的獨立的文檔中去。這就導致了一種近似美國憲法的最終態(tài):有一堆修正案,而非一份一致的文檔。對于將來維護系統(tǒng)的可憐程序員來說,當他們像考古學家一樣翻閱歷史設計文檔,去試圖理解目標系統(tǒng)的時候,原始文檔中給出這些“修正案”的鏈接會非常有幫助。

3.4 維護和學習(Maintenance and learning)

Google 工程師首次接觸一個系統(tǒng)的時候,他們的第一個問題通常是“設計文檔在哪里? 。雖然說設計文檔和所有其他文檔一樣,都會隨著時間的流逝變得和現(xiàn)實不一致,但它們依舊是學習系統(tǒng)在創(chuàng)建之初其背后思考的最佳起步材料。

作為作者,從為自己著想的角度考慮,可以在一兩年后重新閱讀自己的設計文檔。你哪里做對了?哪里做錯了?在今天來看你會做哪些不同的決策?對于工程師來說,回答這些問題是一種絕佳的提升軟件設計能力和自我進步的方式。

4. 結論(Conclusions)

在軟件項目中,圍繞解決最難的問題,設計文檔是一種獲得清晰度以并達成共識的絕佳方法。設計文檔可以節(jié)省金錢,因為在前期足夠的調(diào)研可以幫助避免過早就進入編碼細節(jié)卻未能完成項目目標;設計文檔又花費金錢,因為編寫和審查文檔消耗時間。因此,在你項目中明智地做出選擇。

在考慮是否編寫設計文檔的時候,思考如下問題:

你是否對正確軟件設計不確信?在前期消耗時間來獲取確定性是否合理?

在設計階段引入相關的資深工程師是否有幫助?他們可能沒有時間審查所有代碼。

軟件設計是否是模糊的,甚至是有爭議的?因此圍繞這一問題在組織層面達成共識會很有價值?

我團隊是否有時候會在設計中忘記考慮隱私、安全、日志或者其他橫切關注點?

在組織中是否非常需要遺留系統(tǒng)設計的文檔?這樣可以讓大家在 high-level 快速了解系統(tǒng)。

如果對于上述的問題你有三個或更多“是”的回答,那么在你開始下一個軟件項目的時候,設計文檔大概率是個不錯的方法。


原文鏈接:點擊前往 >
版權說明:本文內(nèi)容來自于技術瑣話,本站不擁有所有權,不承擔相關法律責任。文章內(nèi)容系作者個人觀點,不代表快出海對觀點贊同或支持。如有侵權,請聯(lián)系管理員(zzx@kchuhai.com)刪除!
個人VIP
小程序
快出海小程序
公眾號
快出海公眾號
商務合作
商務合作
投稿采訪
投稿采訪
出海管家
出海管家