日趨一日,程序員能夠在更少的時間內完成更多的事情。使用今日的高級編程語言,開發環境,工具和“快速應用開發”思想,程序員和經理都已經習慣於急速的開發周期。今日的程序員更傾向於直接跳入到編碼之中,害怕花費在非編碼工作中的每一小時,都會導致項目截止日期前的周末多加一個小時班。
編碼之前做設計這一過程已經變得過時了,將設計文檔化就更罕見了。很多程序員從來沒有寫過設計文檔,面對要寫設計文檔這一想法都畏縮不前。即使被要求寫,通常來說也只是產出了一大堆的交互圖和類圖,這些圖表大多沒有表達程序員在設計階段的思考過程。本文將簡明扼要地討論如何不用特殊工具寫出有效的設計文檔,同時無需了解UML。文中也會談到為什么一個好的設計文檔是在開始一個新項目時,程序員可以擁有的最有價值的工具之一。
為什么要寫設計文檔?
一篇設計文檔是一個你同他人交流的工具,來闡明你的設計決策是什么以及為什么你的決策是好的。不要擔心你的設計不符合UML標准,也不要擔心你沒有使用特殊的建模工具來創建它。決定你的設計文檔優劣的最大因素,是它是否清晰的解釋了你的意圖。
然而這引出了一個問題,為了傳達設計決策,你需要去考慮聽眾是誰。一個程序員同行會理解為什么一個精心設計的類抽象是一個好的設計,然而你的經理可能不會。因為你的程序員同行和你的經理對於什么是好設計有不同的概念,所以需要有兩份設計文檔;一份給同行,一份給經理。當你開始你的項目時,每份文檔為了不一樣但有同等價值的目標服務。
這看起來是過多的工作,但它實際上不是。本文將向你展示如何通過文檔的重用來完成它。
哪些因素造就了一個好的設計?
通常,如果一個設計通過有意義的方式實現了需求,它就被認為是好的。如果設計的任意一個方面拿不出正當理由,那么它可能就需要被重新評估。很多程序員試圖在他們的設計中包含進設計模式,這常常只會增加不必要的復雜性。你需要能列舉出至少一個令人信服的與需求相關的理由,去解釋為什么要做出這樣的設計決策。然后這些理由也需要被文檔化。如果你面對一個設計決策無法拿出一個清晰的理由,那么它可能沒有給你的設計增加任何價值。
圖表是將你的設計可視化的偉大工具,但它們無法傳達你的設計決定背后的動機。這就是為什么關鍵的是,讓你的圖表補充你的設計文檔,而不是充當設計文檔。
另外一個關鍵點是,要記錄你的設計決策帶來的好處。通過這樣做,其它閱讀你的文檔的人將能理解他們所能獲得的價值。同理,任何關聯的風險也要被記錄下來。多數情況下,其它程序員可能面對過相同的風險,可能會有你沒有想過的有用的觀點或者方法。通過列出這些條目,你也讓他人去思考潛在的風險。組員常常能看到當你在設計時無法覺察到的陷阱。重組織圖表中的框圖是很簡單的,但如果編碼過程中發現假定不成立,或者踩中了一個沒有預見到的陷阱而需要重寫幾百行代碼,則要困難得多。一個好的設計文檔最小化了意料之外的混亂,因為它在編碼前就將這些困難點定位出來了。
最后,文檔給你,你的經理和你的團隊提供通用的語匯,來討論這個項目。設計文檔對於經理來說是有用的工具,因為它提供了一個深入項目之中的視野,而通常來說他們沒有專門的技術知識去看到這些。通過列出好處,你給你的經理提供了切實的條目來描述為什么你的設計是可靠的。通過在開發之前記錄你設計的風險,你將那些風險的責任傳遞給你的經理了,而那是他們應該承擔的。
還有,設計文檔是一份你,你的經理和你的團隊之間的契約。當你記錄下你的假定,決策,風險等等時,你給其它人一個機會去說:“是的,這就是我所期待的。”一旦你的文檔經過了設計階段,它就是一個基線,用來在項目范圍內控制變化。顯然,需求將會時不時地改變,但有一個基線文檔,你就有權力說項目內的所有變動都不是由於對需求的誤解造成的。
寫給程序員同行的文檔
開發者設計文檔的目標是確保你的想法是有效的,你的方法可以和別人正在做的工作相互配合。如果開發者之間不交流他們的計划,那么在不同的模塊或者類開始交互時,災難一定會爆發。以下條目描述了寫這一類型文檔的通用指南:
第一節 - 陳述你的項目/子系統的目標: 在這一節中,寫幾個段落來描述你的項目或者子系統做了什么。它試圖解決的問題是什么?為什么它需要存在?誰將會使用它?通過回答這些問題,你建立起設計的范圍。如果你發現在這一節中要寫出幾個段落很困難,那你可能還沒有將問題域理解到你需要的程度。如果你不能將你的描述在幾個段落之內表達出來,那可能這個設計的范圍太大了。將這一章節作為一個工具,來驗證你的設計范圍是合理的。
第二節 - 定義你的設計中的高層實體: 高層實體是組成了你的主要設計結構的對象,或者一組對象。一個好的實體案例是一個數據訪問層,一個控制對象,一組業務對象,等等。圖一顯示了一個例子:

圖一
在這一節中,用幾個句子解釋每個實體會干什么。這些描述不必要太繁瑣,只要足夠能描述每一塊的目的就行。確保描述你在圖中定義這一實體的理由,以及它們的角色是什么。
第三節 - 針對每一個實體,定義底層的設計: 這一節是定義你的對象和對象關系的地方。對每一個對象(或者對象集),要定義以下的內容:
- 用法
在一個段落中描述對象是如何使用的,它服務於什么功能。如果一個對象將會同外部對象或系統交互,那么展示對象的接口是個好主意。最重要的是,你必須再次描述你定義這一對象的思考過程。列出好處和風險。如果一個對象提供了封裝,用一個句子描述為什么封裝增加了價值。用你的描述賦予圖表內涵。你不需要說得很繁瑣,只需要講清楚就行。
- 配置
如果你的對象需要特殊的配置或者初始化,這是個好地方去說明。如果沒有,這一節可以省略。
- 模型
圖二展示了一個例子,增補圖一中的系統安全實體。這不是完美的UML圖,但包含某些方面的UML元素。最重要的是,它描述了設計思路。

圖二
不要擔心你的模型是不完美的,但要確保描述清楚圖表中發生了什么。此處,兩個具體的安全對象繼承自一個安全對象基類,一個安全工廠類會根據系統安全模型創建特定的安全對象。
- 交互
這一節也很適合畫交互圖。一個交互圖會展示對象或實體集在完成一個復雜任務時如何相互交流。圖三顯示了一個用戶如何登陸的例子。它用到了圖一中的不同實體。

圖三
再次強調,此圖不是完美的UML,但它解釋了完成復雜任務時的交流順序。在你想用圖表展示你系統中的一個對象如何同其它子系統中的對象交流,交互圖是最有用的。這一類圖表可以讓其它開發者核實交互是否正確。
第四節 - 好處,假定,風險/問題: 在這一節中,做一個列表列舉此種設計的5至6個最重要的好處,一個列表列舉所有已知的風險/問題,還有一個列表列舉所有假定。其中一些可能只是重復你在之前章節中已經寫過的。重要的是要將這些條目都放在一個章節中,這樣如果讀者想了解有哪些好處,風險和假定,就不需要去閱讀整個文檔。
永遠不要移除此章節中的任何內容!如果風險變成非風險,記錄下它們現在不再是風險以及變化原因。不要簡單地擦除它們。同樣的原則也適用於假定。你應該能夠一看本章節就立刻了解當前設計中的風險。
寫給經理的文檔
給經理的設計文檔的目標,是要保證你的經理能理解系統主要的實體有哪些,有哪些好處,以及最重要的,有哪些風險,文檔是你顯示自己理解需求並給出了一個計划來實現這些需求的好機會。
如果你寫好了給程序員同行的文檔,那么寫給經理的文檔是簡單的,因為它僅由1,2和4章節構成。通過用上文描述的方法來划分文檔,通常來說對經理沒有太大意義的部分會包含在一個章節中,可以直接移除。
結論
寫一篇文檔最困難的部分跟“寫作”沒什么關系。難的是你要在開始編碼之前完成一個符合邏輯的設計。一旦你能洞見對象和實體的組織方式,書寫細節是簡單的。另外,完成這一任務應該不需要除字處理程序和一個簡單的繪圖軟件外的其它工具。在這一任務上花費一周時間所帶來的積極效應,會在項目結束時帶來難以想象的回報。正如格言所說:“如果你在做計划上失敗了,那么你就是在計划着去失敗”。
