架構分層的小糾結-層級該如何劃分與定位?

小黎也發表於2018-08-19

題圖 挺胸向前走加油鴨

最近在做專案,遇到個糾結的問題,專案該如何分層? 大部分專案通常會有 controller service也稱(business) DAO這三層,介面請求流轉如下

專案分層

一個介面邏輯通常由以下幾部分組成,許可權校驗、引數校驗、業務編排、資料庫操作、快取操作、第三方服務呼叫,那麼問題來了,這些操作都應該放在那一層呢?

在接手老專案的時候,會發現,大家寫法都很有自己的個性,有的小夥伴喜歡將業務編排放在controller,也有的喜歡放在service,有的會按照前輩的寫法,還有的隨心情,那舒服就放哪,百花齊放,這就會造成一個問題,隨著專案越來越大,業務將散落在各個層級,程式碼冗餘量增多,相同的功能出現多種寫法,這對後續的維護和擴充套件簡直就是無底大坑。

好的分層應該滿足一下幾點:

  1. 層級分明,職責分明
  2. 鏈路清晰,避免環形呼叫
  3. 良好的抽象和複用
  4. 業務介面足夠獨立,一個介面的修改不會影響其他功能

目前的糾結

許可權校驗、引數校驗、業務編排、資料庫操作、快取操作、第三方服務呼叫,這幾部分,許可權校驗、引數校驗自然是放在controller,就像個門衛,將不合法的直接打回;資料庫操作自然是放在DAO層,那麼業務編排、快取操作、第三方服務呼叫這幾部分該在哪裡呢?

嘗試一

將業務編排放在controller,快取操作、服務呼叫等放在service,與DAO層的呼叫也放在service

好處:業務邏輯會比價清晰,很多資料、服務都通過service層一個函式呼叫,controller中的程式碼量也會少很多 壞處:一個業務介面的邏輯,會散落在controllerservice,業務邏輯相對較分散;由於controller中大量呼叫service中方法,導致一個service中的方法可能被多個controller呼叫,導致本來不相干的業務介面出現了交集,對後續的維護和擴充套件,留下了隱患

嘗試二

將業務編排都放在service中處理,controller許可權和引數校驗通過後,就直接呼叫service

好處:業務處理集中在service中,controller僅負責門衛 壞處:為避免環形呼叫,所以service間不能互相呼叫 service層的方法,這一限制,導致services沒法很好的抽象和複用,當某一塊業務越來越龐大的時候,對應的services就顯得臃腫了

阿里巴巴開發規範

為此找了阿里巴巴公開的Java開發手冊,阿里作為世界一流的大廠,它的標準是非常不錯的,哈哈,反正我是這麼覺得,雖然我們是node專案,但設計思想是通用的

因截圖在移動端看不清,所以直接引用阿里開發文件

(一) 應用分層

1.【推薦】圖中預設上層依賴於下層,箭頭關係表示可直接依賴,如:開放介面層可以依賴於 Web 層,也可以直接依賴於 Service 層,依此類推:

阿里巴巴開發規範

  • 開放介面層:可直接封裝 Service 方法暴露成 RPC 介面;通過 Web 封裝成 http 介面;進行閘道器安全控制、流量控制等。
  • 終端顯示層:各個端的模板渲染並執行顯示的層。當前主要是 velocity 渲染,JS 渲染,JSP 渲染,移動端展示等。
  • Web 層:主要是對訪問控制進行轉發,各類基本引數校驗,或者不復用的業務簡單處理等。
  • Service 層:相對具體的業務邏輯服務層。
  • Manager 層:通用業務處理層,它有如下特徵: 1)對第三方平臺封裝的層,預處理返回結果及轉化異常資訊; 2)對 Service 層通用能力的下沉,如快取方案、中介軟體通用處理; 3)與 DAO 層互動,對多個 DAO 的組合複用。
  • DAO 層:資料訪問層,與底層 MySQL、Oracle、Hbase 等進行資料互動。
  • 外部介面或第三方平臺:包括其它部門 RPC 開放介面,基礎平臺,其它公司的 HTTP 介面。

以上內容為引用阿里開發文件

開放介面層和請求處理層,可以理解為我們的controller層,作用是RPC和http介面封裝、安全流量控制、訪問控制轉發、引數校驗和不復用的業務簡單處理。

services層,用於處理具體的業務邏輯。

manager層,通用業務處理層,即services層的沉澱抽象,如快取方案、中介軟體處理、第三方服務封裝等,這一層可以服務於多個services

阿里的這個分層結構,我認為是比較清晰明瞭的,與比較自己的專案一比較,便發現自己專案少了manager這一層,根據阿里規範,我們進行層級優化~

層級優化

我們在嘗試二的基礎上加上manager層,變為如下

優化後的分層結構

  1. controller: 不在編寫業務邏輯,僅處理許可權、引數等校驗的工作,這一層的職責就是校驗合法性
  2. services: 編寫具體業務的實現,這一層的大部分方法不具有複用性,為了防止互相影響和便於後期維護和擴充套件,所以方法應儘量保持相互獨立,同時,考慮到這一層的程式碼量會隨著業務擴充套件而不斷增多,所以services需要根據情況進行適當的功能模組拆分,要避免單檔案過大,同時又要避免同一模組業務過於分散
  3. manager: 對services層的業務沉底抽象,並服務於services層,將services層頻繁出現的功能抽象出來,如快取操作、第三方服務呼叫,這一層將領域處理的口子收斂

總結

有句話,技術是服務於業務的,脫離了業務,技術將沒有任何價值。架構設計也如此,設計源於場景,每個階段的場景皆不同,所以設計也是在不斷的演變,經歷一輪輪的研討和重構後,才能誕生服務於業務的優秀架構。

層級的劃分沒有盡善盡美,適用於當前場景和未來可期的,適用於自己團隊,提高團隊生產力,那麼就是最棒的~

作為一枚前端小白,在高大上架構設計領域,還未看見其門檻,還有很長的路要走呀,哈哈~ 寫的有問題的地方,還請大夥幫忙指正,歡迎大家一起探討,一起進步~

向優秀的人學習,向優秀的人靠齊,加油ヾ(◍°∇°◍)ノ゙

參考文章

領域驅動設計到底難在哪?

你的專案應該如何正確分層?

阿里巴巴Java開發手冊

相關文章