三個月沒寫日誌了,比較懶散……下半年準備做OEA 的 B/S 版本,比較複雜,需要從架構設計開始認真入手。正好今天到了部門反思的時間,今天先把原來的一些設計經驗總結一下,以方便將來回顧。
直入主題,這篇日誌主要用於總結一些架構層級的模組設計經驗。
總述
一個大型的架構,必然由多個較獨立的子系統/子模組構成。這些子模組如何互動,之間的介面如何定義,這是架構的架構設計的問題。而今天我主要要總結一下,針對其中的某一個子模組,應該如何進行設計。(例如,在 OEA 中有這些相對獨立的模組:分布式架構、Entity Framework、介面產生架構、命令架構、產品線架構、分布式緩衝架構、報表模組……)
我在對一個模組進行設計時,大致經過以下流程:預設計階段、邏輯設計階段、設計評審、設計調整階段、設計實現階段、模組整合階段。在一次單獨的設計中,並不是必須要經過以上每一個階段。例如,當模組比較簡單時,就不需要設計評審、設計調整等階段了。以下我逐一描述。
預設計階段
設計開始之前,我們需要為設計做很多工作。其主要的目標是收集並整理模組的需求,力求結構化地描述需求。這些需求主要包括:情境需求、品質屬性要求、環境約束。這個過程對於之後的設計過程相當重要,原因也很明顯,不再贅述。
情境需求包括:架構使用者對模組的功能性需求、70%情境、20%情境、10%情境、API 需求。
品質屬性:參考ISO 9126。這裡要分析出關鍵品質屬性。
環境約束:技術約束、系統內容等。比較常見的是對原有系統的相容性。
根據模組的複雜度不同,這個階段的時間長短可能會有很大區別。例如,介面產生架構在 OEA 架構中是核心模組,在它的 2.0 版本的設計之前,我們平時會不斷地收集前一版本的缺點及不足,做整理並使這些雜亂的需求結構化,這個工作“非正式”地做了一年,這些時間都可以算是在預設計階段中。
最後的交付物自然是:《模組需求規格說明書》。當然,文檔這東西,主要用於溝通、傳授。可以看情況而定,不一定有這個必要。但是,如果後面有正式的評審會議,這個文檔最好還是準備一個正式的。
邏輯設計階段
關鍵點:情境驅動設計、品質屬性驗證設計、環境約束驗證設計。前者做加法,後兩者做減法。
設計師的經驗越豐富,在這個階段成功的機會也就越大。要滿足一套關鍵品質屬性,如果你之前沒有遇到過類似問題的話,可能你覺得你的設計能實現,但是最後的事實往往不一定正確。而且設計不象數學那麼嚴格,更象是藝術,藝術靠什麼,靈感!所以這個階段中,不同的設計師很可能會有不同的設計稿。(當然,如果這個模組比較簡單的話,很可能設計就不會有什麼區別了,畢竟,現有的軟體設計的模式是很多的。)
邏輯設計的方法主要還是畫圖。其中主要還是依據一些通用設計的原則進行設計。
畫什嗎?主要是 UML 中的兩類圖:靜態結構圖表(包圖、類圖);動態結構圖(順序圖表)。
順帶說一句,很多設計人員可能會坐在電腦旁邊直接拿 EA 等工具畫圖。但是我個人比較喜歡的方式是:
- 先用紙筆來畫一些手稿。
這個方式主要是比較方便,任何地點都可以畫,例如開一些不重要的會議的時候,就可以隨手畫畫。而且最後看著許多有用的手稿,感覺還是很有成就感的,跟畫家似的~哈哈。
- 隨時想、隨時畫:
我覺得,一些複雜的設計不是簡簡單單就能想出來的,特別是我覺得自己的智商只是處於常人智商的範圍中,要想出一些卓越的設計,不可能只是坐在辦公室的那一點點時間。(我記得我曾在夢中想出了一些醒著的時候想不出來的東西……)
- 匯總成正式設計稿。
交付物:UML 圖!這是必須的!
這個階段中,主要考慮品質屬性及關鍵需求。
要提升該階段的能力,個人再次推薦幾本著名的書籍:《Pattern of Enterprise Application Architecture》,《Microsoft Application Architecture Guide》,《Enterprise Solution Patterns Using Microsoft .NET》。
設計評審
召開設計評審會議的原因:
- 人無完人,個人的想法很可能有問題。
- 聽取更有經驗的人的指點。
- 團隊協作、團隊溝通。
- 聽模數塊使用者的建議。
所以,如果不是十萬火急,都建議召開評審會議!
我主持過的評審會議,曾經出現了許多的問題,大家可以看看我當時的反思:《反思 - 組內設計評審會議》,不要出現和我一樣的錯誤。
設計調整階段
沒啥,看評審會議的結論。要麼做些小的調整,要麼大改動,甚至重新設計。如果改動較大,別忘了最後再召開一次評審會議。
設計實現階段
這個階段包含了設計的代碼驗證階段。
可能由於公司的組織圖不同,這個階段並不一定由設計師自己去完成。但是我建議不要完全由他人完成,設計就象是自己的孩子一樣,辛苦辛苦把他生下來,你讓別人來把它撫養大,不覺得奇怪嗎?如果你覺得你要設計的東西太多,沒時間完成,我覺得你還是少做一些,做好一些會更好。
建議實戰能力弱甚至沒有實戰能力的設計人員不要再做設計了,先好好在底層磨鍊磨鍊吧。設計師從程式員成長而來,架構師從設計師成長而來,這才是務實的做法!
這個階段考驗的是設計人員的代碼實現能力,團隊協作能力。代碼的實現能力往往真正能看出一個人的設計能力。軟體設計原則大家都會說,但是,要真正把這些原則應用到代碼實現中,卻需要時間的不斷磨鍊。如果開發組裡能有幾個為技術癡迷的人,那是最好不過的了。
實現相對於設計稿,可以有一些更多的靈活性,並不一定要100%符合設計稿,這是因為代碼實現本身就是一種微觀的設計。但是必須要求80%以上是要符合設計稿的。如果實現過程中,不得已有過多的部分不符合當初的設計稿。請:召開討論會議!重新畫圖描述當前設計!總結反思!
值得一說的是,實現階段需要著重對使用情境進行 721 分析,設計良好的 API 以應對這些情境,並配以相應的單元檢測。關於架構設計中的情境驅動設計,大家可以看這篇文章推薦的書籍:《Framework Design Guidelines 2nd Edition》。
模組整合階段
其實這個階段中的工作在上一階段中需要準備好,也就是說,在進行編碼時,需要不斷考慮所設計的代碼能否在大的環境中運行。所設計的介面是否能和當前系統正確的銜接上。如果之前的代碼沒有考慮足夠,在這一整合階段中,可能會發生一些整合的問題。不過這種情況我遇到的比較少,這裡就不展開了。
這階段完成後,最好能配上整合測試。(不過我目前都沒有做過。)
演化模組的考慮點
在整個架構的架構設計完成之後,其中所涉及到的模組分兩類:一類是在架構設計時已經考慮到並明確定義的模組;另一類是架構初始設計時並沒有考慮到,但是隨著系統逐漸演化,發現必須被添加進來的模組,我簡稱其為“演化模組”。兩種模組的設計有許多相同之處,相對而言,設計演化模組時,相對要需要考慮更多的東西。
針對演化模組,在預設計階段,約束中需要重點寫明曆史系統對當前模組的相容性約束。在設計階段,需要分析當前系統,從中找到突破口。
相容性是很麻煩的一種約束,為了滿足這種約束,常常會使簡單的設計變得複雜。最後的代碼也很可能寫得不符合規範。在以後的新版本中,如果做出不再相容這些曆史代碼的決定時,這些相容性設計需要被刪除。
設計失敗的常見原因
- 預設計階段工作做得不充足。
未收集情境、早早地進入了邏輯設計階段、甚至直接開始編碼,導致最終設計了不需要的部分,或者根本滿足不了需求。
- 過份自信,未召開評審會議。
- 設計經驗不足。(邏輯設計要求經驗、靈感)
提升方案:多把現有系統畫出來。架構模式、設計模式都熟了嗎?平時有沒有花非工作的時間多設計些東西?書看太少了?
- 編碼能力不強。(代碼實現要求實戰家。)
提升方案:天天寫些無聊的代碼?非工作時間有多少花在代碼上?書看太多了?
- 邏輯設計、代碼實現分兩波人做。
總結
這篇文章是基於目前我的設計經驗總結而成,將來可能會不斷更新……
同時,希望和園友們交流設計經驗。更加希望平台開發人員能和我一起交流平台層級的開發。
可以簡訊我,交換QQ和EMail。