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