2012年3月11日 星期日

軟體專案的素質之三 ─ 整體設計之 架構設計篇

這次takeshi要談的是架構設計,在正式開始討論之前,takeshi要先幫大家refresh一下記憶,之前takeshi討論系統設計的文章,引用了kenming的文章,如下圖...

{程序員邀稿} 以架構為中心的主要設計產出(1)Kenming's鮮思維
 takeshi也講解過對於 需求、結構和實作觀點的看法,takeshi再舉一個關於"舞台劇"的例子:需求觀點就好比是一齣劇的劇本,而結構觀點就好比是這齣劇的演員,實作觀點就好比是舞台的選擇;我們從導演或編劇(客戶窗口或領域專家)手上拿到劇本(需求收集),然後挑選適合的演員(系統分析),請演員依據劇本作排練(系統設計,takeshi是使用Domain-Driven Design),然後就預期觀眾人數(系統正式上線人數)來決定正式演出的舞台(架構設計);也就是說,舞台劇的預期觀眾人數較少,就使用較簡單的舞台,而預期觀眾人數較多,就使用較大較豪華的舞台

關於劇本的內容和演員的演技,就是藉由不斷的排演(Iteration)來跟導演或編劇作確認與調整;而平常大家都是在排練室作排練來磨練演技(Unit Test, Integrated Test),偶而在正式舞台上作排練來確認最終表演的成果(System Test),必要時也請一些觀眾來參與排練演出(User Acceptance Test);經由不斷的排練,最終是一個博得滿堂彩的演出(成功的專案,客戶滿意、高品質的系統)!

所以說系統的架構設計就是在探討該如何挑選適合的舞台!
那該如何挑選呢? takeshi在這裡分享自己在作系統架構設計時的思考框架

Tiers (欲開發之應用系統的概念分層)
首先,先從欲開發之應用系統(SuD,System under Development)之概念上的分層架構著手,以下這張圖對於JavaEE的developer來說,應該不陌生
SuD的tiers,本blog整理

以下簡單介紹每個Tiers所負責的工作
Client Tier
指SuD使用者的環境,可能是PC、Browser、Smart Phone等...

Presentation Tier
指SuD的使用者介面,現行應用系統大多是圖形化使用者介面(Graphical User Interface)

Business Tier
指SuD商業邏輯運行的地方,Domain Model也是在這裡運行

Integration Tier
指SuD對其他外部系統互動之邏輯所運行的地方

Resource Tier
指外部系統,可能是其他上下游系統,亦或是資料儲存媒體(資料庫、檔案)等

最左邊的Client Tier是對SuD使用者提供服務,使用者觸發某個事件(例如click button),此事件會產生請求,往右邊 Tier傳送,一層接著一層,直到SuD把請求處理完;接著再往左邊 Tier回傳,又一層接著一層,傳回到SuD使用者看到回應,接著使用者再對SuD繼續執行下一個步驟,因此又觸發新的事件,SuD再接著處理;此一連串步驟不斷執行,直到使用者把他/她的目的達到為止

舉個例子,使用者使用瀏覽器(Client Tier)在線上書店網站(Presentation Tier)購物,已在購物車中挑選好想要購買的書籍, 接著點選「結帳」連結,觸發使用者介面事件,事件產生請求(request),並傳送到SuD的Business Tier;SuD商業邏輯要幫使用者產生訂單,會跟Integration Tier請求使用者資訊(地址、電話等)、書籍價格、運費資訊等,接著Integration Tier會跟資料庫(Resource Tier)請求相關資料,再回傳給Business Tier;Business Tier把這些相關資料包裝起來,再一起送到Presentation Tier,在線上書店網站呈現出填寫訂單頁面;等待著使用者填寫訂單,並觸發下一個事件;上述類似流程會不斷執行,一直到使用者把他/她的訂單完成(達到目的)為止

如上所述,把一個SuD拆解成多個Tier,其主要原因如下

降低複雜度
這是人類處理複雜問題的一般處理手法;把一個龐大的複雜問題,照一定的邏輯和相關性作分解和歸類,拆成一個個小型問題,再來針對這些小型問題來想解決方案,問題複雜度會因此降低很多,也就是要分而治之 (divide and conquer)


鬆散耦合和提高內聚力(Loosely-coupled & Highly-cohesive)
這是物件導向設計原則都會提醒的概念,我們在作系統設計時,類別之間要相依於介面而不是實作,和每個類別所負責的操作是否適當,如此才能提高類別之間的彈性和盡量縮小因需求變動而產生的設計變動範圍;然而在設計SuD之間的Tier的相依性時,也是同樣的道理;每一 Tier都會提供介面來對下一個 Tier提供服務;例如當SuD的Resource Tier對外部系統的呼叫,其外部系統的介面從原本的JDBC呼叫,換成了Web Service技術,我們只要抽換此Resource Tier的相關實作即可,SuD的其他Tier皆不會受影響


實務經驗分享
就takeshi在實務上的經驗,其實在業界待過一陣子的developer,大多都知道這個東東,但對為啥要這麼作卻不甚了解,所以到後來的概念分層,變成了單純地只是在命名空間(在Java是指package)上的區別,然而實作之間的相依性卻藕斷絲連,舉一些例子如下...

1. Data Integration Tier使用了DAO pattern(Data Access Object),但卻在Business Tier組裝SQL語法,當作DAO物件方法的參數;試問假如遇到了takeshi剛舉出的例子(從JDBC換成Web Service)時,那是不是連同Business Tier也受到影響了呢?

2. 同樣也是DAO的例子,takeshi也看過直接從DAO方法回傳ResultSet物件出來的...

3. 還有一種是比較不明顯的例子,就是在DAO中直接用SQL組成SuD UI的資料需求,然後直接往前端Tier回傳,而Business Tier單純只是為了要接收request、呼叫DAO,接著把資料往前回傳;就takeshi的觀察,主要會有以下問題衍生...

3.1 SQL語法會異常複雜,並且類似語法會散佈在整個DAO都是(或是散佈在資料庫端),一旦使用者介面有修改需求,必須要搜尋整個DAO tier,確保相關修改資料的SQL語法都有調整到

3.2 一旦SQL語法查詢無法滿足UI需求時,就會在Business Tier作資料組裝的工作,通常此類型的資料組裝邏輯,可讀性相當低;原本複雜的SQL + 到處散佈在DAO Tier + Business Tier的資料組裝的可讀性低,大大地增加系統維護的複雜度!


Layers (平台服務的分層)
接下來takeshi要分享的是各階層平台要提供哪些服務來支持SuD的需求;要聚焦的是SuD的每個Tier,在每一個Layer需要哪些服務,是一種二維的概念,如下圖所示

Tiers & Layers Diagram,本blog整裡

有在追蹤takeshi部落格的朋友,相信對這張圖有點眼熟,這是Java MVC  sample#2的Tiers & Layers Diagram,takeshi借用這張圖來對每個Layer所代表的意義作個簡單介紹

Application Layer
描述SuD的軟體元件;參考上圖,從Client tier到Data Integration tier就是Sample Project #2和Resource tier的DB Schema

Virtual Platform
描述SuD所相依之平台所提供的介面 ;參考上圖,在Client tier是基於html v4.0,而在Presentation tier則是AS v3、MXML和PureMVC-AS3-2.0.4,之後以此類推...

Upper Platform
描述SuD所相依之平台本身;參考上圖,在Client tier是基於任何廠牌的瀏覽器(Any browser)和Adobe Flash Player v10的版本

Lower Platform
描述SuD所相依的作業系統(OS,Operating System);參考上圖,Client tier是可以是任何OS,而SuD也是任何OS;另外要注意的是,Client tier和Presentation ~ Resources tier是拆分為兩個儲存格,其實是代表在不同的電腦上運作的意思

Hardware Platform
描述SuD所相依的電腦規格;參考上圖,不論是Client tier或是Presentation ~ Resources tier都可以是任何電腦

takeshi在實務上會使用tiers & layers diagram或是UML的佈署圖來記錄以上資訊


Service-Level Requirements/Quality Of Service (QoS)
在這一節,takeshi要分享的系統架構設計最大的主角,也就是系統的非功能性需求,簡單介紹如下...

Performance
描述客戶期望SuD對於需求的反應時間;例如,當使用者在線上書店下訂單時,對訂單的處理必須要在三秒內完成,並把結果呈現給使用者知道!

Scalability
描述SuD對於需求的吞吐量,也就是在同一時間單位可同時處理多少需求,同時又能滿足Performance需求;例如,客戶希望SuD有每秒鐘可以同時處理一千位使用者的需求,又能滿足三秒鐘內回覆給使用者知道的能力!

Reliability
描述SuD對於交易處理的完整性與一致性;例如,客戶當然對於SuD保存客戶資料和交易資料相當重視;另外一方面,對於SuD所產生出來的log檔案,其數量可能是最多的,但客戶可能對其儲存的完整性與一致性的要求,相對就沒這麼高;所以對於兩者資料的儲存方式有機會可以採取不同的作法

Availability
描述SuD可以一直提供服務的程度;像是Amozon的EC2服務,保證可以在訂閱之後的365天內,提供99.95%的Availability,換句話說,每年大概約有四個小時,服務會有無法提供的可能性

Security
描述SuD提供的安全性機制;通常客戶會要求SuD,對於使用者敏感資料操作必須要提供SSL連線方式;另外也可能會要求儲存在資料庫的使用者密碼,應該要使用演算法加密,防止可以存取資料庫的相關人員盜竊

實務經驗分享
takeshi在實務上的經驗是,通常系統分析師(System Analyst,SA)在跟客戶窗口搜集需求時,往往都聚焦在功能性需求,而對非功能性需求都比較少關注;當系統進入使用者接受度測試(User Acceptance Test)時,非功能性需求的瓶頸才被關注,然而在此階段才去解決此問題,時間往往都已經不夠用;並且改善非功能性需求的問題,動到系統設計的可能性是高的;通常會演變成開發團隊要卯起來加班,最後就算SuD如期上線,但背後的系統設計可能已經受到影響,對往後的維護工作造成影響

所以對於非功能性需求的部分,應當及早釐清,並在系統開發的過程中,就要盡量做到非功能性的系統測試(System Test);以Java平台而言,takeshi建議可考慮使用類似像Apache JMeter等軟體,來作非功能性測試


SunTone Methodology
以上takeshi介紹的從三個思考框架來看待系統架構,其實可以使用三維的方塊(cube)來表達,如下圖所示
SunTone Cube
上圖的x軸就是指Tiers,y軸就是Layers,而z軸就是QoS;其實這是昇陽提出來的系統架構設計方法,叫做「SunTone Methodology」,有興趣的朋友可以參考這裡,或者是可以去上OO-226的課程,takeshi在這門課程學到不少東東說~


takeshi在選擇和設計系統架構時,就是依據此cube來作思考的,對takeshi相當有幫助,希望也對看到此篇文章的朋友們也有幫助囉 ^^