分層領域模型規約:session
領域模型命名規約:app
|
=====================
看了這麼多,咱們可能仍是很懵,這麼多內容,要記住是不可能的。必需要理解,多花些時間,徹底理解也是能夠的,可是上面的內容比較繞腦。
總結一下:
DO 就是數據庫的表。這個很簡單。
PO是 ORM框架特有的,好比hibernate中的User類,User類可能有id、username、password等屬性,另外User經過deptId關聯部門表,在hibernate中,其表現就是一個 Dept 引用,而後經過hbm 配置一下,這樣就關聯了起來,另外User 可能還擁有數個聯繫方式,因此咱們經過一個 List 關聯 Contact 類。User類本能夠徹底的映射到 一個數據庫的表,但如今 User類 並無直接 和 User表 一致, 看起來仍是有差異的。 因此這就是 PO。 若是是Mybatis呢? Mybatis雖然也是 ORM框架,但它明顯不一樣於hibernate,通常能夠認爲Mybatis的PO 就是 DO。
DTO 泛指用於展現層與服務層之間的數據傳輸對象,也就是 Controller層與 Service 層 傳輸用的, 也就是Service 層 接口的參數的類型。雖然能夠理解,可是容易和VO 搞混,經常運用很差,DTO 的單向的? 仍是相互的?
VO 視圖對象,用於展現層。 是前端(瀏覽器端)傳給Controller層 的數據的類型, 也就是Controller層 接口的參數的類型。
BO 難以理解,理解了也很差運用。「封裝業務邏輯的 java 對象 , 經過調用 DAO 方法 , 結合 PO,VO 進行業務操做」, 是否是能夠認爲 就是Service類? 不是的,但能夠認爲是Service類中用到的 封裝了PO、VO 的類。—— 這樣說,仍是懵逼。 實際上,我也沒怎麼見過。搞這麼些糾纏不清的難概念,是要生生的把程序員玩殘玩呆逼玩白髮玩禿頂嗎。
DAO 你們用得不少,不解釋了。
TO、AO、POJO,通常不會使用。
Controller層 返回給前端的數據類型呢? 能夠是VO、DTO
======================================
VO與DTO的區別
你們可能會有個疑問(在筆者參與的項目中,不少程序員也有相同的疑惑):既然DTO是展現層與服務層之間傳遞數據的對象,爲何還須要一個VO呢?對!對於絕大部分的應用場景來講,DTO和VO的屬性值基本是一致的,並且他們一般都是POJO,所以不必畫蛇添足。但不要忘記這是實現層面的思惟,對於設計層面來講,概念上仍是應該存在VO和DTO,由於二者有着本質的區別,DTO表明服務層須要接收的數據和返回的數據,而VO表明展現層須要顯示的數據。
用一個例子來講明可能會比較容易理解:例如服務層有一個getUser的方法返回一個系統用戶,其中有一個屬性是gender(性別),對於服務層來講,它只從語義上定義:1-男性,2-女性,0-未指定,而對於展現層來講,它可能須要用「帥哥」表明男性,用「美女」表明女性,用「祕密」表明未指定。說到這裏,可能你還會反駁,在服務層直接就返回「帥哥美女」不就好了嗎?對於大部分應用來講,這不是問題,但設想一下,若是需求容許客戶能夠定製風格,而不一樣風格對於「性別」的表現方式不同,又或者這個服務同時供多個客戶端使用(不一樣門戶),而不一樣的客戶端對於表現層的要求有所不一樣,那麼,問題就來了。再者,回到設計層面上分析,從職責單一原則來看,服務層只負責業務,與具體的表現形式無關,所以,它返回的DTO,不該該出現與表現形式的耦合。
理論歸理論,這到底仍是分析設計層面的思惟,是否在實現層面必須這樣作呢?一刀切的作法每每會得不償失,下面我立刻會分析應用中如何作出正確的選擇。
VO與DTO的應用
上面只是用了一個簡單的例子來講明VO與DTO在概念上的區別,本節將會告訴你如何在應用中作出正確的選擇。
在如下才場景中,咱們能夠考慮把VO與DTO二合爲一(注意:是實現層面):
如下場景須要優先考慮VO、DTO並存:
DTO與DO的區別
首先是概念上的區別,DTO是展現層和服務層之間的數據傳輸對象(能夠認爲是二者之間的協議),而DO是對現實世界各類業務角色的抽象,這就引出了二者在數據上的區別,例如UserInfo和User(對於DTO和DO的命名規則,請參見筆者前面的一篇博文),對於一個getUser方法來講,本質上它永遠不該該返回用戶的密碼,所以UserInfo至少比User少一個password的數據。而在領域驅動設計中,正如第一篇系列文章所說,DO不是簡單的POJO,它具備領域業務邏輯。
DTO與DO的應用
從上一節的例子中,細心的讀者可能會發現問題:既然getUser方法返回的UserInfo不該該包含password,那麼就不該該存在password這個屬性定義,但若是同時有一個createUser的方法,傳入的UserInfo須要包含用戶的password,怎麼辦?在設計層面,展現層向服務層傳遞的DTO與服務層返回給展現層的DTO在概念上是不一樣的,但在實現層面,咱們一般不多會這樣作(定義兩個UserInfo,甚至更多),由於這樣作並不見得很明智,咱們徹底能夠設計一個徹底兼容的DTO,在服務層接收數據的時候,不應由展現層設置的屬性(如訂單的總價應該由其單價、數量、折扣等決定),不管展現層是否設置,服務層都一律忽略,而在服務層返回數據時,不應返回的數據(如用戶密碼),就不設置對應的屬性。
對於DO來講,還有一點須要說明:爲何不在服務層中直接返回DO呢?這樣能夠省去DTO的編碼和轉換工做,緣由以下:
對於DTO來講,也有一點必須進行說明,就是DTO應該是一個「扁平的二維對象」,舉個例子來講明:若是User會關聯若干個其餘實體(例如Address、Account、Region等),那麼getUser()返回的UserInfo,是否就須要把其關聯的對象的DTO都一併返回呢?若是這樣的話,必然致使數據傳輸量的大增,對於分佈式應用來講,因爲涉及數據在網絡上的傳輸、序列化和反序列化,這種設計更不可接受。若是getUser除了要返回User的基本信息外,還須要返回一個AccountId、AccountName、RegionId、RegionName,那麼,請把這些屬性定義到UserInfo中,把一個「立體」的對象樹「壓扁」成一個「扁平的二維對象」。筆者目前參與的項目是一個分佈式系統,該系統無論三七二十一,把一個對象的全部關聯對象都轉換爲相同結構的DTO對象樹並返回,致使性能很是的慢。
DO與PO的區別
DO和PO在絕大部分狀況下是一一對應的,PO是隻含有get/set方法的POJO,但某些場景仍是能反映出二者在概念上存在本質的區別:
DO與PO的應用
因爲ORM框架的功能很是強大而大行其道,並且JavaEE也推出了JPA規範,如今的業務應用開發,基本上不須要區分DO與PO,PO徹底能夠經過JPA,Hibernate Annotations/hbm隱藏在DO之中。雖然如此,但有些問題咱們還必須注意:
到目前爲止,相信你們都已經比較清晰的瞭解VO、DTO、DO、PO的概念、區別和實際應用了。經過上面的詳細分析,咱們還能夠總結出一個原則:分析設計層面和實現層面徹底是兩個獨立的層面,即便實現層面經過某種技術手段能夠把兩個徹底獨立的概念合二爲一,在分析設計層面,咱們仍然(至少在頭腦中)須要把概念上獨立的東西清晰的區分開來,這個原則對於作好分析設計很是重要(工具越先進,每每會讓咱們越麻木)。第一篇系列博文拋磚引玉,大唱領域驅動設計的優點,但其實領域驅動設計在現實環境中仍是有種種的限制,須要選擇性的使用,正如我在《田七的智慧》博文中提到,咱們不能永遠的理想化的去選擇所謂「最好的設計」,在必要的狀況下,咱們仍是要勇於放棄,由於最合適的設計纔是最好的設計。原本,系列中的第二篇博文應該是討論領取驅動設計的限制和如何選擇性的使用,但請原諒個人疏忽,下一篇系列博文會把這個主題補上,敬請關注。
=======================================
bo dto vo po有必要劃分這麼清楚嗎
咱們作各類分層,而後呢,爲每一層與其餘層的有向傳輸的數據 分別命名,這樣,咱們就產生了不少的XxxO,
前端到Controller的能夠命名一個VO,
Controller到Service的能夠命名一個DTO,
Service到DAO的能夠命名一個PO,
DAO返回給Service的能夠命名一個DO,
Service到Controller的能夠命名一個BO,
Service到前端的能夠命名一個XxO,
理論上這樣固然是能夠的,可是,若是 VO、DTO、PO、DO、BO、XxO 的字段基本是同樣的, 這樣作太死板了~!
不可缺乏的顯然是DO,有時候,咱們可能會看到一些不規範的命名,好比model層,XxxModel,XxxEntity, 其實就是DO。
我以前看到有的項目,所有的傳輸參數類型基本都是 DO,根本不須要其餘的O,省去了 O們之間相互轉化的麻煩,大大提升了 代碼的可讀性。
雖然如此,咱們不能一刀切,簡單的項目,所有都共用一個DO,也問題不大,可是若是大項目,須要考慮 良好的設計, 那麼增長一個VO、DTO 也不是不能夠的。轉化起來雖然有些麻煩,可是各O的含義是明確的。
因此呢? 仍是按狀況來。我就是一直很是反感那種動不動一個XxO的人,看到那些醜陋的 O之間轉換的代碼,嚴重影響了可讀性和美觀。我建議不要太多O,通常使用DTO、DO 就能夠了。DTO定義在Controller層,DO定義在DAO層
大部分轉載至:
https://www.cnblogs.com/tsiangleo/p/4550355.html
http://www.blogjava.net/johnnylzb/archive/2010/05/27/321968.html