標籤:style blog http color os 使用 ar strong for
本章內容主要包括兩個方面,一是架構分層(控制器、業務對象、實體、Dao)的詳細說明,二是對比常用三層結構的區別和優勢;
我們先看一下前面執行個體中的解決方案目錄:
我們再看各層之間的調用關係:
描敘的控制器有四種方式來操作資料庫,
1)控制器調用實體,通過架構中的ORM來實現單表的操作
2)控制器直接操作資料庫對象(oleDB),通過編寫SQL語句訪問資料庫
3)控制器通過調用Dao操作資料庫
4)控制器調用業務對象,業務對象再調用Dao操作資料庫
還有就是每一層在程式結構中承擔的角色;
一、Dao
Data Access Objects,建立一個Dao必須繼承繼承架構中的AbstractDao對象,AbstractDao對象中封裝了資料庫操作對象oleDb,所以Dao中的方法都是直接編寫SQL語句操作資料庫;
public class BookDao : EFWCoreLib.CoreFrame.BusinessArchitecture.AbstractDao { public DataTable GetBooks(string searchChar, int flag) { string strsql = @"SELECT * FROM dbo.Books WHERE BookName LIKE ‘%{0}%‘ AND Flag={1}"; strsql = string.Format(strsql, searchChar, flag); return oleDb.GetDataTable(strsql); } }
上面代碼是實現對Sqlserver資料庫的操作,如果要實現不同資料庫的操作,如:Oracle、DB2等,要如何??很簡單,先建立IBookDao介面,再分別實現SqlBookDao和OracleBookDao,控制器訪問Dao只需調用IBookDao介面就行了,而最後操作哪個資料庫的Dao在EFWUnity.config設定檔中配置好。
IBookDao介面
public interface IBookDao { System.Data.DataTable GetBooks(string searchChar, int flag); }
SqlBookDao對象
public class SqlBookDao : EFWCoreLib.CoreFrame.BusinessArchitecture.AbstractDao, Books.Dao.IBookDao { public DataTable GetBooks(string searchChar, int flag) { string strsql = @"SELECT * FROM dbo.Books WHERE BookName LIKE ‘%{0}%‘ AND Flag={1}"; strsql = string.Format(strsql, searchChar, flag); return oleDb.GetDataTable(strsql); } }
OracleBookDao對象
public class OracleBookDao : EFWCoreLib.CoreFrame.BusinessArchitecture.AbstractDao, Books.Dao.IBookDao { public DataTable GetBooks(string searchChar, int flag) { string strsql = @"SELECT * FROM Books WHERE BookName LIKE ‘%{0}%‘ AND Flag={1}"; strsql = string.Format(strsql, searchChar, flag); return oleDb.GetDataTable(strsql); } }
EFWUnity.config設定檔
控制器中通過NewDao<>操作方法,建立配置的SqlBookDao對象
綜合上述,不同資料庫Dao結構設計如下:
二、Entity實體
實體代碼都是用工具,根據資料庫表結構資訊產生的;所有實體都必須繼承架構中的AbstractEntity對象,而實體與資料庫表之間的映射不需要另外xml設定檔,而是利用自訂標籤實現ORM映射;TableAttribute標籤映射實體類名與資料庫表,ColumnAttribute標籤映射實體屬性與資料庫表欄位。一個實體映射到多個表也可以,直接類名上配置多個TableAttribute標籤和屬性上配置多個ColumnAttribute標籤,不過要用標籤的Alias參數區分。
三、ObjectModel業務對象
業務對象在書籍管理執行個體並沒有建此對象,因為業務太簡單了,只有當商務程序很複雜或範圍涉及廣的情況,就可以考慮建一些業務對象來解決這些問題;所有業務對象必須繼承架構中的AbstractBusines對象,業務對象中不能直接操作資料庫,必須通過Dao來訪問。另外就是如果多個業務對象是用來解決同一個問題,一般我們使用原廠模式來設計,在架構中可以使用EFWUnity.config設定檔進行業務對象映射;
四、Controller控制器,包括WebController、WinController、WcfController、WcfClientController
控制器分為3種模式,不同模式分別建控制器。控制器在程式結構中的作用就是承上啟下,比如WebController控制器,就是把調用邏輯層返回的資料結構轉換為統一Json字串傳遞給介面JqueryEasyUI。而不同的介面架構則需要對架構中的Webcontroller進行擴充,以後我們會詳細講解各種控制器的實現;
還有就是Controller中提供了資料庫的操作對象OleDB,允許控制器直接編寫SQL語句操作資料庫,為什麼要放開此功能,這也是在項目中遇到的實際情況而不得不妥協的一種設計;
同樣所有控制器也都必須架構中的基類控制器,基於JqueryEasyUI的Webcontroller繼承AbstractJqueryController對象,WinController繼承BaseController對象,wcfController繼承JsonWCFController對象;wcfClientController繼承BaseWCFClientController對象;
再就是控制器暴露給介面UI,還必須加上控制器的自訂標籤,WebController的WebController和WebMethod,WinController的Menu,wcfClientController的WCFController和WCFMethod;
通過上面的介紹,應該對EnterpriseFrameWork架構的分層結構有一定得瞭解,下面我們討論一下,與常用三層結構的區別與優勢?
軟體分層意義主要就包括解耦和複用,也許還能讓代碼維護與擴充更方便;三層結構分別包括介面層、邏輯層和資料層。EnterpriseFrameWork架構中的分層也可以說是三層,只是叫法與承擔的職責不一樣,並且EnterpriseFrameWork架構中的分層可以隨時變化的,不同情況有4種方式對分層進行調整,所以EnterpriseFrameWork架構分層的相容性強。有哪些不同情況,可以總結為兩種,一是根據具體功能的難易程度,二是根據開發人員的代碼水平;
我們對比一下PetShop項目的程式結構:
PetShop項目名稱及描述:(實現步驟為:4-3-6-5-2-1)
1、WEB=展示層
2、BLL=商務邏輯層
3、IDAL=資料訪問層介面定義
4、Model=業務實體
5、DALFactory=資料層的抽象工廠(建立反射)
6、SQLServerDAL=SQLServer資料訪問層 / OracleDAL=Oracle資料訪問層 DBUtility 資料庫訪問組件基礎類
其中3中的IDAL對應EnterpriseFrameWork架構中的Dao介面,Model對應架構中的實體,SQLServerDAL和OracleDAL對應不同資料庫Dao;而不同的有5中的DALFactory在架構中是不需要的,只需設定檔中配置即可;2中的BLL也職責不一樣,架構中更趨向領域模型的設計;1中的WEB展示層,架構中單獨把Controller控制器分出來獨立一層;所以對比兩者發現其思想還是差別比較大的,個人覺得EnterpriseFrameWork架構除了在程式碼的解耦,更在業務、項目等實際情況方面更加合適;
接著再討論一下:貧血模型與充血模型?
貧血模型:是指領域對象裡只有get和set方法,或者包含少量的CRUD方法,所有的商務邏輯都不包含在內而是放在Business Logic層。
充血模型:階層和上面的差不多,不過大多商務邏輯和持久化放在Domain Object裡面,Business Logic(商務邏輯層)只是簡單封裝部分商務邏輯以及控制事務、許可權等。
對這兩種模型的使用個人感覺比較深刻,以前還不知道這種寫法是貧血模型,表產生所有實體,再就是調用實體的N個邏輯對象,這樣的代碼就越寫越過程化,基本上一個系統分成幾個邏輯對象就完成了,沒有了對象的概念;後來就覺得這樣不對,就把實體擴充成一個完整的業務對象,實現對這個實體的所有業務操作方法;這樣剛開始還蠻有感覺,但後來越做越彆扭,一是很多實體根本沒有業務操作,還有就是一個業務操作會跨多個實體;在實體上來補充業務操作方法本來就不太合理,因為表結構的設計本來就不是基於物件導向的;所以後來就演變為現在EnterpriseFrameWork架構中ObjectModel這種模型,我叫做領域物件模型;簡單的業務走第一種模式,複雜的業務就必須分析出領域模型並設計業務對象;
最後分享兩個項目中的小經驗,一個是與大學高校合作開發項目、另一個是小公司老闆的見解;
與大學高校合作開發一個不算太複雜的項目,公司方負責需求的收集與分析,高校針對需求進行設計與開發;高校由一個研究生導師帶隊,也沒用什麼技術架構,就是常用的三層結構,合作的過程就不講了,反正就是最後到我接手維護代碼的時候就感覺到這個系統的坑人之處;首先不算複雜的系統項目建了十多個,找代碼檔案很難找,再就是每改一個小地方要改多個檔案從介面層改到資料層;最受不了的就是代碼的閱讀與調試相當麻煩,每層之間又通過一個工廠反射類名方法名調用;最後我們得出的結論就是在實際項目千萬不能交給高校開發,他們可以搞一些研究項目,做的時候又沒有考慮到一些實際情況;
小公司老闆的見解。一朋友自己做老闆創業,懂點php網頁開發,在學校招了幾個剛畢業生準備研發一個新產品,要我幫忙他們搭建系統架構,我推薦最早架構給他們使用,那時候在Controller中並沒有OleDB操作資料庫;我先把系統的核心業務開發完成,招的幾個畢業生就在此基礎上繼續完善系統,剛開始我在的時候還好,有什麼不明白的我幫忙解決,後來我抽出來後,他們做著做著問題就暴露出來了,一個簡單的功能很久都搞不出來,新產品講究的就是速度嘛,馬上要給客戶看的;所以朋友急了開始找原因,雖然朋友就會個php網頁製作,但通過與幾個畢業生深入溝通,他發現程式分層太複雜了,做一個功能要畫介面,寫控制器、寫業務對象、寫Dao才能完成,更難的他們根本對邏輯層的控制器、業務對象、Dao理解不了,所以一定要他們這樣用就經常搞出一些莫名其妙的問題;朋友就說為什麼不能直接在控制器中寫sql語句,這樣開發起來多簡單?我就說這樣放開不行,會破壞整個程式的分層結構,以後代碼的維護、擴充都會有問題,但我的這些以後說服不了他,他覺得這些以後版本可以最佳化,現在就是要馬上出來;最後只要在控制器也開放了Oledb操作資料庫;
網路上對於三層結構的解釋:
資料訪問層:有時候也稱為是持久層,其功能主要是負責資料庫的訪問。簡單的說法就是實現對資料表的Select,Insert,Update,Delete的操作。如果要加入ORM的元素,那麼就會包括對象和資料表之間的mapping,以及對象實體的持久化。在PetShop的資料訪問層中,並沒有使用ORM,從而導致了代碼量的增加,可以看作是整個設計實現中的一大敗筆。
商務邏輯層:是整個系統的核心,它與這個系統的業務(領域)有關。以PetShop為例,商務邏輯層的相關設計,均和網上寵物店特有的邏輯相關,例如查詢寵物,下訂單,添加寵物到購物車等等。如果涉及到資料庫的訪問,則調用資料訪問層。
展示層:是系統的UI部分,負責使用者與整個系統的互動。在這一層中,理想的狀態是不應包括系統的商務邏輯。展示層中的邏輯代碼,僅與介面元素有關。在PetShop中,是利用ASP.Net來設計的,因此包含了許多Web控制項和相關邏輯。
分層的好處
1、開發人員可以只關注整個結構中的其中某一層;
2、可以很容易的用新的實現來替換原有層次的實現;
3、可以降低層與層之間的依賴;
4、有利於標準化;
5、利於各層邏輯的複用。
概括來說,分層式設計可以達至如下目的:分散關注、鬆散耦合、邏輯複用、標準定義。
分層的壞處:
1、降低了系統的效能。這是不言而喻的。如果不採用分層式結構,很多業務可以直接造訪資料庫,以此擷取相應的資料,如今卻必須通過中介層來完成。
2、有時會導致級聯的修改。這種修改尤其體現在自上而下的方向。如果在展示層中需要增加一個功能,為保證其設計符合分層式結構,可能需要在相應的商務邏輯層和資料訪問層中都增加相應的代碼。
十、EnterpriseFrameWork架構的分層架構及意義(控制器、業務對象、實體、Dao之間關係)