胡亂說一下我對於 BO VO PO DTO 的理解

引言

 

 

本文中將向大家介紹我對於是使用實體的一些體驗,歡迎大家拍磚。更歡迎提出不同或者相同的意見。

正文

 

 

 

剛開始學會使用實體的時候就是建立一個Entity類庫,然後裏面的實體被其他各層引用。大家傳遞和使用的都是這一個類庫中的實體,包括前端和後臺的項目都是引用這個類庫,傳遞和操作這個類庫中的實體。

 

image

 

就像上面的這幅圖一樣。每個都要添加對Entity的引用。每個項目都是這麼做的,也沒有發現什麼不好的地方。

 

以前都是做一些小項目,或者是自己Demo一下。上面的做法也沒有什麼問題,而且看到別人的文章也都是類似這樣的結構。後來在學習DDD(Domain Driven Design)的時候,看到了很多的概念。有DTO,VO,PO,BO,DAO,才發現怎麼需要這麼多的實體類庫(有的不是類庫,例如DAO)呢?覺得不可思議,這麼多維護起來不是很麻煩嗎?一下子還沒有想到分開這麼多類庫的好處。

 

從今年年初開始接觸一個大項目,到目前爲止才搞完一半。主要的結構也是BLL,DAL,由於前端採用了純Silverlight展示,所以訪問數據庫必須要藉助服務類的項目(開始的時候我們還是用silverlight3,後來silverlight4可以使用tcp了,但是端口有限制,不適宜在互聯網環境使用,容易被防火牆阻斷,內網應用可以使用tcp),例如:webservice,wcf,最終我們使用的是WCF。我主要負責後臺代碼的編寫,由於人少,後臺我全負責了,包括dal,bll,wcf,一個人搞定。

 

wcf和silverlight之間傳遞數據使用強類型的實體和實體集合,但是silverlight不能添加普通類庫的應用,它有自己的silverlight類庫項目。當然了,silverlight也可以不添加類庫,在添加服務引用的時候,會自動在silverlight項目生成wcf所需要的實體,在reference.cs文件(這個文件就是wcf在客戶端的代理類,裏面包括了服務的定義,也就是下圖中紅框框中的文件,想看這個文件,需要點擊Solution Explorer的Show All Files按鈕,就是解決方案管理器的左上角)中有。

image

 

於是我就建立了兩個項目,一個是普通的類庫,給後臺的BAL,DAL,SERVICE引用;一個是silverlight的類庫,給silverlight引用,他們的文件內容是一樣的。當然了,需要在類和屬性上添加序列化attribute。類上添加DataContract,屬相上添加DataMember。

 

時間長了,在數據訪問層就會有類似很多下面的代碼。

 

 

public List<Person> GetAll()
        {
            List<Person> list = null;
            using (IDbConnection conn = new System.Data.SqlClient.SqlConnection())
            {
                conn.Open();
                IDbCommand comm = conn.CreateCommand();
                comm.CommandText = "select id,name from person";
                IDataReader reader = comm.ExecuteReader(CommandBehavior.CloseConnection);
                list = new List<Person>();
                while (reader.Read())
                {
                    list.Add(new Person()
                    {
                        ID = (Guid)reader["ID"],
                        Name = reader["Name"].ToString()
                    });
                }
            }
            return list;
        }
 

 

 

 

  

就想着能否簡化一些呢?因爲每次查詢都要寫while。。。reader[“”],好像都很重複,想要少些一些這樣的代碼。就想到了好像有ORM這種工具可以幫助實現映射和持久化,找了幾個,NH,微軟的EF。發現學習起來不是很順利,以前沒有項目使用過,對於他們的內部不是很瞭解,拋出的一些異常也不是很好解決,如果這時候引入項目的話,肯定有風險,搞不好還會拖慢進度,決定放棄引入這些ORM工具,等待詳細學習瞭解之後再做決定。

 

但是上面的代碼還是要簡化啊,至少在從數據庫的reader到entity這一層面可以想辦法簡化賦值過程。想到了反射,利用反射給每個屬性賦值,再加上attribute,給屬性打上標記,方便屬性和數據庫查詢結果列的對應。於是就寫了一個EntityMapper的小工具,來輔助實現reader到enttiy和entitycolleciton的映射。詳見:利用attribute實現簡單的ORM

 

實際上沒有ORM那麼強大,就是一個reader到enttiy和entitycolleciton的映射的工具,以後想着要基於這個逐步完善成一個自己的ORM,這是後話了,暫且不提。

 

這時候發現減少了很多的工作量,而且代碼也簡單多了,沒有了大量的reader[“”]到屬性的賦值。

 

我們系統的業務是經常變化的,後期有添加的需求,有修改前期的需求。導致了,實體類庫需要修改,增加屬性,減少屬性之類的。減少還好辦,頂多就是數據庫查詢的多了,沒有屬性和它對應了,我不賦值就是了。增加屬性就暴露了各層公用一個實體類庫的問題,還是一個不小的問題。

 

例如我在一個類添加一個屬性,由於reader到entity的映射是採用我寫的這個工具,於是添加屬性,添加attribute。新方法,新存儲過程,測試,沒有問題。但是,這個實體的其他方法就報錯了,因爲其他方法對應的存儲過程沒有查詢新添加的字段,但是在映射的時候是根據屬性映射的,就報錯“沒有找到新屬性對應的列”。好吧,那就打開老方法的存儲過程,添加對於新屬性的查詢。問題就出來了,本來是添加方法,卻還要修改以前的存儲過程,少的還好,多的情況的話,就需要修改大量的存儲過程,我碰到最多的一個是牽連了10個存儲過程。這也可以歸結爲緊耦合,依賴太強了,需要解耦。

 

當然,改也是copy,因爲字段一樣,但是這個問題應該有更好的辦法,這樣下去,維護量會越來越大。

 

於是想起學習DDD的過程中遇到的那些概念了,什麼BO,PO,DAO,DTO,VO的。首先給大家說一下這些概念,然後講解我對他們的使用方案。這些概念好像在Java中非常流行,使用java進行開發的人應該更加熟悉他們。

BO:Business Object,業務對象。主要是承載業務數據的實體。處理業務邏輯的時候使用,數據結構也是針對業務邏輯建立的。

PO:persistence Object,持久化對象。數據最終要存儲,無論以何種形式存儲,都必須要持久化。加入使用關係數據庫存儲,一個PO對應一條數據庫的記錄,或者是對象從數據庫查詢出來的結果集的一條記錄。

DAO:Data Access Object,數據訪問對象。包含一些數據庫的基本操作,CRUD,和數據庫打交道。負責將PO持久化到數據庫,也負責將從數據庫查詢的結果集映射爲PO。

DTO:Data Transfer Object,數據傳輸對象。一般用來在前段和後臺的數據傳輸,數據結構的簡歷是基於網絡傳輸的,減少傳輸的數據量,避免傳輸過多無用的數據。

VO:Value Object,值對象。主要用在前段數據和控件的綁定操作中,以鍵值對的形式存在。可以從DTO轉化而來,這麼做的好處就是減少對於DTO的依賴,進一步減少對應後端的依賴。還可以增加前段的可測試性,也就是沒有DTO,也可以對前段邏輯進行自動化的單元測試,可以通過MockDTO來達到測試的目的。

 
 

 

 

image

我想通過上面的這幅圖來表達我的想法。web,winform,silverlight,console代表不同的前端類型。Domain代表領域對象,也可以是BLL。

獲取數據的過程:首先DAO從數據庫獲取結果集,轉換爲PO。Domain接受到DAO傳遞過來的PO之後,負責將PO轉換爲BO,再進行業務邏輯的處理。處理完畢,傳遞BO給service,service負責轉換爲DTO,傳輸給前端接收到DTO之後,首先轉換爲VO,然後再進行前端的業務處理。

提交數據的過程: 前端將數據整理爲DTO,傳輸給service,service轉換爲BO傳輸給Domain,Domain轉換爲PO,調用DAO提供的數據持久化方法,持久化PO,DAO負責將PO持久化爲數據庫的數據。

 

 

 

 

好像還有一個概念叫做:POJO,這是java中的概念。POCO是.NET的概念。個人理解好像就是一類實體的統稱,指的是實體沒有操作,只要屬性,簡單實體,沒有繼承或者實現任何抽象的實體。凡是滿足這個標準的實體都可以叫做POCO或者POJO。

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