軟體架構分層方法論
一般初創軟體,為快速上線,幾乎不考慮分層。但隨業務越發複雜,就會導致邏輯複雜、模組相互依賴、程式碼擴充套件性差等各種問題。
架構分層迫在眉睫。
1 什麼是架構分層?
軟體工程中常見的設計方式,將整體系統拆分成N個層次,每個層次有獨立的職責,多個層次協同提供完整的功能。
初學 JavaWeb 時一般要求設計成 MVC 架構。另外一種常見的分層方式是將整體架構分為
- 表現層(Web)
展示資料結果和接受使用者指令的,是最靠近使用者的一層; - 邏輯層(Service)
複雜業務的具體實現; - 資料訪問層(Dao)
主要處理和儲存之間的互動。
這就可以隔離關注點,讓不同的層專注做不同的事情。其它分層案例,比如OSI網路七層模型,TCP/IP協議網路四層模型。
2 分層有什麼好處?
簡化設計
各司專職,而不必將自己活成全才。
高複用
比如在設計某系統時,發現某層具有通用性,就可把它抽取獨立出來,在設計其它系統時使用。
橫向擴充套件
可以讓我們更容易做橫向擴充套件。如果系統沒有分層,當流量增加時我們需要針對整體系統來做擴充套件。但是,如果我們按照上面提到的三層架構將系統分層後,就可以針對具體的問題來做細緻的擴充套件。
比如業務邏輯裡面包含有比較複雜的計算,導致CPU成為效能的瓶頸,那這樣就可以把邏輯層單獨抽取出來獨立部署,然後只對邏輯層來做擴充套件,這相比於針對整體系統擴充套件所付出的代價就要小的多了。
架構分層究竟和高併發設計的關係是怎樣的?我們知道橫向擴充套件是高併發設計思想之一,既然架構分層可方便橫向擴充套件, 那麼高併發系統一定是分層的。
3 如何架構分層?
關鍵在於理清層次邊界。
若按三層架構分層,邊界不就很容易界定嗎?
是的沒毛病,當業務邏輯簡單時,層次間邊界的確清晰,開發新功能時也知道把程式碼往哪寫。但當業務邏輯越來越複雜,邊界也會變得模糊。
3.1 案例
任一系統都有使用者模組,比如返回使用者資訊的介面,它呼叫邏輯層的GetUser方法,GetUser方法又和User DB互動獲取資料,就像下圖左邊展示的樣子。
這時,產品提出一個需求,在APP中展示使用者資訊的時候,若使用者不存在,那麼要自動給使用者建立一個使用者。同時,要做一個HTML5頁面保留之前的邏輯,即不需要建立使用者。這時邏輯層的邊界就變得不清晰,表現層也承擔了一部分的業務邏輯(將獲取使用者和建立使用者介面關聯)。
3.2 主流分層職責
MVC架構的簡單性讓太多的人覺得專案工程結構理所應當就是這樣的,然後呢,一大堆的業務邏輯就隨意的堆砌在了service中,物件啥的,只是單純的資料傳輸作用,出現了用物件導向的語言,寫程式導向的程式的普遍現象。按照領域驅動設計的思路,最重要的還要有領域模型層。當然manage層這種方案也是一種思路,但是我覺得,這種方式,還不夠,必須有清晰的業務模型和合理的分層結構配合,才能更好的提現分層的作用。
終端顯示層
各端模板渲染並執行顯示的層。當前主要是 Velocity/framemaker渲染、js渲染、移動端展示等
開放介面層
將Service層方法封裝成開放介面,同時進行閘道器安全控制和流量控制等
Web層
主要是對訪問控制進行轉發,各類基本引數校驗,或者不復用的業務簡單處理等
Service層
業務邏輯層。呼叫manager層和dao層處理業務,即簡單的業務可以不抽取manager,直接呼叫dao。
業務類的校驗放在service層,一般性的引數校驗可以放在web層,這可以通用化。
Manager 層(通用業務處理層)
DDD中也叫領域層。
- 可以將原先Service層的一些通用能力下沉到這一層,比如與快取和儲存互動策略,中介軟體的接入。業務邏輯放在manager,service來編排manager的原子服務。
- 也可在這一層封裝對第三方介面的呼叫,比如呼叫支付服務,呼叫稽核服務等
該分層架構相比MVC主要就是增加了Manager層,它與Service層的關係:Manager層提供原子的服務介面,Service層負責依據業務邏輯來編排原子介面。
- 業務邏輯就是你的產品邏輯,比如建立使用者要具體做什麼。
- manager層的原子服務指的是實現單一功能的服務。
- 事務應該在service層
DAO層(資料持久層)
資料訪問層,與底層 MySQL、Oracle、HBase 等進行資料互動。快取可以放在儲存層。
外部介面或第三方平臺
包括其它部門 RPC 開放介面,基礎平臺,其它公司的 HTTP 介面
例如,Manager層提供建立使用者和獲取使用者資訊的介面,Service層負責將這兩個介面組裝起來。這樣就把原先散佈在表現層的業務邏輯都統一至Service層,每層邊界就清晰了。
比如做一個介面,可將實現放在service層。之後公司內部呼叫邏輯可放在web層。而哪一天公司要開放這個介面,可直接新抽象一層(一個新的服務),即開放平臺層!這樣的好處是,可以將本司使用和第三方使用做隔離。比如在提供服務時,為了保證自家介面效能,對開放平臺層做限流處理。
傳統公司很多是分層部署的,比如保險和金融。service和dao部署在比較嚴密的網路區域,controller層部署在一個較寬鬆的網路區域,對外提供服務。等於在網路上增加了一個緩衝區,來保證服務的安全;而且可以通過單向網路規範層級呼叫,controller可以呼叫服務層,而服務層是不能呼叫web層的。
如果將資料訪問層單獨部署,比如拆分為單獨的rpc服務,當然這樣拆分粒度比較細。controller就是對外的門面,呼叫單獨的服務層
- 可以為後期服務運維降低成本
- 可以提高資料訪問層的複用度(資料訪問層對外提供API,其他層的應用通過API方式與資料庫進行互動),三來可以遮蔽各個資料庫實現的具體細節。
3.3 層間依賴
資料流轉只能在相鄰層間。以三層架構為例,資料從表示層進入後一定要流轉到邏輯層,做業務邏輯處理,然後流轉到資料訪問層和DB互動。但若業務邏輯很簡單,可否從表示層直接到資料訪問層,甚至直接讀DB?
功能上是可以的,但從長遠架構設計考慮,這會造成層級呼叫混亂,比如一旦DB地址變更,就需更改多層,這就失去了分層價值,且維護或重構都是災難。
4 架構分層的缺陷
4.1 增加程式碼複雜度
原本可在接收請求後直接查詢DB獲得結果,卻非要在中間多層設計,每層只簡單地做資料傳遞。
有時增加一個小需求,可能還需更改所有層的程式碼,增加了開發成本,也增加了除錯複雜度,增加了與其它模組負責人的溝通成本。
4.2 效能損耗
若每層獨立部署,層間通過網路互動,那多層架構勢必會在效能上有所損耗。
那是否還要選擇架構分層呢?肯定的。
你要知道,任何的方案架構都是有優勢有缺陷的,天地尚且不全何況我們的架構呢?分層架構固然會增加系統複雜度,也可能會有效能的損耗,但是相比於它能帶給我們的好處來說,這些都是可以接受的,或者可以通過其它的方案解決的。我們在做決策的時候切不可以偏概全,因噎廢食。
5 總結
分層架構是軟體設計思想的外在體現,是一種實現方式。一些軟體設計原則都在分層架構中有所體現。
比方單一職責原則規定每個類只有單一的功能,在這裡可引申為每層擁有單一職責,且層與層之間邊界清晰;
迪米特法則原意是一個物件應當對其它物件儘可能少的瞭解,在分層架構的體現是資料的互動不能跨層,只能在相鄰層之間進行;
開閉原則要求軟體對擴充套件開放,對修改關閉。它的含義其實就是將抽象層和實現層分離,抽象層是對實現層共有特徵的歸納總結,不可修改,但具體實現可無限擴充套件,隨意替換。
參考
- 《阿里巴巴Java開發手冊》
相關文章
- 嵌入式軟體架構設計-程式分層架構
- 軟體架構設計原則和模式(上):分層架構設計架構模式
- 三層架構及分層架構
- 都說軟體架構要分層、分模組,具體應該怎麼做(二)架構
- 軟體架構分類(轉載)架構
- 論軟體系統架構風格架構
- 分層架構和SOA架構
- 論軟體架構設計及應用架構
- 軟考論文論湖倉一體架構及其應用架構
- 架構設計方法論架構
- 前端架構思想:聚類分層前端架構聚類
- 4+2 分層架構 - Ricardo架構
- 三層架構--理論與實踐架構
- 軟體架構與架構師架構
- 軟體架構1.什麼是軟體架構架構
- FD.io VPP軟體架構(一):vppinfra(基礎結構層)架構
- 架構之:軟體架構漫談架構
- 軟體架構師架構
- 《恰如其分的軟體架構》筆記摘要架構筆記
- .NET應用架構設計—重新認識分層架構(現代企業級應用分層架構核心設計要素)應用架構
- 架構分層的小糾結-層級該如何劃分與定位?架構
- 軟體架構模式之微服務架構架構模式微服務
- 軟體架構風格——規則架構架構
- 多層架構的討論,歡迎拍磚架構
- 資料倉儲架構分層設計架構
- 基於分層的token架構設計架構
- <ddd--領域驅動設計學習>討論--------分層架構架構
- iOS應用架構談:架構設計的方法論iOS應用架構
- 前端架構設計的方法論前端架構
- 架構製圖:工具與方法論架構
- 軟體架構簡介架構
- 軟體架構入門架構
- 軟體架構設計架構
- 軟體構架師之路
- 軟體架構與敏捷架構敏捷
- 伺服器架構系統軟體簡單分類伺服器架構
- 軟體體系結構:二維分層、模組化和開放平臺
- 架構設計 | 分散式體系下,服務分層監控策略架構分散式