在著手設計系統前,有一個更重要的工作,就是決定系統的架構。設計完成的類別也許已形成一個架構,也許沒有。其中的關鍵在於這些類別是否具備特定的角色,以及不同角色的類別之間,是否存在特定的互動關係。
設計者最常犯的錯誤,是沒有在設計類別之前,就先設計系統中可能會有的類別角色、每一種角色應該提供的特定作用,以及不同的角色之間互動的方式。
在這種情況下,設計者就像是煮了一碗牛肉麵,而碗裡的麵條彼此相互糾結,關係十分複雜。相形之下,有個舉世聞名卻又簡單清晰的軟體架構,就是Unix的系統架構,它是最佳示範。
Unix的系統架構設計,是最簡單清晰的示範
Unix將系統的運行畫分為核心(Kernel)以及外殼(Shell)。系統核心提供所有應用程式共通、需要作業系統提供服務的系統呼叫(System Calls),而處於外殼的應用程式除了執行自身的程式碼之外,同時利用作業系統所提供的系統呼叫,達成應用程式的用途。
我們還可以使用圖二的分層看待圖一的架構。
雖然這個分層架構只有兩層,但卻將「架構」的精神發揮到十足。更明確地陳述一個軟體架構應有的組成包括:
1. 制定系統中可能會有的角色
2. 每一種角色應該提供的特定作用
3. 不同的角色之間如何互動
在Unix的核心/外殼的架構中,程式碼有兩種角色,一種是處於核心的系統呼叫程式碼,另一種則是處於外殼的應用程式碼。系統呼叫程式碼負責提供作業系統應提供的服務,例如檔案處理、記憶體配置、行程執行緒的管理等。
而應用程式碼奠基於系統呼叫之上,實作自身應用所需的其餘程式碼。二者之間的關係十分單純,下層的程式碼完全做為上層程式碼的基礎之用,只有上層的程式碼會呼叫下層的程式碼,下層的程式碼絕不會反向呼叫上層的程式碼。
有層次的架構使軟體像房子,有了立體的高度
在Unix上使用C語言開發應用系統的人,對於圖三的架構絕不陌生。
相較於上述的架構,這個架構將核心之外的外殼部份拆成了兩層:應用程式及執行時期程式庫(Run-Time Library)。執行時期程式庫萃取應用程式在開發時常見的需求,將這些需求畫分到執行時期程式庫負責的範圍,使得程式人在開發時不需要浪費心力,撰寫相同或相似的程式碼。
此外,系統呼叫本身提供的介面相對低階,執行時期程式庫同時也包裝了作業系統的系統呼叫,使得開發者在運用系統呼叫時,能夠更便利。
但這個三層的架構並不會防止應用程式碼直接呼叫系統呼叫,在必要的時候,應用程式碼還是可以直接使用系統呼叫。
當我們開始分層畫分程式碼的角色,程式碼就有了「立體感」。在牛肉麵式的系統中,所有的程式碼都平躺在一塊(因為只有一層),當我們建立起分層時,軟體本身就像房子一樣,有了立體的高度。
分層架構需因應現況調整
分層式的架構是最廣為人所使用的軟體架構。在使用分層架構時,會依據應用系統本身的需求,決定需要的層次,一般來說,多數的程式可以採用下述的分層架構:
其中使用者介面層(User Interface Layer)負責呈現使用者操作介面、與使用者互動,將使用者的輸入傳遞至控制器層。而控制器層(Controller Layer)則接收使用者的輸入,實作商業邏輯協調領域層中程式碼的互動。領域層主要負責系統的資料模型。
資料存取層用來將資料儲存於永續的儲存媒介(例如檔案或資料庫),而系統層則扮演像是整合作業系統之系統呼叫,以及網路傳輸等作用。其中,使用者介面層、控制器層、以及領域層會隨著應用程式的不同而改變,而資料存取層以及系統層,經常會採用現成的程式庫或應用程式框架。
使用如此細緻的分層架構好處是,各層的角色定義得更精確,透過層層相疊的方式,將各層的相依性界定在受限的範圍內。例如,使用者介面層的程式碼,就不會直接碰觸到資料存取層的程式碼,二者之間並不存在相依性,日後即使資料存取的方式有所更動,甚至整個資料存取的方式完全抽換掉,也不會對使用者介面層的程式碼產生任何影響。
上述的分層方式,對應到不同的開發平臺,會有不同具體實現的技術。例如,以Java開發Web-Based的應用程式,你可能會選擇JSP加上Struts提供使用者介面層及控制器層、於領域層及資料存取層使用Hibernate、於系統層使用JDBC。
而這些選擇都只是可能的選項之一,在實務中,身為架構的設計者,會需要從各種選項中選擇出適合專案運用的技術。也許對你的專案而言,在領域層及資料存取層並不希望採用Hibernate,選擇EJB(Enterprise JavaBeans)的技術對你的專案來說,更為適合。
將系統畫分為適當的分層架構,有助於釐清系統中各組成的角色、責任、以及如何分工。也有助於降低系統中各組成之間的相依性,使得系統無論是在修改或是擴充時,都能降低影響的範圍。有些設計者,採用了諸如Struts、Hibernate等暗示被運用在分層架構中的技術,但本身並沒有遵守分層的責任,導致最後系統的架構,仍如一碗麵條彼此相互糾結的牛肉麵一樣,完全得不到分層的好處,這是需要格外注意的常見錯誤。
《作者簡介》王建興
清華大學資訊工程系的博士研究生,研究興趣包括電腦網路、點對點網路、分散式網路管理、以及行動式代理人,專長則是Internet應用系統的開發。曾參與過的開發專案性質十分廣泛而且不同,從ERP、PC Game到P2P網路電話都在他的涉獵範圍之內。
相關閱讀:
物件導向程式設計常見的錯誤(1)抽離作用重複的程式碼,重構品質
物件導向程式設計常見的錯誤(2)責任分配均衡才是健康的系統
物件導向程式設計常見的錯誤(4)Façade畫分子系統,可加速開發
物件導向程式設計常見的錯誤(5)工程化的考量不可走火入魔
熱門新聞
2025-01-13
2025-01-15
2025-01-14
2025-01-14
2025-01-13