你的項目應該如何分層?

1.背景

提及應用分層,大部分人都會認爲這個不是很簡單嘛 就controller,service, mapper三層。看起來簡單,不少人其實並無把他們職責劃分開,在不少代碼中,controller作的邏輯比service還多,service每每當成透傳了,這實際上是不少人開發代碼都沒有注意到的地方,反正功能也能用,至於放哪無所謂唄。這樣每每形成後面代碼沒法複用,層級關係混亂,對後續代碼的維護很是麻煩。java

的確在這些人眼中分層只是一個形式,前輩們的代碼這麼寫的,其餘項目代碼這麼寫的,那麼我也這麼跟着寫。可是在真正的團隊開發中每一個人的習慣都不一樣,寫出來的代碼必然帶着本身的標籤,有的人習慣controller寫大量的業務邏輯,有的人習慣在service中之間調用遠程服務,這樣就致使了每一個人的開發代碼風格徹底不一樣,後續其餘人修改的時候,一看,我靠這我的寫的代碼和我日常的習慣徹底不一樣,修改的時候究竟是按着本身之前的習慣改,仍是跟着前輩們走,這又是個艱難的選擇,選擇一旦有誤差,你的後輩又維護你的代碼的時候,恐怕就要罵人了。git

因此一個好的應用分層須要具有如下幾點:github

  • 方便後續代碼進行維護擴展。
  • 分層的效果須要讓整個團隊都接受
  • 各個層職責邊界清晰

2.如何進行分層

2.1阿里規範

在阿里的編碼規範中約束的分層以下:數據庫

這裏寫圖片描述

開放接口層:可直接封裝 Service 方法暴露成 RPC 接口;經過 Web 封裝成 http 接口;進行 網關安全控制、流量控制等。緩存

終端顯示層:各個端的模板渲染並執行顯示的層。當前主要是 velocity 渲染,JS 渲染, JSP 渲染,移動端展現等。安全

Web 層:主要是對訪問控制進行轉發,各種基本參數校驗,或者不復用的業務簡單處理等。app

Service 層:相對具體的業務邏輯服務層。框架

Manager 層:通用業務處理層,它有以下特徵:1. 對第三方平臺封裝的層,預處理返回結果及轉化異常信息;2. 對Service層通用能力的下沉,如緩存方案、中間件通用處理;3. 與DAO層交互,對多個DAO的組合複用。學習

DAO 層:數據訪問層,與底層 MySQL、Oracle、Hbase 進行數據交互。優化

阿里巴巴規約中的分層比較清晰簡單明瞭,可是描述得仍是過於簡單了,以及service層和manager層有不少同窗仍是有點分不清楚之間的關係,就致使了不少項目中根本沒有Manager層的存在。下面介紹一下具體業務中應該如何實現分層

2.2優化分層

從咱們的業務開發中總結了一個較爲的理想模型,這裏要先說明一下因爲咱們的rpc框架選用的是thrift可能會比其餘的一些rpc框架例如dubbo會多出一層,做用和controller層相似 這裏寫圖片描述

1.最上層controller和TService是咱們阿里分層規範裏面的第一層:輕業務邏輯,參數校驗,異常兜底。一般這種接口能夠輕易更換接口類型,因此業務邏輯必需要輕,甚至不作具體邏輯。

2.Service:業務層,複用性較低,這裏推薦每個controller方法都得對應一個service,不要把業務編排放在controller中去作,爲何呢?若是咱們把業務編排放在controller層去作的話,若是之後咱們要接入thrift,咱們這裏又須要把業務編排在作一次,這樣會致使咱們每接入一個入口層這個代碼都得從新複製一份以下圖所示: 這裏寫圖片描述

這樣大量的重複工做一定會致使咱們開發效率降低,因此咱們須要把業務編排邏輯都得放進service中去作: 這裏寫圖片描述

3.Mannager:可複用邏輯層。這裏的Mannager能夠是單個服務的,好比咱們的cache,mq等等,固然也能夠是複合的,當你須要調用多個Mannager的時候,這個能夠合爲一個Mannager,好比邏輯上的連表查詢等。若是是httpMannager或rpcMannager須要在這一層作一些數據轉換

4.DAO:數據庫訪問層。主要負責「操做數據庫的某張表,映射到某個java對象」,dao應該只容許本身的Service訪問,其餘Service要訪問個人數據必須經過對應的Service。

3.分層領域模型的轉換

在阿里巴巴編碼規約中列舉了下面幾個領域模型規約:

  • DO(Data Object):與數據庫表結構一一對應,經過DAO層向上傳輸數據源對象。
  • DTO(Data Transfer Object):數據傳輸對象,Service或Manager向外傳輸的對象。
  • BO(Business Object):業務對象。由Service層輸出的封裝業務邏輯的對象。
  • AO(Application Object):應用對象。在Web層與Service層之間抽象的複用對象模型,極爲貼近展現層,複用度不高。
  • VO(View Object):顯示層對象,一般是Web向模板渲染引擎層傳輸的對象。
  • Query:數據查詢對象,各層接收上層的查詢請求。注意超過2個參數的查詢封裝,禁止使用Map類來傳輸。
層次 領域模型
Controller/TService VO/DTO
Service/Manager AO/BO
DAO DO

每個層基本都本身對應的領域模型,這樣就致使了有些人過於追求每一層都是用本身的領域模型,這樣就致使了一個對象可能會出現3次甚至4次轉換在一次請求中,當返回的時候一樣也會出現3-4次轉換,這樣有可能一次完整的請求-返回會出現不少次對象轉換。若是在開發中真的按照這麼來,恐怕就別寫其餘的了,一天就光寫這個重複無用的邏輯算了吧。

因此咱們得采起一個折中的方案: 1.容許Service/Manager能夠操做數據領域模型,對於這個層級來講,原本本身作的工做也是作的是業務邏輯處理和數據組裝。 2.Controller/TService層的領域模型不容許傳入DAO層,這樣就不符合職責劃分了。 3.同理,不容許DAO層的數據傳入到Controller/TService.

3.總結

總的來講業務分層對於代碼規範是比較重要,決定着之後的代碼是否可複用,是否職責清晰,邊界清晰,因此搞清楚這一塊也比較重要。

固然這種分層其實見仁見智,團隊中的全部人的分層習慣也不一樣,因此很難權衡出一個標準的準則,總的來講只要知足職責邏輯清晰,後續維護容易,就是好的分層。

最後這篇文章被我收錄於JGrowing-Java設計篇,一個全面,優秀,由社區一塊兒共建的Java學習路線,若是您想參與開源項目的維護,能夠一塊兒共建,github地址爲:https://github.com/javagrowing/JGrowing 麻煩給個小星星喲。

若是你們以爲這篇文章對你有幫助,你的關注和轉發是對我最大的支持,O(∩_∩)O:

相關文章
相關標籤/搜索