細說業務邏輯

前言

      記得幾個月前,在一次北京博客園俱樂部的活動上,最後一個環節是話題自由討論。就是提幾個話題,然後大家各自加入感興趣的話題小組,進行自由討論。當時金色海洋同學提出了一個話題——“什麼是業務邏輯”。當時我和大家討論ASP.NET MVC的相關話題去了,就沒能加入“業務邏輯”組的討論,比較遺憾。

      其實,一段時間內,我腦子裏對“業務邏輯”的概念也是非常模糊的。但在不斷地閱讀、思考和實踐過程中,這個概念及其相關的內容纔在我腦子裏漸漸清晰。我想,很多朋友也許也對這個概念不是很瞭解,所以願意結合既有資料和自己的思考,總結一篇關於業務邏輯的概述性文章,一則與朋友們分享探討,二則也是爲自己對業務邏輯的學習做一個總結和提升。因爲我還不敢說對業務邏輯內涵及外延理解的非常充分,所以文中如有不當之處,還請各位不用客氣,儘管批評就好!

  內容提要

      ===================前篇=====================

      前言

      內容提要

      1、我把業務邏輯丟了!——找回丟失的業務邏輯

      2、細說業務邏輯

            2.1、業務邏輯到底是什麼

            2.2、業務邏輯的組成結構

                  2.2.1、領域實體(Domain Entity)

                  2.2.2、業務規則(Business Rules)

                  2.2.3、完整性約束(Validation)

                  2.2.4、業務流程及工作流(Business Processes and Workflows)

            2.3、業務邏輯層職責相關爭議

                  2.3.1、爭議一:數據的格式化

                  2.3.2、爭議二:數據合法性及完整性驗證

                  2.3.3、爭議三:CRUD

                  2.3.4、爭議四:存儲過程

      ===================後篇=====================

 

      3、業務邏輯的架構模式及實現

            3.1、Transcaton Script

                  3.1.1、概述

                  3.1.2、分析

                  3.1.3、.NET平臺實現示例

            3.2、Table Module

                  3.2.1、概述

                  3.2.2、分析

                  3.2.3、.NET平臺實現示例

            3.3、Active Record

                  3.3.1、概述

                  3.3.2、分析

                  3.3.3、.NET平臺實現示例

            3.4、Domain Model

                  3.4.1、概述

                  3.4.2、分析

                  3.4.3、.NET平臺實現示例

            3.5、各種架構模式的比較及選擇

      4、結束語

      參考文獻

  1、我把業務邏輯丟了!——找回丟失的業務邏輯

      相信朋友們基本都是軟件開發人員。不論身處什麼職位,我們的工作都有一個共同的目標——製作軟件產品。而所謂的軟件產品,一定是在某個領域內去實現某些業務。如此看來,“業務邏輯”本應和“軟件產品”是緊緊綁在一起的,沒有業務邏輯,何來軟件產品?

      但是,我發現一個奇怪的現象,一說業務邏輯,很多人就無法形成清晰地印象。例如,經典的三層架構:表示層、業務邏輯層和數據訪問層,一提到表示層或數據訪問層,大家腦子裏馬上能產生出清晰的概念,但一提到業務邏輯層,就有點模糊了,或者完全不知道其是什麼,或者有個模糊的輪廓,但對其具體的職責、結構不是很清楚。真是奇了怪了!我們天天和業務邏輯打交道,搞不清業務邏輯是什麼。

      對於這個奇怪的現象,我思前想後,結合自身的教訓(我也曾很長時間搞不清業務邏輯),終於弄清楚了其原因——這和我們接觸這個概念的途徑和認知結構有莫大關係。

      不知道有多少人和我一樣,首次接觸“業務邏輯”這個概念是從分層架構中的“業務邏輯層”概念開始的,我相信不在少數。事情壞就壞在這裏!爲了讓朋友們直觀看清“業務邏輯”的概念是怎麼被我們丟掉的,請大家看一個圖,這個圖展示了很多人對“業務邏輯”的認知過程。

圖1-1

圖1-1、狹義的認知分解過程

  如圖1-1所示,我們先接觸了分層架構,然後對每個層產生了初步的認識。其中,由於表示層和數據訪問層的代碼職責清晰明確,基本能正確認識。但是,由於我們接觸的分層架構的Demo大多業務極其簡單,又基本是CRUD操作集中型的業務。所以,我們腦子中就產生了疑問:這個所謂的業務邏輯層是幹什麼的?怎麼就簡單封裝了一下數據訪問層的操作?這有存在的必要嗎?由於有了這種“先入爲主”的誤導,使得很多朋友腦中將“業務邏輯”和“業務邏輯層”兩個概念混淆了,始終想不明白這東西到底是什麼,做什麼用的。再加上很多朋友所看的、所做的系統都是CRUD操作集中型的,就形成了“業務邏輯貌似就是對數據訪問操作的簡單封裝”這一片面概念。

      到底這一概念有沒有錯呢?其實沒錯,因爲在簡單的、CRUD操作集中型軟件中,業務邏輯基本就是對數據訪問簡單的封裝。但是,無錯不代表全面,這是一種狹義的業務邏輯理解,而且是狹義中的狹義。爲什麼這麼說呢?因爲我們不但是在“業務邏輯層”這麼一個狹義範圍內去理解業務邏輯,而且還是CRUD集中型操作這種“非常瘦”的業務邏輯層範圍內去理解,所以,可謂是在狹義的基礎上的狹義。

      當我們把這麼一個“狹義中的狹義業務邏輯”與“業務邏輯”等同起來時,誤會、迷茫、困惑、不屑就出現了。這就如同,給你一隻溫順的哈巴狗,還是病怏怏的、無精打采的小哈巴狗,而你把這隻“病怏怏的小哈巴狗”與“狗”的概念等同起來了。那麼你一定就會爲有人養狗看家和警察養狗當警犬抓壞人而困惑:這東西這麼弱小,我一腳就踩死了,怎麼弄用來看家和抓壞人呢?進而可能會產生“狗狗無用論”,“狗狗廢品”等觀念。當然,在現實中,很少有人只見過小哈巴狗而沒見過狼狗等其它狗類,所以,故事中的誤會對“狗”一般是不存在的。但在現實中,確實有很多人只見過業務邏輯中的“小哈巴狗”,卻沒有見過業務邏輯中的“狼狗”、“藏獒”,所以,這種誤會在對“業務邏輯”的理解上廣泛存在。

      那麼,廣義的情況究竟是怎麼樣的?請看下圖。

圖1-2

圖1-2、廣義的認知分解過程

      (注意!凡是不特別說明,下文中所有“數據”一詞都指需要持久化的數據,而不包括內存中的臨時數據。請各位留心。)

      如圖1-2所示,廣義的認知分解應該是這樣的:軟件產品都是在某個領域內實現某些特定業務,所以,軟件產品天生應該分解爲界面交互部分和業務邏輯部分,其中業務邏輯部分是軟件產品的核心,它客觀存在於軟件產品內部,但是無法對使用者產生直觀刺激,因此業務邏輯不能與使用者直接交互。而界面交互部分是業務邏輯與使用者進行交流的接口,使用者通過界面交互部分,與業務進行交流,從而使得軟件產品發揮其作用。

      而在具體實現系統時,界面交互部分演化成表示層,業務邏輯部分演化成業務邏輯層。所以,可以認爲,數據訪問層不是軟件產品自然演化的直接產物,之所以出現數據訪問層,是因爲某些產品的業務屬於“數據操作集中型”業務,爲了實現隔離、複用等目的,架構師從業務邏輯中分離出了頻繁使用的數據訪問業務,形成了單獨的數據訪問層。從廣義來說,可以認爲數據訪問隸屬於業務邏輯,因爲,數據訪問操作實際上也是業務邏輯的一部分。

      總結一下幾個要點:(這幾個要中的業務邏輯均指廣義業務邏輯)

      1)軟件產品自然的可分爲界面交互部分和業務邏輯部分。

      2)從空間結構上看,業務邏輯和數據訪問不是並列關係,而是隸屬關係——數據訪問隸屬於業務邏輯。雖然在具體系統實現層面,數據訪問層和業務邏輯層是並列存在,但從概念本質層面上分析,兩者是隸屬關係。

      3)從時間結構上看,應該是先有業務邏輯的概念,纔有數據訪問的概念。業務邏輯衍生自軟件本身,數據訪問衍生自業務邏輯。

      4)因爲業務邏輯是軟件產品自然的一部分,所以擁有業務邏輯是軟件產品的必要條件(讀者可以試着舉出一個不包含業務邏輯的軟件)。但是一個軟件可以沒有數據訪問,如“計算器”、“不帶存檔的小遊戲”等。

      利用以上論述要點和認知分解,朋友們可以試試在腦中重新構築狹義和廣義“業務邏輯”的概念。看能不能把我們丟掉的業務邏輯概念找回來。關於業務邏輯更多的細節,將在下文中討論。

  2、細說業務邏輯

  2.1、業務邏輯到底是什麼

      在第一大節裏說了那麼多,相信各位基本已經形成“業務邏輯”的概念了。如果我在這裏再囉嗦什麼,我不嫌累各位也要嫌煩了。所以,這裏我僅給出兩個定義。

      廣義上的義務邏輯——軟件本身固有的一種品性,自然存在於軟件產品內部,是軟件具有的在某個業務領域內的邏輯,是軟件的核心和靈魂。軟件產品除界面和交互外的一切都可看作是廣義業務邏輯。

      狹義上的業務邏輯——等同於分層架構中“業務邏輯層”的職責,是軟件中處理與業務相關任務的部分,一般狹義上的業務邏輯不包含數據持久化,而只關注領域內的相關業務。

      對於以上兩種定義,希望朋友們不要割裂開來看,而 要辯證統一的去看,這樣,才能構建一個完整而辯證統一的“業務邏輯”概念。在下文中,將不再明確區分狹義和廣義,“業務邏輯”一詞將代表兩者的辯證統一體。

  2.2、業務邏輯的組成結構

      業務邏輯作爲一個高層次概念,其內在結構也是非常豐富的,下面我們深入其裏,去探尋一下業務邏輯都是由哪些更底層的部分構成的。

  2.2.1、領域實體(Domain Entity)

      通俗的說,領域實體就是這個領域內有哪些東西。例如,銀行業領域內有賬戶、支票、前臺營業員等實體;B2C電子商務領域有商品、訂單、交易等實體;魔獸世界遊戲的領域內有角色、種族、道具、魔法等實體;高等代數領域有矩陣、行列式等實體。

      領域實體是某個領域內各種對象的抽象,可以用名詞表示(可以是具體名詞或抽象名詞,甚至動名詞,只要其具有名詞性),構成了整個業務邏輯的骨骼和靜態模型。一般每個領域實體有自己的一些屬性和行爲。順便說一句,領域實體的存在時OOA&D的基礎。

      在具體的軟件系統中,領域實體往往會根據架構的不同有不同的映射存在形式。

      其中一種叫做Business Object(BO),即業務對象,某些文獻稱其爲“充血實體類”,這種對象完整抽象了領域內的某個實體,封裝了此實體相關屬性和行爲。在面向對象的設計和架構中,這種實體類很常見。

      另一種叫做Data Transfer Object(DTO),某些文獻稱其爲“貧血實體類”,其特點是僅有屬性,不存在行爲。這種實體類主要負責整體性傳遞數據。另外,與BO不同的是,DTO可以不抽象領域實體的全部屬性,而只根據需要抽象一部分。例如,某個“User”實體存在很多屬性,但如果某個方法僅需要其聯繫方式,可以設計一個DTO,僅有id,email,address,phone等就夠了。在面向過程的設計和架構中,這種實體設計比較常見。

      2.2.2、業務規則(Business Rules)

      業務規則就是某個領域內運作的規則,構成了整個業務邏輯的靈魂和動態模型。業務規則作用於領域實體,領域實體遵從業務規則進行運作。

      如:在銀行領域內,“轉賬時從A賬戶扣除相應款項,在B賬戶添加相應款項,並從A賬戶扣除相應手續費,並通過某些途徑通知A和B賬戶的戶主”就是一條規則。需要注意的是,業務規則比較抽象,並不是需求,需求需要具體且無二義性,而業務規則只是抽象的一種描述,例如,通知戶主的途徑是什麼?電子郵件?電話?短信?並沒有具體描述,但在規則中有“通知”這一項,因此不能將業務規則等同於需求。

      2.2.3、完整性約束(Validation)

      領域實體和業務規則構建了業務邏輯的主體,但在這主體之上,還存在着一個限制,這就是完整性約束。

      完整性約束是對業務領域中的數據、規則的強制性規定與約束。這種約束是系統正常運轉的保證。

      如“賬戶密碼不能爲空”,“身份證號必須符合具體格式規定”,“轉賬流程必須具有原子性,A賬戶扣錢、B賬戶存錢、A賬戶扣除手續費、通知戶主四項操作必須要麼都做,要麼都不做”,都是完整性約束。

      2.2.4、業務流程及工作流(Business Processes and Workflows)

      有了上述三項,業務邏輯還不能正常工作,因爲還沒有“啓動器”和“過程託管器”。設想我們有了各種實體類,它們有各自的屬性和行爲,也有定義好的業務規則和完整性約束。現在實體類僅僅具有實現業務規則的能力,但它們如何啓動並交互協調完成業務規則呢?因此我們需要有東西去觸發和協調實體。

      業務流程或工作流是啓動及託管協調領域實體完成既定規則的過程。例如,“在線訂購”是一個業務流程,它包括“用戶登錄-選擇商品-結算-下訂單-付款-確認收貨”這一系列流程。各個實體如會員、訂單、商品等已經包含了完成在線訂購必要的行爲,但仍需一個流程,才能真正完成業務。

      具體到程序中,業務流程也許通過一個方法來實現,這個方法負責啓動並協調各個實體類,完成一個流程。

  2.3、業務邏輯層職責及相關爭議

      2.3.1、數據的格式化

      關於數據的格式化應該放在業務層進行還是表示層進行一直存在爭議。我個人的意見是這樣的:

      業務層送給表示層的數據應該具備以下要求。1)返回的數據應該完成了所有必要的業務處理和業務計算。例如,若返回訂單信息讓表示層展示,會有個必要的數據——訂單總額。這個數據需要首先用各個訂單項的單價乘以數量,然後加和。那麼,這個數據應該在業務層完成計算直接返回,總之不應讓表示層進行任何業務處理和計算操作。2)一次性返回所有需要的數據,避免表示層再一個Action裏調用多次業務。打個比方,例如訂單中有個“客戶姓名”,這個數據不保存在訂單表中,而是通過外鍵關聯的,那麼,業務層應該將“客戶姓名”一併取出返回給表示層。總之,避免表示層在一個Action裏多次調用業務層。3)不攜帶任何格式信息,僅僅是結構良好的純淨數據,如DTO形式。因爲,數據如何展示,是表示層的職責,如何在業務層中返回了過多格式信息,就會造成表示層的修改困難。例如,我曾聽說過所裏承接的一個實際項目,開始是使用B/S,當時他們的業務層返回的數據全都附帶了html代碼。後來,客戶嫌B/S響應不夠迅速(可能是客戶公司的網絡條件不好),要求改成C/S,當時全傻眼了,貌似幾乎修改了整個業務層。那個項目相當龐大,7個子系統,投入200人開發了1年多,想想修改的難度吧。

  2.3.2、數據合法性及完整性驗證

      一般做系統,都避免不了數據驗證。上文曾經提到,完整性約束是業務邏輯的一部分。如此看來,數據驗證一般應該放在業務層。但是,實際情況並不盡然。個人認爲數據驗證的方式,目前沒有統一標準,可以根據需要放在表示層或業務層。但是,我個人不提倡在“表示層的服務端”放置過多完整性驗證。因爲,表示層的職責應該僅僅是接收數據並傳遞給業務層,不應對數據是否合法負責。過多的數據驗證,不但令表示層代碼臃腫,而且使得表示層職責變得不明確。

      可以在“表示層的服務端”放置一些簡單的驗證,如空值驗證,兩次輸入密碼是否一致等,但業務關係緊密的驗證,最好放在業務層。甚至有些驗證只能在業務層驗證,如“當前用戶名不能與已有用戶名重複”,這種驗證需要訪問持久化數據,需要由業務層完成。

      這裏之所以強調“表示層的服務端”,是因爲一般在B/S系統中,都會在JavaScript里加入一些基本的數據驗證,如空值檢查,格式正則匹配等。這主要是爲了減輕服務器負擔,將大多數顯然包含不合法數據的請求拒絕掉,而不發給服務端驗證。當然,因爲可能會出現JS被屏蔽或黑客惡意攻擊行爲,所以,所有驗證不論JS中是否驗證過,服務端(可能是表示層的服務端部分或業務層)一定要再進行驗證。

      2.3.3、CRUD

      CRUD,即常說的增刪改查操作。關於CRUD是否是業務層的職責,一直也是爭議不斷。因爲目前並沒有權威的定義,所以這裏我斗膽說一下我對這個問題的看法。還請大家批判性閱讀。

      一說到“增刪改查”,大家一定會覺得這理所當然是數據訪問層的職責。我認爲這個理解是對的,但是隻對了一半!之所以這麼說,是因爲“增刪改查”有兩個層次含義。

      第一個層次,是數據訪問層次上的。在這個層次上,“增刪改查”只是單純的數據庫操作,“增刪改查”可以理解爲“插入一條記錄,刪除一條記錄,更新一條記錄的信息,獲取一條或多條記錄”四個操作,其意義和着眼點完全是數據訪問層面上的,不帶有任何業務成分和業務知覺。這個層面上的CRUD應該屬於數據訪問層的職責。

      第二個層次,是業務邏輯層次上的。在這個層次上,“增刪改查”是業務領域內實體的變化以及一系列相關反應,“增刪改查”可以理解爲“領域內新增一個業務實體,領域內去掉一個業務實體,領域內一個業務實體更新了信息,得到領域內一個或多個業務實體的信息”。

      兩者最大的不同,是業務層面上的增刪改查往往不是單純的增加減少,還包括實體變化後相關的業務流程。下面舉個例子:

      “添加一個新的訂單”——這是一條典型的“增”操作。在數據訪問層面上,它的意義是“在表示訂單的數據表裏增加一條記錄”;而在業務邏輯層面上,它的意義除了“領域內多了一個訂單實體”外,還可能包括“根據業務規則判斷是否是重複下單,根據金額對下訂單客戶的等級做相應提升、發送Email和短信通知客戶等”。可以看到,業務層面上的“增”可能不僅是簡單封裝一個簡單的插入記錄,可能還要去做其他數據訪問——提升用戶等級,以及做一些非CRUD的業務操作——發送短信通知。

      在許多稍微複雜的系統中,業務往往不僅僅是封裝了一條數據訪問操作,而是還有很多如計算等業務處理,一個業務操作期間可能要多次使用數據訪問操作。退一步說,即使某個業務僅僅封裝了一條數據訪問操作,其意義和層面也是不同的,在數據訪問層面,僅僅是多了一條記錄,而業務邏輯層面,是領域內多了一個業務實體。也許其本質上都是往數據庫插入一條記錄,但人類的抽象思維可以將之在不同層面上區分,這也是人類思維層面的一種抽象能力的表現。例如,我們知道太陽升起不過是地球自轉使得從背陰面轉到了向陽面,但當人們看日出時,很少有人會說“看!我們從背陰面轉到向陽面了!”,我們會說“看!日出!”,這就是同一事物的不同層次表現。

      2.3.4、存儲過程

      也許是性能上的誘惑,許多人喜歡在數據庫系統中寫很複雜的存儲過程。這樣,許多業務操作就被寫到存儲過程中去了。我個人建議,除非對性能要求極高,否則最好還是不要用存儲過程實現業務。例如,在一般的系統中,某個業務操作可能需要1秒,而是用了存儲過程只用0.1秒,看上去存儲過程將效率提高了10倍。但對大多數用戶來說,1秒和0.1秒的差別並不大,但是這樣做的話,業務會變得十分不容易維護。所以,我個人覺得,除非十分必要,還是不要用存儲過程實現業務。

3、業務邏輯的架構模式及實現

   Martin Fowler在《Patterns of Enterprise Application Architecture》一書中,總結了四種企業應用中業務邏輯的組織方式 :Transcation Script,Domain Model,Table Module及Service Layer,另外,本書的第十章“Data Source Architecture Patterns”中包含一種模式——Active Record。結合軟件體系結構的近期發展及個人的理解,我更傾向將Active Record歸入業務邏輯的組織模式,而Service Layer應該不算做業務邏輯特有的模式,所以,在本文中,將介紹四種模式:Transcation Script,Table Module,Active Record及Domain Model。

  3.1、Transction Script

      3.1.1、概述

      Transction Script(以下簡稱TS)是一種面向過程的業務邏輯組織方式。這裏首先要強調一點,這裏的Transction一詞與數據庫系統中表示“事務”的Transction沒有任何聯繫。TS是將領域中的業務分解爲一個個業務過程,每個過程實現一項業務功能,具體到程序中,一個業務過程往往映射到一個方法。TS是完全面向過程的業務組織模式,適合應用於業務邏輯較簡單的場合。

      應該說,我們見到的絕大多數系統都是以TS組織業務的。例如PetShop及Oxite等經典示例。有時爲了方便維護,開發者會將同一領域實體相關的業務方法集中到一個類中,這裏雖然用到了領域實體和類的概念,但和麪向對象沒有任何關係,完全是面向過程的。

      當使用TS時,可以不需要數據訪問層,而是將數據操作執行代碼(如執行SQL或存儲過程的代碼)直接嵌入在業務方法中,有時爲了複用性和維護性可以編寫一個helper類封裝數據庫的操作。當然這並不是說TS不能配合數據訪問層使用,但由於應用TS的場合一般業務非常簡單,如果配合Repository或ORM使用,業務邏輯層往往就會變得非常“瘦”,看起來僅僅是對數據訪問層的封裝。一般在需要支持多數據庫的場合,要配合Repository和Abstract Factory使用。

      TS的示意圖如下所示:

圖3-1

圖3-1、 Transcation Script架構示意

  可以看到,在TS中,業務層並沒有面向對象的東西。也許會用到類,但類只是組織業務方法的模塊,每個模塊中有一個個業務方法,每個業務方法完成一個業務流程,完全按面向過程結構組織。

      3.1.2、分析

  • 什麼時候可以用TS?

      應該說,如果具備以下條件之一,你可以考慮TS:

      1)系統業務十分簡單直觀,並且頻繁變動的可能性不大

      2)工期很緊,需要儘量壓縮設計的時間,儘快投入編碼

      3)不能熟練掌握和使用OO進行系統的設計與開發

      4)厭惡OO,就是喜歡面向過程

  • TS的優點?

      1)設計階段投入較小,啓動耗費低。因爲TS較容易掌握,使用起點低,所以使用TS的初期投入較少

      2)在業務比較簡單直觀的情況下,TS結構的代碼直觀易懂,具有良好的可維護性

  • TS的缺點?

      1)容易造成代碼冗餘。因爲各個業務自行組織流程,所以減少了複用的機會,可能產生重複性代碼

      2)因爲TS天生不適合業務複雜的系統,當系統業務較複雜時,可能會令業務層代碼繁雜不堪

  3.2、Table Module

  3.2.1、概述

      Table Module(以下簡稱TM)同樣是一種面向過程的業務邏輯組織方式,與TS不同的是,TM更貼近關係型數據庫結構。在TS中,一般使用DTO等進行數據表示和傳遞,其着眼點一般在單個對象。而TM一般根據數據表組織業務模塊,每個模塊對應一個表,其中包含了這個表的相應處理。並且在業務層內,使用庫-表結構的對象進行數據操作,做到最大限度與數據表的對應。業務組織一般按照面向過程組織。

      一般當業務相對簡單且業務基本集中在CRUD操作時,可以考慮TM。使用TM意味着使用數據驅動設計。通常自己實現一套庫-表結構操作對象的庫是難度比較大的,所以一般選用TM時,所使用的平臺應該包括這麼一套庫。如.NET平臺上的ADO.net就內置了豐富的庫-表操作,DataSet,DataTable,DataAdapter等在TM架構的實現中可以起到非常方便的作用。

      使用TM後,一般不需要再配合Reponsitory或ORM,因爲此時的業務層也是面向過程和麪向關係型結構的,無須映射。

      TM的示意圖如下:

圖3-2圖3-2、Table Module架構示意 

      在使用TM後,業務代碼中往往有各種對象對應數據庫中的庫、表、記錄、字段等元素,並提供類似關係數據庫的操作。

  3.2.2、分析

  • 什麼時候可以用TM?

      如果同時具備以下條件,你可以考慮TM:

      1)系統業務較直觀,以CRUD操作比較集中

      2)整個開發的指導思想是數據驅動

      3)所選用的平臺有成熟的庫-表操作庫支持

  • TM的優點?

      1)類似關係數據庫的數據操作方式非常直觀,使得設計和編寫數據操作功能的代碼簡單高效

  • TM的缺點?

      1)TM需要完全的數據驅動,從業務到UI傳遞、存放數據都要以表結構形式,造成一定程度上的不靈活

      2)當業務並非CRUD集中型操作,特別是領域模型和數據庫表模型差異較大時,使用TM組織業務的難度非常大

  3.3、Active Record

  3.3.1、概述

      Active Record(以下簡稱AR)是一種面向對象的業務邏輯組織方式。AR適用於在業務較簡單的情況下,應用面向對象思想進行設計。它的基本思想就是將領域中每個實體抽象出一個業務類(BO),然後,將這個實體的數據和行爲封裝成類的屬性和方法。特別的,將CRUD功能也封裝進BO中。也就是說,AR中的BO同時具備業務方法和持久化功能。其本身具有ORM的特性,其內部要處理關係實體間的關聯問題。

      使用AR時,一般最好有相應框架支持,否則完全手工實現AR有點麻煩。像Castle框架中就有AR功能,Linq to sql也有AR的意思。使用AR後,一般不需要再單獨使用數據訪問層。

      AR的組織架構如下圖:

圖3-3 圖3-3、Active Record架構示意

      從圖3-3中可以看出,AR對業務領域進行了一個簡單的OO抽象,將各個實體抽象爲AR業務對象,AR業務對象內含有數據、業務方法及數據訪問相關的ORM方法。另外,AR業務對象要維護實體間簡單的一對多和多對多等關係。

  3.3.2、分析

  • 什麼時候可以用AR?

      如果同時具備以下條件,你可以考慮AR:

      1)系統業務較直觀

      2)想嘗試使用或習慣於使用OO進行系統設計與實現

      3)平臺上有成熟的AR框架可以用

  • AR的優點?

      1)使用OO的方式進行設計與實現,能在一定程度上避免冗餘代碼問題)

      2)使用AR後,與某個實體相關的數據和業務全部集中於AR業務對象中,模塊內聚性好,便於維護

      3)實踐證明,AR結構的業務層編碼效率很高

  • AR的缺點?

      1)AR仍需要關注數據之間的關聯,在一定程度上帶有數據表和影子,沒有完全擺脫數據驅動,所以當業務領域和數據庫結構差距大時,實施困難

      2)AR的CRUD是以個體爲粒度的,當進行批量操作時,如一次查數千個數據,如果嚴格尊從AR就需要生成數千個AR業務對象,這簡直是場災難。所以在有大規模查詢的情況下,可以考慮使用TS配合AR

      3)如果業務非常複雜,AR將力不從心

  3.4、Domain Model

  3.4.1、概述

      Domain Model(以下簡稱DM)是一種適合領域驅動和爲複雜業務系統組織業務的面向對象業務邏輯組織方式。前面三種架構模式都有一個共同的缺點——不適合業務複雜的系統。那麼何爲複雜何爲簡單?很抱歉,我給不出明確答案,而且我估計世界上任何一個人都很難給出標準的無爭議答案。因爲軟件系統中的複雜和簡單本身就是一個難以量化的指標,很多時候,只能靠專業人員的經驗了。

      我個人估計,世界上95%的軟件系統其業務難度都不會超出上述三種模式的能力範圍,而若你不幸遇到剩下的5%,恐怕目前只有Domain Model能幫你了。Domain Model是一種純面向對象的業務架構模式,它的核心思想是獲取領域中的各種實體抽象,然後完全按照現實領域中的情況去建模和運行。並且業務對象是“持久化無知”的。關於“持久化無知”下面細討論。這個模式十分複雜和難以掌握,但一旦掌握並使用,其能力絕對會超乎你的想象。

      下面看一下DM的架構示意圖:

圖3-4  圖3-4、Domain Model架構示意

      從圖3-4中可以看出,DM看上去是個十分糾結的模式,而實際上,它確實很糾結!實際上,我認爲如果能熟練掌握並運用DM進行業務邏輯的組織,那這人絕對是架構師中的大師級人物(我目前是做不到)。

      還是先結合圖示分析一下DM中的要點。

      第一,DM中的業務對象是純業務對象,不含數據訪問操作。這個可以和AR中的業務對象對比一下。也就是說,DM中的業務對象是純業務對象,它們只關注與業務的實現。

      第二,DM的組織內部對象多,關係複雜,而這種關係不再只是那種簡單的一對一、一對多的關係,而是領域中的各種依賴和關聯的抽象,關係類型多,非常複雜。

      第三,DM需要業務部分“持久化無知”。所謂持久化無知,指業務部分只需執行業務功能,而不必關係持久化。在使用DM時,必須設計一套ORM機制(注意這裏用到了“機制”一詞,而不是“框架”或“庫”),使得在業務系統運行時,自動在必要的時候執行數據持久化操作。這也是爲什麼上圖數據源和業務層間的箭頭是虛線的關係。

      上文曾說過,DM要最大程度模擬現實情況。而現實世界和軟件世界最大的區別就是現實世界是“內存無限大、永不停機的”,可以把現實世界看成在一個無限大內存裏永不停止運行的程序。而軟件世界不同,它的內存有限制,我們不能將所有對象都放在內存,而且一旦掉電,它就會停止運行,正因如此,我們才需要持久化機制去配合DM模擬現實世界。爲了讓業務更接近現實,它必須對持久化過程毫無感覺。而一套持久化機制默默爲其營造了一個好似內存無限大、永不停機的環境,因此DM才得以發揮威力。

      第四,DM往往需要Services Layer的配合。因爲DM內部僅有一個個業務對象,它們互相調用,並沒有提供一個友好的接口與UI交互,所以在使用DM時,往往在其上對各種UI需要的服務進行封裝(回顧一下Facade模式),形成一個Services Layer,以方便與UI交互。

  3.4.2、分析

  • 什麼時候可以用DM?

      如果同時具備以下條件,你可以考慮DM:

      1)系統業務極爲複雜

      2)有功底紮實和經驗豐富的精通OO的架構及設計師

      3)項目經費和時間充足

      4)貫徹領域驅動設計

  • DM的優點?

      1)完全的OO思想運用,將使你享受到OO的所有優勢

      2)應付複雜業務的強力殺手鐗。如果DM運用得當,將會使得複雜業務被高效解決

  • DM的缺點?

      1)使用門檻極高,難度極大,如果團隊中沒有精通OO和系統架構且經驗豐富的專家很難實施

      2)設計過程極爲複雜,可能會導致設計癱瘓

      3)如何設計良好的ORM機制輔助DM是一大難題

  3.5、各種架構模式的比較及選擇

      相信看過上文內容後,各位一定對各種業務組織模式及其特點、優劣、應用場景有了清晰地認識,如果我在這裏再喋喋不休討論各種模式的比較及如何選擇,難免有侮辱各位智商之嫌O(∩_∩)O~,所以這裏我只給大家呈現一幅決策網絡圖,以期起到一個梳理和歸納總結的作用。

圖3-5

圖3-5、業務架構模式決策網絡

      (鄭重聲明:圖3-5爲本人原創,並非摘錄自已有文獻,因此此圖的選型流程僅代表個人意見。由於筆者水平有限,不能保證此圖一定合理和正確。因此在實際選型時請多多參考已有文獻及諮詢相關專家,此圖只起總結歸納和探討作用,不作爲任何指導和規範。若因遵循此圖選型而給項目帶來的任何經濟及其他方面損失,筆者不承擔任何責任。)

  4、結束語

      本文通過兩篇文章的篇幅,先後介紹了業務邏輯的定義、相關理論及經典的業務邏輯相關的架構模式。本文中闡述了不少已有理論,亦摻雜諸多個人理解及看法。因此請各位在閱讀時多進行批判吸收,同時參考以後經典文獻及書目綜合理解業務邏輯,切勿僅看我一家之言。

      另外,由於本文僅僅是綜述性文章,不能具名業務邏輯的各個方面,在深度上也基本是淺嘗輒止。因此,若希望深入理解業務邏輯,可以看到相關經典書籍及文獻。

  參考文獻

  [1] [意]Dino Esposito, Andrea Saltarello, .NET軟件架構之美英文版(原名Microsoft .NET Architecting Application for the Enterprise), 人民郵電出版社, 2009

  [2] [美]Martin Fowler, 企業應用架構模式影印版(原名Patterns of Enterprise Application Architecture), 中國電力出版社, 2004

  [3] [美]Mclaughlin, Pollice, West, 深入淺出面向對象分析與設計影印版(原名Head First OOA&D), 東南大學出版社, 2007

  [4] Google, www.google.com

  作者:T2噬菌體
  出處:http://leoo2sk.cnblogs.com
  本文版權歸作者和博客園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接,否則保留追究法律責任的權利。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章