題圖 挺胸向前走加油鴨
最近在做專案,遇到個糾結的問題,專案該如何分層?
大部分專案通常會有 controller
service也稱(business)
DAO
這三層,介面請求流轉如下
一個介面邏輯通常由以下幾部分組成,許可權校驗、引數校驗、業務編排、資料庫操作、快取操作、第三方服務呼叫,那麼問題來了,這些操作都應該放在那一層呢?
在接手老專案的時候,會發現,大家寫法都很有自己的個性,有的小夥伴喜歡將業務編排放在controller
,也有的喜歡放在service
,有的會按照前輩的寫法,還有的隨心情,那舒服就放哪,百花齊放,這就會造成一個問題,隨著專案越來越大,業務將散落在各個層級,程式碼冗餘量增多,相同的功能出現多種寫法,這對後續的維護和擴充套件簡直就是無底大坑。
好的分層應該滿足一下幾點:
- 層級分明,職責分明
- 鏈路清晰,避免環形呼叫
- 良好的抽象和複用
- 業務介面足夠獨立,一個介面的修改不會影響其他功能
目前的糾結
許可權校驗、引數校驗、業務編排、資料庫操作、快取操作、第三方服務呼叫,這幾部分,許可權校驗、引數校驗自然是放在controller
,就像個門衛,將不合法的直接打回;資料庫操作自然是放在DAO
層,那麼業務編排、快取操作、第三方服務呼叫這幾部分該在哪裡呢?
嘗試一
將業務編排放在controller
,快取操作、服務呼叫等放在service
,與DAO
層的呼叫也放在service
層
好處:業務邏輯會比價清晰,很多資料、服務都通過service
層一個函式呼叫,controller
中的程式碼量也會少很多
壞處:一個業務介面的邏輯,會散落在controller
和service
,業務邏輯相對較分散;由於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
層,變為如下
controller
: 不在編寫業務邏輯,僅處理許可權、引數等校驗的工作,這一層的職責就是校驗合法性services
: 編寫具體業務的實現,這一層的大部分方法不具有複用性,為了防止互相影響和便於後期維護和擴充套件,所以方法應儘量保持相互獨立,同時,考慮到這一層的程式碼量會隨著業務擴充套件而不斷增多,所以services
需要根據情況進行適當的功能模組拆分,要避免單檔案過大,同時又要避免同一模組業務過於分散manager
: 對services
層的業務沉底抽象,並服務於services
層,將services
層頻繁出現的功能抽象出來,如快取操作、第三方服務呼叫,這一層將領域處理的口子收斂
總結
有句話,技術是服務於業務的,脫離了業務,技術將沒有任何價值。架構設計也如此,設計源於場景,每個階段的場景皆不同,所以設計也是在不斷的演變,經歷一輪輪的研討和重構後,才能誕生服務於業務的優秀架構。
層級的劃分沒有盡善盡美,適用於當前場景和未來可期的,適用於自己團隊,提高團隊生產力,那麼就是最棒的~
作為一枚前端小白,在高大上架構設計領域,還未看見其門檻,還有很長的路要走呀,哈哈~ 寫的有問題的地方,還請大夥幫忙指正,歡迎大家一起探討,一起進步~
向優秀的人學習,向優秀的人靠齊,加油ヾ(◍°∇°◍)ノ゙