軟體設計是怎樣煉成的(5)——規劃系統的骨架(架構設計)(下篇)

張傳波(Fireball)發表於2014-02-18

摘要:

概要設計和詳細設計,可能是最開始聽說的設計,但後來發現如果侷限在這兩個設計的框架下,可能會有諸多不順,我們需要架構設計、資料庫設計、模組設計和使用者體驗設計,本文主要分享架構設計,此文有點長,所以分拆為上下兩篇,下篇為你分享:在”需求驅動“如何做出初步架構設計、如何逐步細化這個設計、分散式與單機系統架構設計的區別等。

 

大綱:

1.什麼是優秀的設計?
2.優秀的設計能節省專案工作量
3.優秀設計從分析需求開始
4.軟體系統不是木桶型的
5.軟體設計的“大道理”
6.規劃系統骨架——架構設計
7.打造系統的底蘊——資料庫設計
8.細節決定成敗——詳細設計
9.使用者感覺好才是真的好——使用者體驗設計
10.持續提升設計水平

 

本文章是系列文章之一,如果你還沒有看過之前的文章,建議先看完前面的文章再看本篇,這樣效果更好。

 

 

6.規劃系統骨架——架構設計

 
 
6.5 逐步拆解架構設計
 
需求驅動設計
有這樣的一句話:不以結婚為目的的談戀愛是耍流氓!
這句話與軟體設計有什麼關係呢?很有關係呢!因為有另外這樣的一句話:不以解決需求為目的軟體設計就是耍流氓!
所以如果不想被人家說你耍流氓,你需要了解需求,需要“需求驅動”地思考設計問題。
 
前文我們從需求中發現了四個設計點,一起來回顧一下:
1)用例圖中提到,員工可以通過移動裝置提出請假或外出申請,領導可以及時收到審批的提醒。那麼我們應該如何設計“即時瞭解”和“及時收到提醒”呢?解決方案可能有:簡訊提醒、郵件提醒、或者兩者同時提醒。
2)需求中要求員工可以通過移動裝置提出申請,領導也可以通過移動裝置完成審批?我們要思考,為什麼需要移動裝置完成這些工作呢?什麼情況下才需要通過移動裝置完成這些工作呢?我們的解決方案是怎樣呢?通過簡訊、手機上網,還是通過手機的APP來搞定?
3)請假申請和審批流程,跟流程相關的都可以扯到“工作流”。工作流可以是一個很“恐怖”的話題,你打算做一個"死"的工作流,“半死不活”的工作流,還是“全活”的工作流呢?你打算從零開始做,還是買一個工作流引擎呢?
4)許可權要做成重用已經是有一定難度的,同時還需要考慮與工作流的結合,還要考慮工作流也可以做成重用,難度很高啊!那到底要不要考慮做成重用,並且許可權和工作流能結合起來呢?
 
補充說明一下工作流:
1)死的工作流:就是程式碼寫死的(hard code),資料庫設計也是死的,流程或表單有任何變化,都可能需要改程式碼和資料庫設計。
2)半死不活的工作流:部分地方寫死,部分地方是靈活的,能適應部分需求變化。
3)全活的工作流:程式碼和資料庫設計等都是靈活的,能基本適應流程及表單的變化,不需要修改程式碼或資料庫設計,只要配置一下就可以搞定。
沒有任何工作流技術積累的情況下,要做到“全活的工作流”是很高難度的,一般不要在當前專案中就定下這樣的設計目標,基本是實現不了的。可以分階段來做,先寫“死”,然後“半死不活”,最後才追求“全活”。
 
初步架構設計(第一層拆解)
我們再次回顧一下,什麼才是優秀的設計?
我在前文中提到,一個優秀的設計應該具備以下特點:

1)優秀的設計都是需求驅動的,不熟悉需求就做出來的設計是不靠譜的;
2)優秀的設計應該是當前團隊能理解能實現的,太超前的設計專案團隊做不出來,這個設計只能是擺設;
3)優秀的設計應充分考慮當前各種限制條件,適當做出平衡,能保證達成專案的目標:
4)優秀的設計能儘量降低專案的整體工作量,讓整個專案更加可控。

我們嘗試一下,儘量按上述標準來完成這個設計吧!

我打算用 .net(開發語言採用 C#) 及 SQLServer 來開發這個系統。
你可能會問,為什麼你選擇這個開發語言和資料庫?這些不是需要論證,需要做方案選擇的嗎?
我們不是搞理論或學術研究,一個真實專案的情況是這樣的:你接手專案時合同已經簽下來,合同中會規定用什麼技術框架的,包括開發語言與資料庫,一般不會不定下來的。而定下來的技術框架,一般就是你們公司最熟悉的那種,而你接手這個專案,一般是熟悉這個技術框架的。公司不會這麼傻,選一個自己公司一點都不熟悉的技術框架來完成專案,客戶更加不會這麼傻選一個不懂這個技術架構的軟體公司,你的上司也不會這麼傻找不熟悉這個技術架構的你來負責這個專案的設計。
一個系統到底用.net好一點,java好一點,PHP好一點?這些其實沒有定論的,一般來說就是你熟悉哪個就用哪個!哪個你最有經驗最有成功案例就用哪個!針對具體一個專案做架構設計時,不能脫離具體的技術框架,要先確定你的開發語言、資料庫種類等。架構設計要從物理設計的深度來思考,而不能僅僅是理論設計或者是邏輯上的設計,否則又會犯了太空洞的毛病(即“放之四海而皆準”的毛病)。
 
以下是初步的架構設計,這個設計並不是怎樣“驚天地泣鬼神”,僅僅是我覺得我們能做到的也能應對需求的一個設計。
 
圖6.6 初步的架構設計
 
圖中標記出來的1、2、3、4,分別對應對前面的設計關注點1、2、3、4。此圖對設計關注點1、2考慮得稍微具體一點,而對於設計關注點3、4僅僅是一個初步的考慮,因為當時我們工作流的技術積累還比較初級。
需要特別說明的:請留意“智慧手機”這個客戶端,圖中寫的是作業系統用WindowsMoble,這是一個以前的設計,在現在看來是不合適的,現在用這種作業系統的手機幾乎不存在了。需求中提到要求使用移動裝置完成相關工作,那麼我們就需要思考是什麼移動裝置呢?移動裝置上需要什麼作業系統?需要安裝什麼軟體等等?這些我們都需要考慮。
 
小結一下進行初步架構設計的要點:
1)我們的系統大部分會涉及到多個客戶端及伺服器,我們需要思考我們的系統需要怎樣的客戶端及伺服器,思考這些裝置上面需要安裝怎樣的作業系統、平臺、軟體等,思考這些裝置需要怎樣的硬體配置,如CPU、記憶體、硬碟大小等等。
2)我們需要思考這些客戶端及伺服器之間的物理聯絡方式,例如:是區域網方式、網際網路,還是兩者都支援?是HTTP或是HTTPS?等等。
3)這些裝置上我們需要開發什麼軟體、資料庫等?例如:圖6.6中需要我們需要開發的東西有:Web Application、工作流定義用的客戶端軟體、三個資料庫。架構設計其實就是劃分系統的各部分及各部分的關係,這些內容其實就是我們整個系統的第一次的各部分的劃分,而各部分的關係我們可以通過圖6.6大致可以瞭解。
 
繼續深入拆解(第二層拆解)
圖6.6已經從硬體配置、軟體各部分的劃分、資料庫的規劃等方面描述了本系統的初步架構,當然這個架構還是太粗了,我們還需要繼續深入思考,請看下圖:
圖6.7 架構設計的進一步思考
 
這個系統至少有5個需要我們開發的部分,每一個部分都需要更進一步深化設計,下面我們以Web Application為例子,繼續深入設計!請看下圖:
 
圖6.8 Web Application的設計
 
我們規劃 Web Application 的內部架構時,除了考慮內部各部分之間的關係,也需要考慮內部所劃分出來的各部分,有哪些是需要和外部互動的?圖6.6中表示的各部分關係還比較粗,我們還需要繼續細化,請看下圖:
 
圖6.9 系統各部分的關係
 
當我們逐步細化設計的時候,我們很可能會發現之前初步架構設計不合理的或遺漏的地方等等,留意圖6.9中紅色的部分,這是之前沒有畫進去的內容。這個圖已經更進一步細化設計了,但我們仍然有很多問題未解決,請看下圖:
 
圖6.10 更多的更具體的設計問題
 
圖6.10與圖6.9的區別就是多了黃色的部分,請思考這三個問題:
1)許可權設定的UI如何考慮?
使用者管理、許可權管理的UI可考慮設計成可重用的。
介面可以是獨立的,也可以“嵌入”到別的系統中。
2)工作流如何設計?
還需要對工作流進行進一步的抽象。
考慮清楚工作流的對外介面。
考慮清楚資料庫設計。
3)圖形定義客戶端軟體如何設計?
圖形平臺自主開發,還是利用第三方的?
資料如何儲存到DB中?
除了上述這些問題和思考,還會有更多的其他問題,軟體設計是充滿挑戰的工作!
 
設計初期的問題可能比較朦朧比較大,但隨著設計的深入,問題會越來越多,問題也會越來越具體。有時候你會覺得怎麼越深入設計,發現的問題越多,這是正常現象,而且是好事!如果沒有發現問題,這往往不是真的沒有問題了,而是我們不具備發現問題的能力了,這是相當可怕的,要小心留意不可輕敵噢!
 
圖6.6後我們連續進行了多步的設計拆解,這裡小結一下:
1)系統需要開發什麼軟體和資料庫等,這些是第一次對系統各部分的拆分,姑且這叫”第一層的拆解“,接下來需要繼續拆解。
2)繼續拆解時可參考分層架構,但需要拆分得更加具體,不要犯”放之四海而皆準“的毛病。這個層次的拆解,姑且叫“第二層的拆解”。
3)除了規劃好內部各部分的關係,還需要規劃內部的各部分與外部之間的關係。
4)在拆解的過程中,問題會越來越多,也會越來越細,這是正常現象,也是好現象。
5)拆解過程中也可能會發現之前初步架構設計中不合理或遺漏的地方,請馬上調整;有時候甚至會發現之前的設計完全不對,那麼就要有勇氣推翻重做。
6)“第二層的的拆解”結果有可能是元件(Component)、程式碼包、某個分層等等,可能是“物理分拆”也可能是“邏輯分拆”。那麼“第二層的拆解”要多細才合適呢?其實很難有固定的標準,給一個簡單標準作為參考:如果再拆解下去下一步的拆解就到類了,那麼就可以認為目前的拆解粒度比較合適了。細化到類的拆解,可以在模組設計(詳細設計)中再進一步考慮。
 
說明一下“物理分拆”和“邏輯分拆”:
物理分拆:物理分拆就是物理上是獨立的部分,有可能是exe、dll、資料庫檔案等。圖6.6中將系統分拆為5部分,分別是Web Application、流程定義用的客戶端軟體以及三個資料庫,這就是物理分拆;我們對Web Applicationi繼續分拆時,圖6.8中的日曆控制元件是物理分拆,這個控制元件將通過二進位制的方式供程式其他部分呼叫,而這個控制元件將來也可以供其他系統使用。
邏輯分拆:程式碼包、某個分層這些往往是邏輯分拆,物理上它們不會編譯成單獨的一部分,而是被整體編譯進軟體當中。
 
“第二層拆解”的目的除了更加方便我們設計出系統,另外一個重要目的就是做系統的重用設計。如果是“物理分拆”,就可以做到二進位制重用;如果是“邏輯分拆”,那麼只能做到原始碼重用。這些重用不僅僅為當前軟體服務,還可以為將來及其他軟體服務。
 
 
6.6 分散式系統與單機系統的架構設計
 
分散式系統可能有很多定義,有些資料可能也說得比較炫,文章這裡提出這個說法不是用來“拋書包”的,這裡也順便說明一下:本文中提出的一些概念(例如:第一層拆解、第二層拆解、物理分拆、邏輯分拆)是為了更加方便說明問題而已,大家沒有必要去網際網路上搜尋這些名詞的定義。
我們開發的東西只需要安裝在一臺電腦上,這個軟體就能工作,這就是單機軟體,例如Office軟體、Photoshop軟體等;但分散式系統往往需要我們在多臺裝置上部署,各部分需要聯調後,整個系統才能正常工作。
文中用到的案例是分散式系統,分散式系統如何做架構設計,相信你已經有一些體會了。單機系統的架構設計看上去似乎更簡單一點,因為它不需要做“第一層拆解”,直接就是“第二層拆解”。其實不一定的,因為單機系統的“第二層拆解”往往是很複雜的,單機系統往往有特殊的高科技的演算法、有獨特資料儲存格式等等,你可以設想一下,你能完成Office的架構設計嗎?還有Photoshop的架構設計?
 
 
6.7 架構設計小結
 
架構設計是高難度、高技術含量的活,我覺得很難寫出一本祕籍,你看了後就能應對大部分軟體的架構設計。如果我們不精通業務,不精通技術,沒有豐富的設計經驗,很多設計我們將會束手無策。
 
小結一下分散式系統的架構設計要點,單機系統也可以參考:
1)我們的系統大部分會涉及到多個客戶端及伺服器,我們需要思考我們的系統需要怎樣的客戶端及伺服器,思考這些裝置上面需要安裝怎樣的作業系統、平臺、軟體等,思考這些裝置需要怎樣的硬體配置,如CPU、記憶體、硬碟大小等等。
2)我們需要思考這些客戶端及伺服器之間的物理聯絡方式,例如:是區域網方式、網際網路,還是兩者都支援?是HTTP或是HTTPS?等等。
4)思考系統需要開發什麼軟體和資料庫等,這些是第一次對系統各部分的拆分,姑且這叫”第一層的拆解“。
5)繼續拆解時可參考分層架構,但需要拆分得更加具體,不要犯”放之四海而皆準“的毛病。這個層次的拆解,姑且叫“第二層的拆解”。
6)除了規劃好內部各部分的關係,還需要規劃內部的各部分與外部之間的關係。
7)在拆解的過程中,問題會越來越多,也會越來越細,這是正常現象,也是好現象。
8)拆解過程中也可能會發現之前初步架構設計中不合理或遺漏的地方,請馬上調整;有時候甚至會發現之前的設計完全不對,那麼就要有勇氣推翻重做。
9)“第二層的的拆解”結果有可能是元件(Component)、程式碼包、某個分層等等,可能是“物理分拆”也可能是“邏輯分拆”。那麼“第二層的拆解”要多細才合適呢?其實很難有固定的標準,給一個簡單標準作為參考:如果再拆解下去下一步的拆解就到類了,那麼就可以認為目前的拆解粒度比較合適了。細化到類的拆解,可以在模組設計(詳細設計)中再進一步考慮。
 
軟體架構設計博大精深,上述僅僅是一些規律的簡單總結,希望對你能有一點點幫助。
 

本文是系列文章的其中一篇,要做軟體設計師一點都不簡單啊,請留意後續文章!

 

如果本文對你有幫助,麻煩點一下“推薦”啦,謝謝!

 

 

作者:張傳波

創新工場創業課堂(敏捷課程)講師

軟體研發管理資深顧問

CMMI首席專家

《火球——UML大戰需求分析》作者

軟體知識原創基地創辦人

相關文章