tft每日頭條

 > 科技

 > 軟件工程詳細設計文檔

軟件工程詳細設計文檔

科技 更新时间:2025-02-25 20:23:30
1、設計文檔是什麼?

設計文檔是軟件工程設計中的重要組成部分,是對一個技術問題的解決方案的系統性描述。設計文檔的目的,是闡明設計的總體思想和設計中考慮的權衡點。

作為一名軟件工程師,我們的工作本質不僅僅是編寫程序代碼,而是解決真正的問題。因此,相比最終的程序代碼,文字形式的設計文檔,在早期能夠更加簡明扼要地傳達信息,便于讓讀者理解問題,找到解決方案。

除了作為系統設計的最初體現,設計文檔在軟件工程的開發周期中起到下面重要作用:

通過設計文檔,我們可以:

  • 在可以低成本叠代的時候,盡早發現設計中的問題 - 設計左移,代價左移,快速失敗(fail fast)
  • 在團隊中對設計達成一緻 - 設計的本質是取舍(tradeoff)。幾乎所有的架構設計決策都會被挑戰,原因之一是:讀者并非對所有的取舍都知曉,且與作者達成共識。在設計文檔中清晰地列出取舍,有利于幫助讀者了解(并認可)你的決策思路,減少被挑戰的可能。
  • 将資深工程師的經驗和思想擴展到整個團隊,幫助團隊成長 - 作為作者,可以供資淺工程師學習 - 作為讀者,可以審核資淺工程師的設計并提供建議
  • 形成團隊軟件設計的一緻方式,沉澱團隊/公司技術積累 - 企業的生命力在于知識價值的積累
2、什麼時候需要設計文檔?

本身撰寫設計文檔是需要編寫成本的。如果問題的解決方案非常清晰,沒有明确的取舍,設計文檔中基本都是實現描述,則應該省略設計文檔而直接實現。換言之,如果編寫設計文檔的時間主要消耗在“寫”而不是在“思考”上,則這個設計文檔可省略。當你考慮編寫一個設計文檔時,想一想以下這幾點:

  • 軟件的規模是否較大,值得付出額外的編寫評審設計文檔的時間來降低失敗的風險?
  • 高級工程師無法确保 CR 每一份代碼,讓他們參與設計評審是否回報更高?
  • 軟件設計決策是模糊的,甚至有争議。有必要圍繞設計文檔在組織上達成共識?
  • 是否需要通過設計文檔強調項目交叉問題,如隐私性(Privacy)、安全性(Security)、日志記錄?
  • 是否有必要寫一份文檔來對有關遺留系統的設計問題提供高層次的分析?

如果以上的問題的答案為“是”,那麼設計文檔可能是開始你的下一個軟件項目的絕佳方法。

3、設計文檔要怎麼寫?

在考慮通過用設計文檔解決問題,開始着手準備設計文檔前,需要厘清設計文檔易混淆的三個概念,它們也是創作設計文檔的根基。一旦出現偏差,我們認真撰寫的文檔很有可能完全不可用,在糾正偏差時也會出現大量工作返工,造成資源的浪費。所以,撰寫設計文檔前需要搞清楚這些前提。

3.1 撰寫設計文檔的三個前提

在搞清楚設計文檔撰寫的三個前提後,就會進入文檔的編寫階段。設計文檔是非正式的文檔,因此他們的内容不會遵循嚴格的準則,一個首要原則是,針對項目的具體情況可以用相對合理的方式來編寫。盡管如此,筆者也參考文獻并結合自身經驗給出一些建議。

寫作風格的三要素

設計文檔的寫作也是技術寫作(Technical Writing),因此同樣強調以下三要素:

  • 清晰
  • 簡潔
  • 優雅
設計文檔的五個要點

系統設計及編寫設計文檔時需要注意的 5 個要點。

1. 任何架構問題都是取舍。

在軟件設計中,沒有任何一個維度有絕對意義上的優劣。每一個設計決定都需要考量很多相違背的因素。例如,可擴展性和效率相背;長期效率和短期收益相背;規模化提升了效率,但降低了靈活性。“高内聚低耦合” 便于叠代,但是會增加短期的開發成本。NoSQL 比 SQL 性能高,但代價是功能的大幅降低。如果一個設計決策看上去沒有任何的取舍,往往是因為取舍還沒有被識别。在設計時應從取舍視角切入,尋找不同需求間的平衡。

2. “為什麼” 比 “怎麼做” 更重要。

設計所解決的問題往往是複雜而模糊的,因此,解決方案往往是不唯一的。對工程設計,方案的論證通常比方案本身更重要。

3. 考慮時間維度

做設計取舍時不能忽略時間維度,隻設計某個階段的終态。設計需要考慮以下方面:

  • 可維護性與可擴展性
  • 考慮實現路徑
  • 考慮未來計劃
4. 避免過度設計

設計伊始,界定問題的範圍。

一個良好界定的問題是一個良好設計的必要條件。不要迷信設計模型、設計模式、XX 驅動設計。這些是工具,而非法則。不要為了制造問題而解決問題。不要通過複雜的設計來體現工作的難度和深度: 一個困難的問題可能會有一個簡單的答案。也不要過于擔憂設計被迅速淘汰。保留可擴展性,但不要在未知時浪費精力擴展。

【文章福利】另外小編還整理了一些C/C 後台開發教學視頻,相關面試題,後台學習路線圖免費分享,需要的可以自行添加:點擊 正在跳轉 加入~群文件共享

小編強力推薦C 後台開發免費學習地址:C/C Linux服務器開發/後台架構師【零聲教育】-學習視頻教程-騰訊課堂

軟件工程詳細設計文檔(如何寫一份高可讀性的軟件工程設計文檔)1

5. 總結

最重要的是要知道如何設計,知道自己在設計什麼。列甯·克魯格效應告訴我們,這未必顯然。

I think test-driven design is GREat. I do that a lot more than I used to do. But you can test all you want and if you don’t know how to approach the problem, you’re not going to get a solution. ——Coders at Work, Peter Norvig

3.2 設計文檔的核心原則前提一:設計文檔的讀寫比最高

實現代碼、系統接口、設計文檔,讀寫比(内容被所有人閱讀花費的時間:内容寫作花費的時間)是逐步上升的。通常,設計文檔供閱讀讀的時間往往遠多于寫的時間。因此,編寫設計文檔時就更多考慮讀者的體驗而非作者的體驗。為提升設計可讀性的時間非常值得投資。

前提二:設計文檔不是文學寫作

設計文檔的目的是為了溝通設計,而不是為了自我表達。把精力放在如何清晰、簡潔地表達,而非放在文采上

前提三:設計文檔為誰而寫

首先先了解你的讀者是誰?在良好的文檔分享文化下,讀者不應該隻是你的 TL 以及該設計文檔的實施者,你的設計文檔實際讀者的範圍往往大得多。在不确定的時候,經驗做法是,假設的讀者群體為:公司内部的、有一定工程經驗的、但對該系統的上下文隻有初步了解的軟件工程師。通常,設計文檔的範圍越大,假定的受衆群也會更大。這意味着受衆對目标系統的平均了解程度更低,也就意味着設計文檔往往需要:

  • 更加詳細的背景介紹
  • 更少使用内部術語或縮寫
  • 更多闡述設計思路、取舍,更少解釋具體實現細節

其次,考慮讀者喜歡如何閱讀?大部分讀者不會逐字逐句閱讀你的設計文檔。大家都很忙。讀者通常隻會掃描大體結構,然後閱讀(或者跳讀)自己感興趣的部分。讀者喜歡“故事”。将内容以故事的結構呈現最容易被接受,即使我們并不是需要講述一個傳統的打怪升級的故事。雖然故事内容各有不同,但大部分故事都遵循一些基本的範式。例如,約瑟夫·坎伯 總結提出全世界大部分神話故事都符合“ 英雄之旅 ”-- “啟程、啟蒙、歸程”三幕 -- 這個模式。

對于設計文檔/科技論文寫作,通用安全的選擇是 Writing Science 所介紹的 OCAR 故事結構。

  • Opening:開場,背景介紹
  • Challenge:挑戰,所要解決的問題
  • Action:行動,執行的實驗/設計/...
  • Resolution:結果

設計文檔通常遵循特定的組織結構,我們可以将每一個結構對應到 OCAR 的不同部分,以此講述故事。

最後,辯證看待設計文檔可讀性。設計文檔可讀性 vs. 代碼可讀性都稱作可讀性,兩者有些共通之處:

  • 文檔着重強調的内容應該是并非顯而易見的事項:

設計文檔

代碼文檔

說明背景

說明上下文

強調 Why/權衡/其它方案

強調 Why

注意事項

注意事項

代碼可以清晰表達的内容不需要文檔

代碼可以清晰表達的内容不需要文檔

  • 沒有絕對的正确答案:沒有完美的代碼,也沒有完美的設計文檔。- 不同的讀者對可讀性的理解有細微的不同。可讀性是主觀的。- 在實踐中,我們追求讓更多(而非所有)讀者更順暢地閱讀設計文檔。- 不要為完美主義付出過重代碼。平衡可讀性與時間成本。
  • 我們的目标是有意識地提高文檔寫作/代碼水平。高質量的寫作是一種習慣。提高水平的方法有:- 多讀他人優秀的設計文檔。- 評審(Design doc review/Code review)有益。- 設計文檔評審往往主要關注系統設計合理性,但是可讀性方面的評審也有必要。
  • 多寫作、多修改、多重寫。
3.3 設計文檔的最佳實踐遣詞

用詞要簡練、準确、直白。

  • 正确使用專業術語。- 合理地使用常見術語可以降低溝通成本。- 不要過多使用過于小衆或自創的術語。如果有必要,需要在文中 - 必要時提供對照的英文術語以方便理解。- 避免無上下文的縮略詞。
  • 省略程度副詞
  • 不管作者意圖為何, “非常重要” 和 “重要” 在讀者看來大同小異。
  • 使用數據 - 與其說明“該系統的性能提升明顯”,不如“該系統的性能提升了 42%”更為可信,也更方便讀者做出自己的判斷。
  • 忌佶屈聱牙
  • 例如上文,應改為“不要使用過于生僻的詞彙,不要過度使用書面語”
  • 千萬不要寫文言文
造句
  • 使用短句,不要使用多從句的複雜句式。- 讀者不是來考 GRE 的。- 寫文檔也不是為了炫耀自己可以駕馭長難句。

“_系統形式問題就是下面這樣一個問題:怎樣把各種不同的對象種類安排在一個系統中,以使較高的對象種類總能從較低的對象種類構造出來,也就是說前者可還原為後者。為了解決這個問題,我們必須從其相互可還原性來研究各種不同的對象種類。

為此目的,我們要根據所涉及的對象領域的實際科學知識為每一個要考察的對象尋找其基本事實存在的充分而必要的條件的各種可能性。對此我們可采取下面的辦法來進行,即要求這門實際科學給出基本事實的一個(确實而常在的)表征_。”Excerpt From: 【德】魯道夫·卡爾納普. “世界的邏輯構造.”

  • 簡單表達,去掉無意義的修飾,去掉試圖緩和語氣的從句。- 反例:“我們可以看到, TencentDB 在一定程度上可以滿足我們對事務支持的需求。” - 修改後:“TencentDB 支持事務”。- 反例:“MR 提交信息作為讀者查閱修改曆史時第一時間看到的信息,其重要性不言而喻。” - 修改後:“讀者查閱修改曆史時會首先關注 MR 提交信息。” - 本段讨論另一個問題,即……
  • 語氣要冷靜。避免過于口語化。- 不要加順口溜 - 不要使用語氣詞 - 不要使用歎号!如果希望強調,使用粗體或者斜體!也可以使用分級标題!
  • 準确。描述客觀事實,避免加入主觀情緒。
段落

段落應該盡量短。通常,一個段落不要超過 8 個完整的句子。每個段落有且僅有一個清晰的主題。每個段落開頭應該是主題句,方便讀者快速了解段落大意。段落中的每一句話應該與主題緊密相關;否則,它應該另起段落,或者應該删掉。

注意段落的流動。段落句子應該始于一個讀者已經熟悉的概念,将新的内容放在句子結尾。這樣,讀者可以更連貫地理解。

使用列表

使用 Bullet point 标明無順序的列表,使用數字序号明确前後順序。如何正确使用列表不在本文詳細展開,會在後續文章介紹,也可參見文末的參考文獻。

結構
  • 使用模闆:使用模闆可以作為思考輔助,同時也提供了相對較完整且規範的結構。文末提供了一份設計文檔模闆以供參考。
  • 使用圖表:一圖勝千言。合理地使用圖表可以極大地降低用戶的理解成本。
  • 使用标題:标題要分級、要簡短清晰
篇幅

設計文檔不要過長。太多内容堆積在一個文檔中會讓讀者喪失興趣。

對于一個大型項目來說,10 頁(~5000 字)左右是一個合适的長度。當超過這個長度時,可以考慮将問題拆分成子問題分别編寫設計文檔,并在總體設計文檔中鍊接子設計文檔。

對于小問題做增量的改進,考慮使用單頁文檔(one-pager)。通常這類文檔的範圍較小,解決問題較簡單,目标用戶群體僅限于對問題已經有充分了解的内部成員。這時,可以省略背景等内容,而僅使用 目标 -- 方案 兩段式論證的結構。

排版

使用統一的字體。用戶不會意識到不同的字體代表不同的含義,隻會感受到混亂。微軟雅黑是安全選擇。

不要使用不同顔色來區分内容。不要在文中使用超過三種顔色。可以在标題及分級标題使用标志性的顔色,同時正文使用黑色。

附錄:設計文檔模闆

設計文檔沒有定式。即使如此,筆者參考谷歌設計文檔的結構和格式,并結合實際工作經驗加以完善。在此提供一個可供新手參考的設計文檔模版,您可以使用此文檔模闆作為思考的基礎。通常,無須事無巨細地填寫每一部分,不相關的内容直接略過即可。

目标

我們要解決什麼問題?”

用幾句話說明該設計文檔的關鍵目的,讓讀者能夠一眼得知自己是否對該設計文檔感興趣。如:“本文描述 Spanner 的頂層設計"

繼而,使用 Bullet Points 描述該設計試圖達到的重要目标,如:

  • 可擴展性
  • 多版本
  • 全球分布
  • 同步複制

非目标也可能很重要。非目标并非單純目标的否定形式,也不是與解決問題無關的其它目标,而是一些可能是讀者非預期的、本可作為目标但并沒有的目标,如:

  • 高可用性
  • 高可靠性 如果可能,解釋是基于哪些方面的考慮将之作為非目标。如:
  • 可維護性:本服務隻是過渡方案,預計壽命三個月,待 XX 上線運行後即可下線

設計不是試圖達到完美,而是試圖達到平衡。顯式地聲明哪些是目标,哪些是非目标,有助于幫助讀者理解下文中設計決策的合理性,同時也有助于日後叠代設計時,檢查最初的假設是否仍然成立。

背景

我們為什麼要解決這個問題?”

為設計文檔的目标讀者提供理解詳細設計所需的背景信息。按讀者範圍來提供背景。見上文關于目标讀者的圈定。設計文檔應該是自足的”(self-contained),即應該為讀者提供足夠的背景知識,使其無需進一步的查閱資料即可理解後文的設計。保持簡潔,通常以幾段為宜,每段簡要介紹即可。如果需要向讀者提供進一步的信息,最好隻提供鍊接。警惕知識的詛咒(知識的詛咒(Curse of knowledge)是一種認知偏差,指人在與他人交流的時候,下意識地假設對方擁有理解交流主題所需要的背景知識)

背景通常可以包括:

  • 需求動機以及可能的例子。如,“(tRPC) 微服務模式正在公司内變得流行,但是缺少一個通用的、封裝了常用内部工具及服務接口的微服務框架”。- 這是放置需求文檔的鍊接的好地方。
  • 此前的版本以及它們的問題。如,“(tRPC) Taf 是之前的應用框架, 有以下特點,…………, 但是有以下局限性及曆史遺留問題”。
  • 其它已有方案, 如公司内其它方案或開源方案, "tRPC v.s. gRPC v.s. Arvo"
  • 相關的項目,如 "tRPC 框架中可能會對接的其它 PCG 系統"

不要在背景中寫你的設計,或對問題的解決思路。

總體設計

我們如何解決這個問題?”

用一頁描述高層設計。說明系統的主要組成部分,以及一些關鍵設計決策。應該說明該系統的模塊和決策如何滿足前文所列出的目标。

本設計文檔的評審人應該能夠根據該總體設計理解你的設計思路并做出評價。描述應該對一個新加入的、不在該項目工作的騰訊工程師而言是可以理解的。

推薦使用系統關系圖描述設計。它可以使讀者清晰地了解文中的新系統和已經熟悉的系統間的關系。它也可以包含新系統内部概要的組成模塊。

注意:不要隻放一個圖而不做任何說明,請根據上面小節的要求用文字描述設計思想。

軟件工程詳細設計文檔(如何寫一份高可讀性的軟件工程設計文檔)2

軟件工程詳細設計文檔(如何寫一份高可讀性的軟件工程設計文檔)3

軟件工程詳細設計文檔(如何寫一份高可讀性的軟件工程設計文檔)4

不要在這裡描述細節,放在下一章節中;不要在這裡描述背景,放在上一章節中。

詳細設計

在這一節中,除了介紹設計方案的細節,還應該包括在産生最終方案過程中,主要的設計思想及權衡(tradeoff)。這一節的結構和内容因設計對象(系統,API,流程等)的不同可以自由決定,可以劃分一些小節來更好地組織内容,盡可能以簡潔明了的結構闡明整個設計。

不要過多寫實現細節。就像我們不推薦添加隻是說明"代碼做了什麼"的注釋,我們也不推薦在設計文檔中隻說明你具體要怎麼實現該系統。否則,為什麼不直接實現呢?以下内容可能是實現細節例子,不适合在設計文檔中讨論:

  • API 的所有細節
  • 存儲系統的 Data Schema
  • 具體代碼或僞代碼
  • 該系統各模塊代碼的存放位置、各模塊代碼的布局
  • 該系統使用的編譯器版本
  • 開發規範

通常可以包含以下内容(注意,小節的命名可以更改為更清晰體現内容的标題):

各子模塊的設計

闡明一些複雜模塊内部的細節,可以包含一些模塊圖、流程圖來幫助讀者理解。可以借助時序圖進行展現,如一次調用在各子模塊中的運行過程。每個子模塊需要說明自己存在的意義。如無必要,勿添模塊。如果沒有特殊情況(例如該設計文檔是為了描述并實現一個核心算法),不要在系統設計加入代碼或者僞代碼。

API 接口

如果設計的系統會暴露 API 接口,那麼簡要地描述一下 API 會幫助讀者理解系統的邊界。避免将整個接口複制粘貼到文檔中,因為在特定編程語言中的接口通常包含一些語言細節而顯得冗長,并且有一些細節也會很快變化。着重表現 API 接口跟設計最相關的主要部分即可。

存儲

介紹系統依賴的存儲設計。該部分内容應該回答以下問題,如果答案并非顯而易見:

  • 該系統對數據/存儲有哪些要求?- 該系統會如何使用數據?- 數據是什麼類型的?- 數據規模有多大?- 讀寫比是多少?讀寫頻率有多高?- 對可擴展性是否有要求?- 對原子性要求是什麼?- 對一緻性要求是什麼?是否需要支持事務?- 對可用性要求是什麼?- 對性能的要求是什麼?- …………
  • 基于上面的事實,數據庫應該如何選型?- 選用關系型數據庫還是非關系型數據庫?是否有合适的中間件可以使用?- 如何分片?是否需要分庫分表?是否需要副本?- 是否需要異地容災?- 是否需要冷熱分離?- …………

數據的抽象以及數據間關系的描述至關重要。可以借助 ER 圖(Entity Relationshiop) 的方式展現數據關系。

回答上述問題時,盡可能提供數據,将數據作為答案或作為輔助。不要回答“數據規模很大,讀寫頻繁”,而是回答“預計數據規模為 300T, 3M 日讀出, 0.3M 日寫入, 巅峰 QPS 為 300”。這樣才能為下一步的具體數據庫造型提供詳細的決策依據,并讓讀者信服。注意:在選型時也應包括可能會造成顯著影響的非技術因素,如費用。

避免将所有數據定義(data schema)複制粘貼到文檔中,因為 data schema 更偏實現細節。

其他方案

我們為什麼不用另一種方式解決問題?”

在介紹了最終方案後,可以有一節介紹一下設計過程中考慮過的其他設計方案(Alternatives Considered)、它們各自的優缺點和權衡點、以及導緻選擇最終方案的原因等。通常,有經驗的讀者(尤其是方案的審閱者)會很自然地想到一些其他設計方案,如果這裡的介紹描述了沒有選擇這些方案的原因,就避免讀者帶着疑問看完整個設計再來詢問作者。這一節可以體現設計的嚴謹性和全面性。

交叉關注點基礎設施

如果基礎設施的選用需要特殊考量,則應該列出。如果該系統的實現需要對基礎設施進行增強或變更,也應該在此讨論。

可擴展性

你的系統如何擴展?橫向擴展還是縱向擴展?注意數據存儲量和流量都可能會需要擴展。

安全 & 隐私

項目通常需要在設計期即确定對安全性的保證,而難以事後補足。不同于其它部分是可選的,安全部分往往是必需的。即使你的系統不需要考慮安全和隐私,也需要顯式地在本章說明為何是不必要的。安全性如何保證?

  • 系統如何授權、鑒權和審計(Authorization, Authentication and Auditing, AAA)?
  • 是否需要破窗(break-glass)機制?
  • 有哪些已知漏洞和潛在的不安全依賴關系?
  • 是否應該與專業安全團隊讨論安全性設計評審?
  • ……
數據完整性

如何保證數據完整性(Data Integrity)?如何發現存儲數據的損壞或丢失?如何恢複?由數據庫保證即可,還是需要額外的安全措施?為了數據完整性,需要對穩定性、性能、可複用性、可維護性造成哪些影響?

延遲

聲明延遲的預期目标。描述預期延遲可能造成的影響,以及相關的應對措施。

冗餘 & 可靠性

是否需要容災?是否需要過載保護、有損降級、接口熔斷、輕重分離?是否需要備份?備份策略是什麼?如何修複?在數據丢失和恢複之間會發生什麼?

穩定性

SLA 目标是什麼?如果監控?如何保證?

外部依賴

你的外部依賴的可靠性(如 SLA)如何?會對你的系統的可靠性造成何種影響?如果你的外部依賴不可用,會對你的系統造成何種影響?除了服務級的依賴外,不要忘記一些隐含的依賴,如 DNS 服務、時間協議服務、運行集群等。

實現計劃

描述時間及人力安排(如裡程碑)。這利于相關人員了解預期,調整工作計劃。

未來計劃

未來可能的計劃會方便讀者更好地理解該設計以及其定位。

我們确實應該把設計限定在當前問題,但是該設計可能是更高層系統所要解決問題的一部分,或者隻是階段性方案。讀者可能會對方案的完整性有所疑問,會質疑到底問題是否得到完整解決,甚至會質疑該問題在更高層的系統中是否确實值得解決。“背景(過去)-- 當前方案 -- 未來計劃” 三者的結合會為讀者提供更好的全景圖。

參考資料

軟件工程詳細設計文檔(如何寫一份高可讀性的軟件工程設計文檔)5

推薦一個零聲教育C/C 後台開發的免費公開課程,個人覺得老師講得不錯,分享給大家:C/C 後台開發高級架構師,内容包括Linux,Nginx,ZeroMQ,MySQL,Redis,fastdfs,MongoDB,ZK,流媒體,CDN,P2P,K8S,Docker,TCP/IP,協程,DPDK等技術内容,C/C Linux服務器開發/後台架構師【零聲教育】-學習視頻教程-騰訊課堂 立即學習

原文:如何寫一份高可讀性的軟件工程設計文檔

,

更多精彩资讯请关注tft每日頭條,我们将持续为您更新最新资讯!

查看全部

相关科技资讯推荐

热门科技资讯推荐

网友关注

Copyright 2023-2025 - www.tftnews.com All Rights Reserved