1. 程式人生 > >什麽是三層架構?你真的理解分層的意義嗎?

什麽是三層架構?你真的理解分層的意義嗎?

靜下心來 感到 面向過程 基於 用不了 加班 str transacti context

首先聲明,本文並不是介紹什麽是N層架構,然後給張分層圖,最後來一堆代碼結束。本文主要是對分層過程中常常讓人感到困惑地方的思考,從個人經驗角度出發,努力嘗試來解決這些困惑,歡迎拍磚!
開始
我們先從一幅大家眼熟能詳的圖開始:
技術分享圖片
這是應用開發人員最熟悉的N層架構圖,其中:
數據訪問層:應用程序中全權負責與數據存儲對話並持久保存和檢索業務對象的層。通常,數據訪問層包括所有的CRUD 方法與查詢機制,使得業務邏輯層能夠針對任何給定的條件檢索對象。
業務邏輯層:它包含定義和處理復雜業務功能的所有規則、工作流和驗證邏輯,設計軟件以滿足這些復雜的功能;困惑最多的地方就是這一層。
應用層:封裝業務模型,並為所有相關的應用程序提供接口。關於應用層,有一個十分讓人困惑的地方,後面會詳細說明。
這是三層的簡單定義,當開發者看到這些定義的時候,基本都會有這麽一個感覺:哦!也就這麽回事。可是在實際編寫代碼時,尤其是隨著項目代碼量越來越多,業務越來越復雜的時候,會明顯覺得:
要改這個業務,又要去改數據層的CRUD,太難受了;
這個操作不分層,我一個函數調用就搞定了,為什麽一分層,我要嵌套這麽多層,太惡心了;
...
當你有這些感覺的時候,請停下手頭上的工作,思考一下,有沒有因為遇到下面這些情況讓你感覺到困惑。
困惑1:層之間的依賴關系


技術分享圖片
該圖引用自jesse liu的博客(如有侵權請告知,我會在第一時間修改,實在是懶得畫),我覺得很形象。上面是常見的三層中的依賴關系。下面是在領域驅動設計下的依賴關系。不要小看這個圖,可以肯定的是90%以上的開發人員在開發過程中對N層架構的依賴關系是這樣的,哪怕是在使用領域驅動進行設計時,無形中也擺脫不了這種依賴關系。初學者一般覺得這種依賴關系很正常啊?本來就應該是這樣的。造成這種思想的根本原因是初學者通常覺得DAL層(或DDD中的repository)可以方便給其他系統調用呀?不就實現復用了嗎?我的BLL層也可以....

打住,請打住!!你的BLL層能復用?你的BLL層已經在依賴DAL了。

DAL能復用?是能復用。但,對於特定的開發系統來說,DAL層的復用毫無意義。你會把圖書管理系統中的DAL復用給加班系統嗎?除了能復用最基本的ADO操作之外,你什麽都復用不了。
所以,層之間的引用應該設計成這樣的:
技術分享圖片

好吧,圖還是jesse liu的。這個圖很形象的說明了我們該如何處理層之間的依賴關系。因為系統中真正可以復用的其實是這樣的BLL層。它不依賴任何層,對於特定的系統來說,無論你的數據庫變了,界面變了,但核心的業務其實是比較穩定的。其實該實現方式的核心思想就是大名鼎鼎的依賴倒置。實現方式可以使用反射或IOC等進行,可以參考dalbll.com其他小夥伴的文章或我的另一文:通用數據采集平臺,從架構到代碼 。

困惑2:業務邏輯層實現方式的選擇
業務邏輯層實現方式有三種:事務腳本、活動記錄及領域模型。現在dalbll.com裏面大興DDD之風,對領域驅動設計推崇倍至,你要是和他說其實這個用事務腳本封裝一下,那個來點活動記錄集搞搞就行了。保證他立馬噴的你體無完膚。常言道:存在即合理。前兩種實現模式自打程序設計出現以來,有著悠久的歷史。這裏我們簡單介紹一下它們及說明一下他們的適用場景。

事務腳本(Transaction Script)

名字叫的很玄乎,其實說直白點它就是使用一系列功能函數來實現系統的業務邏輯。它遵循面向過程的開發方式,而不是面向對象的方法。核心思想是為每個業務創建一個過程,每個過程都包含完成業務事務所需要的所有業務邏輯,包括從工作流、業務規則和驗證檢查到數據庫持久化保存的所有內容。

從各大經典教材上來看,它適用於具有很少邏輯或沒有多少邏輯的簡單應用程序,在用戶界面中實現所有的業務邏輯。在實際操作中,將應用程序分成小的功能模塊,分別將它們實現成用戶界面,並在其中嵌入業務規則。這時采用自動化程度最高的用戶界面創建工具(比如ASP.NET中的服務器控件)和可用的可視化編程工具進行開發。

活動記錄(Active Record)
該模式對於數據庫中的每個表都存在一個對應的業務對象。業務對象代表數據表中的一行,在業務對象中包含數據和行為,同時包含用於持久化對象的方式及添加新實例和查找數據集合的方法。

適用於業務只是在數據庫之上加一個顯示處理界面。在有些精典書籍中提出,以EF與linqtosql為代表的數據訪問對象模式(DAO)最適合的就是這種場景。它們都通過一個數據上下文(DbContext)作為入口,實現業務對象與數據表的對應。但個人認為EF(linqtosql用的較少)經過多個版本的演化,已經擺脫了一對一映射的限制。完全適用於領域模型。

領域模型(Domain)
該實現模式與活動記錄非常相似,它與活動記錄集的主要差異就是:領域模型的業務實體不知道如何持久化自身,且數據模型與業務模型之間並不是一定要存在一對一映射的關系。
關於該模型的文章有很多。這裏就不詳細介紹。它適用於對復雜業務邏輯進行建模,至於這個復雜業務邏輯的標準是什麽,我也在探索中。我想有些開發者使用它是為了表現自己的技術能力。其實完全沒有必要。個人覺得理解它的思想就行,在一些小項目中能不用盡量不要去用。折騰自己也折騰同事。

這裏要特別說明一點的是:因為業務實體並不知道自己如何持久化,所以領域模式依賴於ORM或Repository模式來持久化。我們在這裏的依賴並不是在設計時領域要依賴下面的數據操作,而是領域層最終要靠ORM或Repository來實現數據存儲的讀寫。DDD設計中最大的爭論也就此展開:Repository模式到底有沒有必要,尤其在使用EF的情況下。我們單獨為此開一個專題。

困惑3:Repository模式
Repository的爭論曾經在園子深挖DDD的幾位牛人圈子裏面持續了一段時間:初探領域驅動設計(2)Repository在DDD中的應用。
Repository 倉儲,你的歸宿究竟在哪?(一)-倉儲的概念
尤其是當用EF實現Repository時,爭論可以達到慘烈的程度:
dalbll的大牛們,被你們害慘了,Entity Framework從來都不需要去寫Repository設計模式
那段時間我也是看著他們的文章,陪著他們一起困惑,一起糾結。但某個風高月黑的晚上。我突然間有了以下想法:

領域模型的業務實體不知道如何持久化自身,如果我們想把這些實體存儲到電腦中,我們必定需要一個可以持久化的方法。方法太多了,ADO.NET、linqtosql、EF等等,於是我們提取一個數據化的接口在業務邏輯層,取個名字叫Ixx..叫什麽呢?Martin Fowler大大說叫IRepository吧,於是Repository模式就出來了。記住:這裏在業務邏輯層裏面添加的是接口,而不是實現,這很重要!

其實我贊同Leo C.W在那篇慷慨激昂的文章裏面提到的觀點:EntityFramework 本身就是基於Repository設計的,我也贊同他說的那些EF+Repository包裹後的缺點。但,這不足以讓我們拋棄Repository,哪怕是和EF做搭檔。當他們兩個一起工作的時候,Repository可以理解為設計模式中的適配器模式。為了保持整個設計的接口統一,為了協調領域和數據映射層。因為如果在業務邏輯層裏面直接使用EF,你的領域就已經不再是純潔的領域。所以我在上面一段結尾的時候強調了在業務邏輯層裏面添加的是IRepository接口。

而且就像我在困惑2中提到的一樣,當你選擇使用領域模型的時候,就可以假定你所處理的業務邏輯比較復雜,而且需要兼顧擴展性(比如數據庫更換),所以Repository有存在的意義。如果你的項目屬於短期的項目,或者說你不用考慮更換數據訪問層,你大可直接選擇活動記錄模式,那麽如果你不想用Repository,那就不用。不然直白點說:你用領域就是為了裝那個啥。
技術分享圖片
困惑4:應用層
很多人覺得這一層很簡單,就是處於界面與業務邏輯之間的一個外觀模式。但,就像田園裏的蟋蟀說的一樣:

有時候我們在領域驅動設計的時候最容易混淆的就是應用層和領域層,網上關於領域層和應用層的定義概念一搜一大把,你可能也會說幾句,比如什麽應用層是很薄的一層,主要工作是協調任務的等等,但是實踐起來呢?用代碼表示就蒙了。
對於某個XXService,你會無比糾結它到底是放在業務邏輯層中還是應用層中,尤其是像我這種對代碼整齊有潔癖的人,更是痛不欲生。蟋蟀後來提出:
應用層很薄,所做的工作是:
1.發起一個請求
2.確認處理結果
3.提交工作單元
看到他的這個觀點,瞬間讓我想到《ASP.NET設計模式》這本書中的一個觀點:Document Message消息傳送模式。作者在應用層裏面唯一做的一件事情就是把所有的界面邏輯封裝成一個Request,然後通過業務邏輯層中的功能組合計算出一個Response,返回給界面(詳見該書6.3.2章節)。
技術分享圖片
綜合上面的兩點經驗,也算是給我們指明了一條怎樣使應用層“變薄”的出路了。

總結
真正對分層進行研究是因為公司裏面一個水務集團的項目,數據量業務邏輯都相對比較復雜,當時硬著頭皮要求使用領域驅動設計,結果很悲慘。項目一半的時候大家都被折磨瘋了,那時才知道我們離真正的建模差距有多大。我們以前的分層,無非是借著面向對象的外殼,使用類來進行面向過程的分層罷了。中間為了設計模式而設計模式,為了分層而分層。後來項目雖然完工,但遠沒達到我心目中的期望。於是靜下心來,看了園子裏面很多這方面的文章,記錄下些許心得。還請各位大大不吝指教,感謝!

原文轉載自:http://www.dalbll.com/Group/Topic/ArchitecturedDesign/4971

什麽是三層架構?你真的理解分層的意義嗎?