企業應用架構之業務邏輯層的頂層設計與底層思考

摘要

 

        本文將以架構的方式去分析分層結構中的業務層設計,如何寫出來內聚度,高耦合的業務邏輯層,並且如何根據我們的項目功能需要去設計業務層。我們將會通過幾種可能的業務層設計模式去分析,分析每種設計模式的優點與缺點及每種設計模式的應用場景,並且結合一定的使用實例來講解,當然這些具體的內容都是自己在項目中的經驗與總結。錯誤之處,在所難免,本人抱着求真務實的態度,爭取寫好每一篇文章,錯誤之處還請大家指正。

 

        本章講解的內容我們先看一下圖中的幾個簡單模式:

 

 

 

業務層設計分析

 

        本節中將會對業務層設計進行詳細的分析。

 

        首先,我們知道業務層是一個系統中最核心的部分,業務層是實現系統業務功能的核心邏輯層。業務層我們通常說的BLL(Business Logic Layer)層,現在我們一般的稍微複雜一些的業務邏輯都是通過分層結構來構建一個應用系統,我想大家在組織業務邏輯功能時大部分的情況下是使用BLL層單獨負責相應的業務邏輯來實現的。有些應用可能業務邏輯層並不複雜,這時我們可以把問題簡單化,不用引入一些框架性的東西來提升系統的複雜度,但是有些業務規模較大,並且業務邏輯性較強時,可能使用好的業務設計模式帶來的優越性就顯而易見了。我們大家都知道業務邏輯層主要是用來處理領域模型對象之間的邏輯關係的部分。業務層的數據最終是要保存到數據庫中,我們在進行業務層設計時一般是在架構中的分層架構模式中出現的。分層結構中一般是將領域模型與底層數據訪問、表現層等進行分開組織,這樣可以讓系統結構上清晰,並且容易降低他們之間的耦合性。

 

        其次,我們的很多操作都是可以在業務層來完成,比如說用戶的角色權限,數據驗證等一些基本的業務規則。當然這裏說明業務層主要負責系統中的業務規則的實現。這裏我們需要知道2個概念,就是對象模型與領域模型:下面我們說下這2者的區別。

               

                                      

 

        描述對象模型與領域模型的區別。

 

        最後,業務邏輯層作爲分層系統中的中間位置,業務模型是表現層與數據層之間的紐帶。當然在系統設計時,一般不會把領域模型中的領域實體作爲分層之間的傳輸信息,因爲一般來說領域模型中的實體不但包含實體的數據信息,並且包含實體的行爲。可能我們在各層中只會用到實體的數據信息,無疑這時採用領域實體的形式進行傳輸,會增加系統的傳輸負載。當然這裏就會出現我們平時所謂的3層模式中的Model層。當然Model層設計的主要作用就是實體數據的承載,其中並不包含任何行爲。具體的行爲通過數據訪問層來實現CRUD(DDL中的四個基本操作)的操作。

       

                                       

 

        目前我們設計的分層結構中的對象模型中並不包含實體的行爲。其實這裏可以看作是比較好的設計方式,因爲採用對象模型的方式進行數據傳輸時可以降低系統的耦合。當然我們也可以把領域實體看作是多個對象實體的組合並且包含這些對象實體之間的關係。所以我們在做系統架構時可能如何權衡就比較重要,具體是使用領域實體進行數據傳輸還是對象實體主要要看業務的需要。

 

        幾種不同的業務設計模式

 

        首先我們在業務邏輯層設計時,必須首先確定是採用面向過程還是面向對象的模式來設計。下面我們就將針對開篇介紹的幾種模式進行分別介紹,錯誤之處請大家批評指出。我們首先來講解過程式的2類邏輯層的架構模式。

 

        過程式模式

 

        1、事務腳本模式

 

        事務腳本模式是面向過程的模式,那麼我們就不會採用面向對象的設計思想。這種模式是將業務代碼映射到用戶的操作中。簡單的理解就是將用戶的每個操作都對應一個方法,這個方法就是我們這裏講的事務腳本。當然這裏的“事務”就是指我們平時說的業務流程,“腳本”則是我們說的流程中的相應操作方法。這裏需要注意的是 ,不要認爲數據庫操作的相應方法也屬於腳本中的內容,我們通常還是將數據訪問層單獨的書寫,只不過腳本中調用而已。通常,事務腳本模式中都是一系列的邏輯判定或者循環或其他方式,通過一系列的函數調用來實現業務流程的。通常來說一般業務比較單一或者不是很複雜的系統功能,通過該模式實現起來會比較簡單。而且如果業務流程中的變化較爲頻繁的話不建議使用該模式來做。個人認爲,對於這類簡單的功能,我們沒有必要花費較大的代價去設計領域模型和其他方面的考慮。事務腳本模式的一大優勢就是很簡單,沒有開始時的額外代價,它可以很好的進行快速的應用程序開發,一般情況下來說,如果一個項目的時間緊迫,邏輯簡單,並且使用強大的開發工具時,我們可以使用這樣的模式來進行,無論是成本還是開發效率上都非常客觀。

 

        根據上面的介紹可能認爲,事務腳本模式的可重用性不高,並且耦合性太高,適應性並不好,但是仍然可以通過我們好的設計來實現代碼重用,可以在進行“腳本”編寫時將重用的部分抽象出來,寫一個單獨的函數,以達到複用的目的。事務腳本模式的一個重大缺點就是通過這樣的設計很容易造成代碼重複,通常來說我們很容易完成一系列的業務功能,但是隨着應用程序功能的增加,應用程序代碼會變成非常複雜的程序結構,當然我們可以通過重構去緩解該模式下的這一劣勢,當規模達到一定程度時,同樣沒辦法去完成重構工作。

 

        通過上面的講述,我們對事務腳本模式有了初步的認識,那麼下來我們看看我們在進行業務邏輯層設計時的詳細使用該模式的步驟及相關準則。

 

                                                                        

 

        本圖描述了事務腳本模式的設計過程,那麼基本上每個系統流程都可以通過這樣的流程來完成設計。下面我們就針對一個簡單的實例來講解下如何通過這樣的設計流程來實現系統的功能。

 

        我們這裏以簡單的購物流程來講述。如何下一個訂單

    

        首先,我們先來分析下用例:

 

                                                         

 

        我們知道註冊的會員可以通過將產品添加到購物車中,然後通過付款模塊來進入支付系統,完成訂單;其次,分析出事務。

 

                                         

 

                             

                                                         

        一般來說購物的流程是這樣的流程。當然這裏也不是標準的形式。

 

        當然我們也可以將所有的一系列的腳本封裝到一個類裏面,通過靜態方法的方式來訪問也是可以的。只是組織方法的形式不同。當然我這裏提高了,通過將腳本封裝到一個類裏面,通過靜態方法的形式或者實例方法的形式都是可以的,那麼我們來講講什麼時候封裝成靜態方法,什麼時候封裝成實例方法。

 

                                 

 

        我們如何將數據傳入給實體腳本呢,通常我們是通過前面說的對象實體來完成的,因爲數據對象實體只是包含實體的數據信息,並不包含具體的行爲。

   

        我們主要是通過get;set訪問器來實現的。

 

        總結:業務邏輯層是將表現層觸發一系列事務分別實現,那麼對業務邏輯層的建模其實就是對事務的具體實現,將事務映射到業務邏輯層中的不同方法上,一般來說事務代碼維護起來比較難以維護,重用性低,難以理解。

 

        2、表模塊模式

 

        表模塊模式是對事務腳本模式的實踐總結並優化而提出的新模式。相比而言,表模塊模式結構性更強,總體來說,表模塊就是將數據庫中的某個表上的所有可能的操作都寫在一個類文件中,這個類文件中定義了該數據庫表對應的所有的業務方法。表模塊類是一個容器,它內部包含了類的數據信息和相應的行爲。表模塊是映射數據庫表的關係,因此表模塊對應的是數據集合,那麼無法將數據庫表中的某個行記錄進行區分,只能通過集合中的鍵或者索引來訪問行記錄的信息。

 

        表模塊模式由於是在事務腳本模式發展的更有結構化的模式,那麼可以說表模塊模式雖然是面向過程的模式,但是它朝面向對象的模式已經邁了很大的一步,通常在將對象模型中的數據保存到關係數據庫中時,需要使用相關的ORM工具去完成相應的轉換。面向對象模型能夠很靈活、更好的對領域模型建模。當然,表模塊模式仍然關注的是方法,而不是對象。

 

        通常在更好的結構設計指導的同時,需要考慮更多的規則,意味着我們需要書寫更多的代碼。表模塊模式的具體實例可以參考Visio Studio中的提供的DataSet和dataTable。表模塊在處理簡單的實體時具有很好的優勢,但是當實體較複雜時,或者實體之間的關係緊密時無法很好的處理。

 

        總結:表模塊模式相比事務腳本模式。是我們推薦的使用模式。並且VS中自動繼承了相應的datatable 與datas的相應的圖形化設計方法,很方便的使用。並且內部.NET framework 內置了相應的操作方法可以迅速的實現交互,在過程式模式中無疑是使用表模塊模式是首選方案。表模塊模式更關注的是與數據庫表的映射關係,那麼可以說表模塊模式中包含了數據模型。有一些面向對象的味道,不過表模塊模式中並不關注業務。

 

對象式模式

 

        我們來講述下面向對象的模式中的2種方案

 

        1、活動記錄模式

 

        業務邏輯層中的業務邏輯纔是系統的核心,所以我們更關注的是業務邏輯或者領域邏輯。因爲必須關係實體之間的交互。如果對領域模型建模。需要使用面向對象的角度去分析需求。我們先來看看基於對象模式的活動記錄模式。

 

        活動記錄模式是在表模塊模式的基礎上,將表模塊粗粒度的基於數據集上的映射細化到表中行記錄的細粒度的映射,映射的對象中包含相應的數據庫表中的數據信息,並且包含對象的行爲。例如,我們現在如果想將產品表中的產品信息映射到數據庫中的表product中的行記錄,那麼我們需要構建一個product類,該類中的屬性與product表中的列信息一一對應。並且product類中還包含該對象所有的行爲。例如CRUD的操作,其他的行爲等。

 

        首先需要知道活動記錄的優勢是什麼?我的理解就是活動記錄模式容器理解,簡單,並且目前有很多的框架支持這樣的模式。首先就像Linq、Castle框架都是採用這樣的模式。一般情況下,活動記錄模式在關係型模型中可以很好的支持。如果在應用程序中不使用關係型模型來設計業務層的話,就需要我們人工來組織,協調活動記錄與數據模型之間,其實這個就可以簡單的理解爲數據映射,一般的ORM框架中都提供這樣的功能。

 

        我們需要知道,如果活動記錄模式下的對象發生改變了,那麼數據庫也得跟着修改,或者數據庫表發生改變了,那麼你不得不修改對應的活動記錄對象及相關代碼。

 

        總而言之,如果在使用活動記錄模式的過程中不能保證對象模型與數據模型之間的對應關係,我們將會很快失控,領域模型顯然能夠解決這樣的問題。

 

        數據庫表之間如果有關聯的話,通過的是外鍵的形式來進行關聯,那麼我們在活動記錄中一般如何來標識某個類對應的外鍵對象信息呢。

 

        那麼我們在訂單中可能會有對應的用戶ID,不過在不同的框架中可能對外鍵對應的對象信息的存儲方式會有所不同,有些框架中在外鍵對象上通過屬性的方式返回對象的實例的應用。

 

        上面我們看到了活動記錄模式的簡單使用方式,當然我這裏沒有說是寫出來可以運行的實例代碼。只是簡單的顯示了,使用這些模式可能的用法,當然如果大家有更好的理解或者用法可以一起交流。當然活動記錄模型一般就能滿足我們的系統功能,如果說針對業務複雜的領域,那麼必須設計領域模型去完成相應的業務邏輯層的設計。下面我們將來介紹領域模型模式的相關實例。

 

        2、領域模型模式

 

        我們前面講解的幾類模式,其實說白了都是以數據爲中心進行抽象與設計的形式,當然採用這樣的形式無疑是以業務中的數據爲中心,並不是關心的業務本身。以數據爲核心的設計方法一般流程如下:

 

                                        

 

        一般來說我們目前主流的方式都是這樣的順序來執行。當然通過這樣的方式的確一般的簡單應用當然都是沒有太大的問題。有的時候需要同時關係對象的數據與行爲,顯然以數據爲核心的情況就會顯得力不從心,當然簡單的系統時不會有太大的體現,當系統的規模上升到一定的程度時,哪怕添加一些新的需求時,對系統的影響都是致命的。

 

        領域模型關注的是系統期待的行爲及系統正常工作所需要的數據流。一般在設計領域模型的時候需要這個領域的專家協助,最後以類的形式呈現出來。領域模型模式中的實現方式,大家都知道的就是有名的DDD(領域驅動設計)。

 

        領域模型設計的最終目標就是與系統的概念模型匹配起來。我們可以把領域模型看作是概念模型的物理模型。在一個項目中可以說領域模型是最重要的,最關鍵的部分。

 

        領域模型可以看作是一系列對象之間的交互。領域模型中的每一部分都需要用一個帶有行爲的類來表示。這個怎麼理解呢,請看圖:

 

                                                    

 

        訂單信息對象首先會與訂單中的產品對象有交互關係,產品項與產品分類有交互關係。訂單信息與用戶買家有交互關係,訂單的其他信息(物流信息、支付信息等)有交互關係。

 

        例如常說的記錄的系統日誌,不管是錯誤日誌還是其他的所有系統中的日誌,我們建議的方式採用AOP的方式來處理。

 

        領域模型中只關心跟業務流程相關的內容,具體的數據持久化之類的內容一概不關心。領域模型中是一系列的對象之間的交互,那麼我們可能會關心,如何將領域模型中的這些對象的狀態進行保存呢,那麼就會牽扯到對象模型到關係型數據庫中持久化的個問題了,在持久化的問題上,我們可能有幾種選擇,一種是採用現有的ORM框架去實現對象數據的自動持久化,當然這是一種解決辦法。有時候我們是通過手動的方式來進行持久化,可能就不存在這樣的問題。

 

        我們通常在持久化數據的問題上我們希望能做到持久化的透明性,這樣就可以說具體的業務層不需要書寫持久化的操作代碼,當然我們現在設計的時候可能都是要麼是通過特性來實現持久化,或者是通過繼承基類的方式來做持久化的操作,那麼可能帶來如下的問題。

 

                                                          

 

        一般我們知道,一個類如果想不寫相應的持久化代碼還能實現持久化的話,就只能通過動態的注入持久化代碼的方式來實現這樣的持久化透明的方案,微軟的EntityFrameWork2.0中的POCO中的ORM方案,就是通過這樣的方式來實現的。我們更關心的是代碼應該放在何處,是在領域模型中還是領域模型外呢,當然目前的一些常見的框架中已有實現方案,其中大家熟知的NHibernate就是持久化透明的方式,大家如果感興趣可以參考NHibernate的實現思路來做。一般對於這種動態注入代碼的這樣的方案,這裏簡單介紹下可能的實現,由於.NET framework 中提供了一個派生自特性類型的代理類,通過代理類來動態的將這個類的相關功能追加到指定的對象中,這就是所謂的動態代理,當然針對某個特定的類型這樣來做,WCF也是通過代理類的方式來實現這樣的動態插入的形式。

 

本章總結

        本章主要是對業務層建模的不同的架構模式進行了相應的總結及簡單說明,可能某些地方說明不是特別的清晰,當然我也是將平時自己的業務開發中的一些經驗和總結,部分內容是參考以前看的書上的內容,不足之處還請大家多多的指點,還有請感興趣的朋友一起交流領域模型的設計,包括持久化的透明的實現方案等,歡迎大家多提意見和建議。本人抱着學習和寧缺毋濫的原則,寫好每一篇,看過這方面資料的同仁當溫習下相關內容,沒有看過同仁希望對你們有幫助,那就是我最大的動力。

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