架構的那些事1--分層框架
分層架構是一種很常見的架構模式,它也叫N層架構
。
這種架構是大多數JaveEE應用的實際標準,因此很多的架構師,設計師,還有程式設計師都知道它。
許多傳統IT公司的組織架構和分層模式十分的相似。
所以它很自然的成為大多數應用的架構模式。
模式分析
分層架構模式裡的元件被分成幾個平行的層次,每一層都代表了應用的一個功能(展示邏輯或者業務邏輯)。
儘管分層架構沒有規定自身要分成幾層幾種,大多數的結構都分成四個層次:展示層
,業務層
,持久層
,和資料庫層
。
如表1-1,有時候,業務層和持久層會合併成單獨的一個業務層,尤其是持久層的邏輯繫結在業務層的元件當中。
因此,有一些小的應用可能只有3層
一些有著更復雜的業務的大應用可能有5層或者更多的分層。
分層架構中的每一層都著特定的角色和職能。
- 舉個例子,
展示層負責處理所有的介面展示以及互動邏輯,
業務層負責處理請求對應的業務。
架構裡的層次是具體工作的高度抽象,它們都是為了實現某種特定的業務請求。
- 比如說
展示層並不需要關心怎樣得到使用者資料,它只需在螢幕上以特定的格式展示資訊。
業務層並不關心要展示在螢幕上的使用者資料格式,也不關心這些使用者資料從哪裡來。它只需要從持久層得到資料,執行與資料有關的相應業務邏輯,然後把這些資訊傳遞給展示層。
分層架構的一個突出特性是元件間關注點分離 (separation ofconcerns)
一個層中的元件只會處理本層的邏輯。
- 比如說
展示層的元件只會處理展示邏輯,
業務層中的元件只會去處理業務邏輯。
多虧了元件分離,讓我們更容易構造有效的角色和強力的模型。
這樣應用變的更好開發,測試,管理和維護。
關鍵概念
注意表1-2中每一層都是封閉的。這是分層架構中非常重要的特點。
這意味request必須一層一層的傳遞。
- 舉個例子
從展示層傳遞來的請求首先會傳遞到業務層,
然後傳遞到持久層,最後才傳遞到資料層。
那麼 為什麼不允許展示層直接訪問資料層呢 ?
如果只是獲得以及讀取資料,展示層直接訪問資料層,比穿過一層一層來得到資料來的快多了。
這涉及到一個概念:
層隔離。
層隔離就是說架構中的某一層的改變不會影響到其他層:
這些變化的影響範圍限於當前層次。
如果,展示層能夠直接訪問持久層了,假如持久層中的SQL變化了,這對業務層和展示層都有一定的影響。
這隻會讓應用變得緊耦合,元件之間互相依賴。這種架構會非常的難以維護。
從另外一個方面來說,
分層隔離使得層與層之間都是相互獨立的,架構中的每一層的互相瞭解都很少。
為了說明這個概念的牛逼之處,想象一個超級重構,把展示層從JSP換成JSF。
假設展示層和業務層的之間的聯絡保持一致,業務層不會受到重構的影響,它和展示層所使用的介面架構完全獨立。
- 不便之處
然而封閉的架構層次也有不便之處,有時候也應該開放某一層
。
如果想往包含了一些由業務層的元件呼叫的普通服務元件的架構中新增一個分享服務層。
在這個例子裡,新建一個服務層通常是一個好主意,因為從架構上來說,它限制了分享服務訪問業務層(也不允許訪問展示層)。
如果沒有隔離層,就沒有任何架構來限制展示層訪問普通服務,難以進行許可權管理。
在這個例子中,
新的服務層是處於業務層之下的,展示層不能直接訪問這個服務層中的元件。
但是現在業務層還要通過服務層才能訪問到持久層,這一點也不合理。
這是分層架構中的老問題了,解決的辦法是開放某些層。
如表1-3所示,服務層現在是開放的了。請求可以繞過這一層,直接訪問這一層下面的層。
既然服務層是開放的,業務層可以繞過服務層,直接訪問資料持久層。這樣就非常合理。
開放和封閉層的概念確定了架構層和請求流之間的關係,
並且給設計師和開發人員提供了必要的資訊理解架構裡各種層之間的訪問限制。
如果隨意的開放或者封閉架構裡的層,整個專案可能都是緊耦合,一團糟的。
以後也難以測試,維護和部署。
示例
為了演示分層架構是如何工作的,想象一個場景,如表1-4,使用者發出了一個請求要獲得客戶的資訊。
黑色的箭頭
是從資料庫中獲得使用者資料的請求流,紅色箭頭
顯示使用者資料的返回流的方向。
在這個例子中,
使用者資訊由客戶資料和訂單陣列組成(客戶下的訂單)。使用者介面只管接受請求以及顯示客戶資訊。
它不管怎麼得到資料的,或者說得到這些資料要用到哪些資料表。
如果使用者介面接到了一個查詢客戶資訊的請求,它就會轉發這個請求給使用者委託(Customer Delegate)模組。
這個模組能找到業務層裡對應的模組處理對應資料(約束關係)。
業務層裡的customer object聚合了業務請求需要的所有資訊(在這個例子裡獲取客戶資訊)。
這個模組呼叫持久層中的customer dao 來得到客戶資訊,呼叫order dao來得到訂單資訊。
這些模組會執行SQL語句,然後返回相應的資料給業務層。
當 customer object收到資料以後,它就會聚合這些資料然後傳遞給customer delegate,然後傳遞這些資料到customer screen 展示在使用者面前。
從技術的角度來說,有很多的方式能夠實現這些模組。
比如說在Java平臺中,customer screen 對應的是 (JSF) Java Server Faces ,用 bean 元件來實現 customer
delegate。用本地的Spring bean或者遠端的EJB3 bean 來實現業務層中的customer object。
上例中的資料訪問可以用簡單的POJP’s(Plain Old Java Objects),或者可以用MyBatis,還可以用JDBC或者Hibernate 查詢。Microsoft平臺上,customer screen能用 .NET 庫的ASP模組來訪問業務層中的C#模組, 用ADO來實現使用者和訂單資料的訪問模組。
注意事項
分層架構是一個很可靠的架構模式。它適合大多數的應用。
如果你不確定在專案中使用什麼架構,分層架構是再好不過的了。
然後,從架構的角度上來說,選擇這個模式還要考慮很多的東西。
- 第一個要注意的就是
汙水池反模式(architecture sinkhole anti-pattern)。
在這個模式中,請求流只是簡單的穿過層次,不留一點雲彩,或者說只留下一陣青煙。
比如說介面層響應了一個獲得資料的請求。響應層把這個請求傳遞給了業務層,業務層也只是傳遞了這個請求到持久層,持久層對資料庫做簡單的SQL查詢獲得使用者的資料。這個資料按照原理返回,不會有任何的二次處理,返回到介面上。
每個分層架構或多或少都可能遇到這種場景。
關鍵在於這樣的請求有多少。80-20原則可以幫助你確定架構是否處於反汙水模式。
大概有百分之二十的請求僅僅是做簡單的穿越,百分之八十的請求會做一些業務邏輯操作。然而,
如果這個比例反過來,大部分的請求都是僅僅穿過層,不做邏輯操作。那麼開放一些架構層會比較好。
不過由於缺少了層次隔離,專案會變得難以控制。
模式分析
下面的的表裡分析了分層架構的各個方面。
整體靈活性
評級:低
分析:總體靈活性是響應環境變化的能力。
儘管分層模式中的變化可以隔絕起來,想在這種架構中做一些也改變也是並且費時費力的。
分層模式的笨重以及經常出現的元件之間的緊耦合是導致靈活性降低的原因。易於部署
評級:低
分析:這取決於你怎麼釋出這種模式,釋出程式可能比較麻煩,尤其是很大的專案。
一個元件的小小改動可能會影響到整個程式的釋出(或者程式的大部分)。釋出必須是按照計劃,
在非工作時間或者週末進行釋出。因此。分層模式導致應用釋出一點也不流暢,在釋出上降低了靈活性
。可測試性
評級:高
分析:因為元件都處於各自的層次中,可以模擬其他的層,或者說直接去掉層,所以分層模式很容易測試。
開發者可以單獨模擬一個展示元件,對業務元件進行隔絕測試。還可以模擬業務層來測試某個展示功能。效能
評級:低
分析:儘管某些分層架構的效能表現的確不錯,但是這個模式的特點導致它無法帶來高效能。
因為一次業務請求要穿越所有的架構層,做了很多不必要的工作。伸縮性
評級:低
分析:由於這種模式以緊密耦合的趨勢在發展,規模也比較大,用分層架構構建的程式都比較難以擴充套件。
你可以把各個層分成單獨的物理模組或者乾脆把整個程式分成多個節點來擴充套件分層架構,但是總體的關係過於緊密,這樣很難擴充套件。易開發性
評級:容易
分析:在開發難度上面,分層架構得到了比較高的分數。
因為這種架構對大家來說很熟悉,不難實現。
大部分公司在開發專案的都是通過層來區分技術的,這種模式對於大多數的商業專案開發來說都很合適。
公司的組織架構和他們軟體架構之間的聯絡被戲稱為”Conway’slaw”。你可以Google一下查查這個有趣的聯絡