存在即是合理的,業務復雜,人員協同性要求高的場景下,這些規范性的東西不按着來雖然不會出錯,程序照樣跑,但是遵守規范會讓程序更具擴展性和可讀性,都是前輩血淋淋的寶貴經驗,為什么不用?
隨着現在后端編程標准化程度越來越高,各種編程模型層出不窮。作為Java開發人員,大部分人不免要接觸VO,BO,PO,DO,DTO之類的,但很多同學對這些概念一直以來都是雲里霧里,團隊開發過程中也總是處於混亂的狀態,抓起來就用,本來是規范性的東西,卻反而導致更加混亂了。
今天我們把這些概念掰開揉碎來講解一下,力求有一個清晰的理解,在開發中能有所助益。文中又理解不到位的,也歡迎大家斧正。
概念
-
VO(
View Object
):視圖對象,用於展示層,它的作用是把某個指定頁面(或組件)的所有數據封裝起來。 -
DTO(
Data Transfer Object
):數據傳輸對象,這個概念來源於J2EE的設計模式,原來的目的是為了EJB的分布式應用提供粗粒度的數據實體,以減少分布式調用的次數,從而提高分布式調用的性能和降低網絡負載,但在這里,更符合泛指用於展示層與服務層之間的數據傳輸對象。 -
BO(
Business Object
):業務對象,把業務邏輯封裝為一個對象,這個對象可以包括一個或多個其它的對象。 -
PO(
Persistent Object
):持久化對象,它跟持久層(通常是關系型數據庫)的數據結構形成一一對應的映射關系,如果持久層是關系型數據庫,那么,數據表中的每個字段(或若干個)就對應PO的一個(或若干個)屬性。 -
DO(
Domain Object
):領域對象,就是從現實世界中抽象出來的有形或無形的業務實體。
如果光看這些概念,可能大部分人都理解,但還是很繞,具體用的時候還是不能很好區分,我們來橫向做個比較,理解會加深一些。
易混點一:VO和DTO
首先VO是最常用的,但對於這個概念,網上也是眾說紛紜,value object 或 view object,一般說視圖對象或者值對象,我更傾向理解為視圖對象。說白了它就是展示用的,不管展示方式是網頁,還是客戶端,還是APP,只要是這個東西是讓人看到的,我們就把它封裝為VO。
VO比較容易混淆的是DTO,DTO是展示層與服務層之間傳遞數據的對象,可以這樣說,對於絕大部分的應用場景來說,DTO和VO的屬性值基本是一致的,而且他們通常都是POJO,那么既然有了VO,為什么還需要DTO呢?
我們舉例來說明一下:
某公司有一個后台服務,服務層有一個getUser的方法返回一個系統用戶,包含sex(性別)、年齡。對於服務層來說,DTO只從語義上定義,可能是這樣的:
{ "gender":"男", "age":35 }
但這個服務同時供多個客戶端使用(不同門戶),而不同的客戶端對於表現層的要求有所不同,比如管理端要求顯示准確的年齡,而應用端為了保護客戶隱私,只需要顯示一個年齡段即可。
管理端VO:
{ "gender":"男", "age":35 }
應用端VO:
{ "gender":"男", "age":30~40 }
從這個例子可以看出,DTO很有存在的必要,根據職責單一原則,服務層只負責業務,與具體的表現形式無關,DTO不應該出現與表現形式的耦合,DTO定義的是原始數據,VO再對DTO數據進行解釋。這下VO和DTO用法就清晰很多了。
易混點二:BO和PO
PO是持久對象,這個很好理解,就是實體和數據庫字段的對應,一個PO的數據結構對應着庫中表的結構,表中的一條記錄就是一個PO屬性,大多數情況下,PO僅僅作為PO只是用來增刪改使用。
PO比較容易混淆的是BO,BO是業務對象,對應的是某個具體的業務塊,可以包含多個屬性、對象。簡單點來說,我們可以把BO看作是PO的組合。
我們舉例來說明一下:
PO-1是交易記錄對象,PO-2是登錄記錄對象,PO-3是商品瀏覽記錄對象,PO-4是添加購物車記錄對象,PO-5是搜索記錄對象,BO是個人網站行為對象,BO對象:{PO-1;PO-2;PO-3;PO-4;PO-5}。這樣做的優點不言而喻,維護代碼的時候查看BO,就能知道這塊邏輯涉及多少表(PO)。
易混點三:BO和DTO
搞清楚了BO和PO各自的用途后,我們會發現BO和DTO有重疊功能,一樣可以對PO進行排列組合,那BO的存在的意義是什么呢?
從用途上進行根本的區別,BO是業務對象,DTO是數據傳輸對象,雖然BO也可以排列組合數據,但它的功能是對內的,比如上個例子中的BO對象包括{PO-1;PO-2;PO-3;PO-4;PO-5}還有其他字段屬性,但在提供對外接口時,BO對象中的某些屬性對象可能用不到或者不方便對外暴露,那么此時DTO只需要在BO的基礎上,抽取自己需要的數據,然后對外提供。
在這個關系上,通常不會有數據內容的變化,內容變化要么在BO內部業務計算的時候完成,要么在解釋VO的時候完成。
DO
DO是領域對象,就是從現實世界中抽象出來的有形或無形的業務實體。事實上,DO和PO在絕大部分情況下是一一對應的。阿里巴巴的開發手冊中的定義DO等同於PO,即與數據庫表結構一一對應,通過DAO層向上傳輸數據源對象。
上一張圖,更加直觀的展示這些名詞使用的節點:
總結
VO,BO,PO,DTO這樣分層還是很有意義的。尤其在團隊成員較多的情況下,結構更加一目了然,同時也能很大程度避免多端系統數據所需不一致時,有人修改屬性影響其他頁面。但也完全沒有必要教條主義,把這些全部用上,需要根據所開發的業務復雜度來取舍,如果本身業務邏輯不負責,照搬全上反而讓開發變的更復雜。
例如業務不復雜,根本沒有多端展示的差異化,VO可以直接拿掉,直接使用DTO傳輸到前端數據即可。
同時在使用過程中,最重要的是要在團隊中達成共識,概念一致,如果使用了這些,但各按各的理解來,甚至抓起來就直接用,反而會讓代碼變得更亂,還不如直接POJO、DTO打天下。
另附這些概念命名規范:
- 數據對象:xxxPO,xxx即為數據表名。(也可DO)
- 數據傳輸對象:xxxDTO,xxx為業務領域相關的名稱。
- 展示對象:xxxVO,xxx一般為網頁名稱。
- 業務對象:xxxBO,xxx是業務名稱。