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開發手冊》