摘要:
十幾年前剛畢業不久,我從事第一份軟體開發的工作,要完成一個專案,但沒有任何軟體設計的思路,於是請教我的老闆。我的老闆給了我兩種思路:1)先假設軟體已經做出來了,想好軟體的外在表現,由此倒推軟體的實現方法;2)思考程式的資料結構,先設計資料庫,然後再搭建軟體的上層建築。老闆給了我很大的啟發,隨著工作的開展,後來我又發現了第3種設計的思路。本文將為你分享三種軟體設計的思路:1)由頂而下;2)由底而上;3)由中間到上下。
大綱:
1.什麼是優秀的設計?
2.優秀的設計能節省專案工作量
3.優秀設計從分析需求開始
4.軟體系統不是木桶型的
5.軟體設計的“大道理”
6.規劃系統骨架——架構設計
7.打造系統的底蘊——資料庫設計
8.細節決定成敗——詳細設計
9.使用者感覺好才是真的好——使用者體驗設計
10.持續提升設計水平
本文章是系列文章之一,如果你還沒有看過之前的文章,建議先看完前面的文章再看本篇,這樣效果更好。
5.軟體設計的“大道理”
5.1 我的第一次商業軟體的設計經驗
1999年剛畢業不久,我從事第一份軟體開發工作,當時要負責一個大型桌面軟體,但不知道應該如何開展軟體設計工作,於是向老闆請教。老闆也僅僅是年長我幾歲,不過公司的核心產品是老闆開發的,老闆說他其實也沒有什麼系統的方法,不過有兩種思路供我參考:
1)先假設軟體已經做出來了,想好軟體的外在表現,由此倒推軟體的實現方法;
2)思考程式的資料結構,先設計資料庫,然後再搭建軟體的上層建築。
2)思考程式的資料結構,先設計資料庫,然後再搭建軟體的上層建築。
上述的兩種軟體設計思路,相信很多有軟體設計經驗的朋友都能體會到。後來我又體會到第三種的設計思路,後文將會為你分享我對這三種設計思路的一些體會。
5.2 N層架構是怎麼回事?
這三種設計思路都與軟體系統的N層架構有關係,我們以常見的四層架構為例子,請看圖:
圖5.1 四層架構
這個是UML的包圖(Package Diagram),圖中好像資料夾的那個東西就是“包”,包與包之間的虛線箭頭表示的是依賴關係。
上圖表示的意思如下:
1)四層架構的四層,分別是指:表現層、邏輯層、資料訪問層和資料層;
2)表現層依賴於邏輯層,邏輯層依賴於資料訪問層,資料訪問層依賴於資料層。
2)表現層依賴於邏輯層,邏輯層依賴於資料訪問層,資料訪問層依賴於資料層。
那“依賴”是什麼意思呢?
“依賴”可以是以下情況之一:
1)A需要呼叫B的方法,則A依賴於B;
2)A的方法中某些引數的型別是B,則A依賴於B;
3)A的某些方法的返回值型別時B,則A依賴於B。
2)A的方法中某些引數的型別是B,則A依賴於B;
3)A的某些方法的返回值型別時B,則A依賴於B。
這樣我們大概瞭解了四層架構是怎麼回事了,但我們還會有以下問題:
1)表現層如何將資料傳遞給邏輯層?
2)邏輯層如何將資料傳遞給資料訪問層?
3)資料訪問層如何將資料傳遞給資料庫?
3)資料訪問層如何將資料傳遞給資料庫?
通常我們不會這麼老土通過一大堆引數來傳遞層與層之間的資料,通常我們會將資料裝在實體類中,通過實體類來傳遞資料。所以圖5.1可以進一步表示為圖5.2:
圖5.2 四層架構與實體類
補充說明一下什麼實體類?
實體類通常是一個只有屬性沒有方法的類,通常我們會將某一業務物件的資料裝在一個實體類中。例如:某請假單實體類,該類可能有請假人姓名、請假起止時間、請假類別和請假事由等屬性。
5.3 “由頂而下”的設計思路
看了圖5.1和圖5.2,你大概就清楚了什麼是軟體的“頂”?什麼是軟體的“ 底”?“頂”就是表現層,“底”就是資料層。那麼“由頂而下”的設計思路,其實就是先想清楚軟體的表現層,然後再思考邏輯層、資料訪問層、資料層的實現。
前文我們提到要“需求驅動設計”,這個說法有點籠統,我們需要進一步思考:“什麼需求”驅動“什麼設計”?
請看下圖:
圖5.3 由頂而下的設計思路
這是UML的活動圖,橫線將圖分成了上下兩部分,上部分是需求分析,下部分回答了“什麼需求”驅動“什麼設計”的問題。
說明一下:“需求驅動”及橫線不是UML圖的標準語法,圖加上這些非UML元素是為了更好地表達問題。
“需求分析”這個活動有三種工作產品,分別是:
1)用例/使用者故事;
2)業務流程圖;
3)業務概念圖。
2)業務流程圖;
3)業務概念圖。
你可以理解為上述三種工作產品是“需求分析”這個活動的“輸出”。
“用例/使用者故事”和“業務流程圖”是“規劃介面”這個活動的“輸入”;類似,“業務流程圖”和“業務概念圖”是“設計邏輯層”這個活動的“輸入”。其他就不再多解釋了,你應該可以看懂這個圖了,後續幾個圖的語法類似,也不再解釋了。
上述是對圖5.3語法及表達意思的基本解釋,這裡再稍微小結一下:
1)分析需求是設計的開始,我們還需要將需求至少分解為三部分:軟體要滿足的功能(用例/使用者故事)、業務流程(業務流程圖)、業務概念(業務概念圖)三部分;
2)設計不同的層時,主要依賴的需求是不太一樣的,上述分解的三部分需求對不同的層設計提出了不同的要求。比方說:設計資料庫時主要是根據業務概念來設計的,規劃介面時主要根據軟體需要滿足的功能點,還有業務流程來設計。
2)設計不同的層時,主要依賴的需求是不太一樣的,上述分解的三部分需求對不同的層設計提出了不同的要求。比方說:設計資料庫時主要是根據業務概念來設計的,規劃介面時主要根據軟體需要滿足的功能點,還有業務流程來設計。
5.4 “由底而上”的設計思路
經過前面的鋪墊後,這個“由底而上”的設計思路,相信你一看圖就可以懂了。
圖5.4:由底而上的設計思路
這個圖也分成了上下兩部分,上部分的內容其實和圖5.3是一樣的,只是左右順序不太一樣而已。
5.5 “由中間到上下”的設計思路
這種設計思路是我從事軟體研發工作若干年後才認識的,當時是因為專案出現了特殊狀況,為了應對這樣的狀況而採取的一種設計方法。
案例分享:客戶要改SQLServer為Oracle
簽訂合同時,我們和客戶約定的專案技術架構是.net+SQLServer,當時客戶沒有反對,我們就按這樣的技術架構完成了系統,並且部署上線。但是不久客戶居然提出了這樣的要求:要求我們使用Oracle資料庫,而不能用SQLServer資料庫!我們通常是按照“由底而上”的思路來設計軟體的,如果資料庫要更換,基本上整個軟體就等於重做!
如果你遇到這樣的狀況,你會怎麼辦呢?能不能按需求變更來處理呢?只有客戶願意付錢,我們就願意幹!但客戶願意付錢嗎?這可是要付推翻重做的錢啊!!
最後我們的領導決定免費重做,領導決定免費重做的原因是:
這是公司的一個核心專案,我們期望這個專案將來能產品化,能持續賺錢。但我們技術選型主要是根據我們當前的技術情況來決定的,沒有充分考慮客戶的情況。客戶是某重要行業的企業單位,單位體制內的所有企業基本都是用Oracle的,但我們選擇“視而不見”,選擇了我們最熟悉的SQLServer來開發系統,其實遲早是要遇到問題的。客戶除了用我們的系統,還會用其他更大型的更重要的系統,客戶的其他系統基本上都是使用Oracle資料庫的。所以如果我們要在這個客戶領域開啟市場,將專案做好,就有必要將系統改造為Oracle資料庫。
但是我們已經有部分客戶使用了我們的基於SQLServer的系統了,將來也有可能會有部分客戶要求用SQLServer,所以我們領導決心改造軟體的架構,要讓我們的軟體可以支援SQLServer,也可以支援Oracle!於是我們按照“由中間到上下”的思路,重新打造了軟體架構,請看下圖:
圖5.5 由中間到上下的設計思路
這個圖也分成了上下兩部分,上面部分和前面的圖內容也是一樣的,但下面部分就很不一樣了,而且可能比較難理解。
“由中間到上下”基本的思路是這樣的:
1)先不考慮表現層,也不考慮資料層;
2)先定義實體類和資料層介面;
3)介面定義好後,往上可以設計邏輯層和表現層,往下可以設計資料層介面的實現和設計資料庫。
2)先定義實體類和資料層介面;
3)介面定義好後,往上可以設計邏輯層和表現層,往下可以設計資料層介面的實現和設計資料庫。
按照這樣的設計思路做出來的軟體架構,應該是這樣的:
圖5.6 由中間到上下的系統架構
圖中見到資料操作層介面有兩種不同的資料庫實現,分別是SQLServer和Oracle,如果要考慮第三種資料庫,那麼再增加一個實現就搞定了,而系統的上層建築(表現層、邏輯層)不需要改變。
這樣的設計方式看上去很酷,是不是應該所有系統都要考慮用這樣的方式來打造呢?
不是滴,這樣的設計方式是有缺點的:
1)系統將不能充分利用資料庫的特性,一般會禁止在資料庫中寫儲存過程、觸發器、甚至是檢視等,程式的的效能其實會降低;
2)因為不能充分利用資料庫本身的特性,所以大部分甚至是全部的業務邏輯只能靠程式搞定,這樣其實增加了程式的複雜度和工作量。
2)因為不能充分利用資料庫本身的特性,所以大部分甚至是全部的業務邏輯只能靠程式搞定,這樣其實增加了程式的複雜度和工作量。
所以每種設計方法都是有針對性的,都很難做到十全十美,一般只能針對主要矛盾做出一些取捨。
5.6 小結
如果系統沒有多資料庫的要求,我會比較建議你用“由頂而下+由底而上”的設計思路;如果程式需要支援多資料庫,那麼可能考慮“由中間到上下”。上面介紹的三種設計思路,其實在實際工作中我們往往不會只選其一,往往是結合了多種思路的。不要侷限自己的思路,軟體設計的可能性是無窮的。
本文是系列文章的第4篇,要做軟體設計師一點都不簡單啊,請留意後續文章!
如果本文對你有幫助,麻煩點一下“推薦”啦,謝謝!
作者:張傳波
創新工場創業課堂(敏捷課程)講師
軟體研發管理資深顧問
CMMI首席專家
《火球——UML大戰需求分析》作者
軟體知識原創基地創辦人