<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    Johnny's Collections

    生活總是有太多的無(wú)奈與失望,讓我們以在努力學(xué)習(xí)和工作中獲得的成就感和快樂(lè)來(lái)沖淡它們。

    BlogJava 首頁(yè) 新隨筆 聯(lián)系 聚合 管理
      10 Posts :: 0 Stories :: 80 Comments :: 0 Trackbacks

    上一篇文章作為一個(gè)引子,說(shuō)明了領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)的優(yōu)勢(shì),從本篇文章開(kāi)始,筆者將會(huì)結(jié)合自己的實(shí)際經(jīng)驗(yàn),談及領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)的應(yīng)用。本篇文章主要討論一下我們經(jīng)常會(huì)用到的一些對(duì)象:VODTODOPO

    由于不同的項(xiàng)目和開(kāi)發(fā)人員有不同的命名習(xí)慣,這里我首先對(duì)上述的概念進(jìn)行一個(gè)簡(jiǎn)單描述,名字只是個(gè)標(biāo)識(shí),我們重點(diǎn)關(guān)注其概念:

     

    概念:

    VOView Object):視圖對(duì)象,用于展示層,它的作用是把某個(gè)指定頁(yè)面(或組件)的所有數(shù)據(jù)封裝起來(lái)。

    DTOData Transfer Object):數(shù)據(jù)傳輸對(duì)象,這個(gè)概念來(lái)源于J2EE的設(shè)計(jì)模式,原來(lái)的目的是為了EJB的分布式應(yīng)用提供粗粒度的數(shù)據(jù)實(shí)體,以減少分布式調(diào)用的次數(shù),從而提高分布式調(diào)用的性能和降低網(wǎng)絡(luò)負(fù)載,但在這里,我泛指用于展示層與服務(wù)層之間的數(shù)據(jù)傳輸對(duì)象。

    DODomain Object):領(lǐng)域?qū)ο螅褪菑默F(xiàn)實(shí)世界中抽象出來(lái)的有形或無(wú)形的業(yè)務(wù)實(shí)體。

    POPersistent Object):持久化對(duì)象,它跟持久層(通常是關(guān)系型數(shù)據(jù)庫(kù))的數(shù)據(jù)結(jié)構(gòu)形成一一對(duì)應(yīng)的映射關(guān)系,如果持久層是關(guān)系型數(shù)據(jù)庫(kù),那么,數(shù)據(jù)表中的每個(gè)字段(或若干個(gè))就對(duì)應(yīng)PO的一個(gè)(或若干個(gè))屬性。

     

    模型:

           下面以一個(gè)時(shí)序圖建立簡(jiǎn)單模型來(lái)描述上述對(duì)象在三層架構(gòu)應(yīng)用中的位置


     

          

    l         用戶(hù)發(fā)出請(qǐng)求(可能是填寫(xiě)表單),表單的數(shù)據(jù)在展示層被匹配為VO

    l         展示層把VO轉(zhuǎn)換為服務(wù)層對(duì)應(yīng)方法所要求的DTO,傳送給服務(wù)層。

    l         服務(wù)層首先根據(jù)DTO的數(shù)據(jù)構(gòu)造(或重建)一個(gè)DO,調(diào)用DO的業(yè)務(wù)方法完成具體業(yè)務(wù)。

    l         服務(wù)層把DO轉(zhuǎn)換為持久層對(duì)應(yīng)的PO(可以使用ORM工具,也可以不用),調(diào)用持久層的持久化方法,把PO傳遞給它,完成持久化操作。

    l         對(duì)于一個(gè)逆向操作,如讀取數(shù)據(jù),也是用類(lèi)似的方式轉(zhuǎn)換和傳遞,略。

     

    VODTO的區(qū)別

           大家可能會(huì)有個(gè)疑問(wèn)(在筆者參與的項(xiàng)目中,很多程序員也有相同的疑惑):既然DTO是展示層與服務(wù)層之間傳遞數(shù)據(jù)的對(duì)象,為什么還需要一個(gè)VO呢?對(duì)!對(duì)于絕大部分的應(yīng)用場(chǎng)景來(lái)說(shuō),DTOVO的屬性值基本是一致的,而且他們通常都是POJO,因此沒(méi)必要多此一舉,但不要忘記這是實(shí)現(xiàn)層面的思維,對(duì)于設(shè)計(jì)層面來(lái)說(shuō),概念上還是應(yīng)該存在VODTO,因?yàn)閮烧哂兄举|(zhì)的區(qū)別,DTO代表服務(wù)層需要接收的數(shù)據(jù)和返回的數(shù)據(jù),而VO代表展示層需要顯示的數(shù)據(jù)。

           用一個(gè)例子來(lái)說(shuō)明可能會(huì)比較容易理解:例如服務(wù)層有一個(gè)getUser的方法返回一個(gè)系統(tǒng)用戶(hù),其中有一個(gè)屬性是gender(性別),對(duì)于服務(wù)層來(lái)說(shuō),它只從語(yǔ)義上定義:1-男性,2-女性,0-未指定,而對(duì)于展示層來(lái)說(shuō),它可能需要用“帥哥”代表男性,用“美女”代表女性,用“秘密”代表未指定。說(shuō)到這里,可能你還會(huì)反駁,在服務(wù)層直接就返回“帥哥美女”不就行了嗎?對(duì)于大部分應(yīng)用來(lái)說(shuō),這不是問(wèn)題,但設(shè)想一下,如果需求允許客戶(hù)可以定制風(fēng)格,而不同風(fēng)格對(duì)于“性別”的表現(xiàn)方式不一樣,又或者這個(gè)服務(wù)同時(shí)供多個(gè)客戶(hù)端使用(不同門(mén)戶(hù)),而不同的客戶(hù)端對(duì)于表現(xiàn)層的要求有所不同,那么,問(wèn)題就來(lái)了。再者,回到設(shè)計(jì)層面上分析,從職責(zé)單一原則來(lái)看,服務(wù)層只負(fù)責(zé)業(yè)務(wù),與具體的表現(xiàn)形式無(wú)關(guān),因此,它返回的DTO,不應(yīng)該出現(xiàn)與表現(xiàn)形式的耦合。

           理論歸理論,這到底還是分析設(shè)計(jì)層面的思維,是否在實(shí)現(xiàn)層面必須這樣做呢?一刀切的做法往往會(huì)得不償失,下面我馬上會(huì)分析應(yīng)用中如何做出正確的選擇。

     

    VODTO的應(yīng)用

           上面只是用了一個(gè)簡(jiǎn)單的例子來(lái)說(shuō)明VODTO在概念上的區(qū)別,本節(jié)將會(huì)告訴你如何在應(yīng)用中做出正確的選擇。

           在以下才場(chǎng)景中,我們可以考慮把VODTO二合為一(注意:是實(shí)現(xiàn)層面):

    l         當(dāng)需求非常清晰穩(wěn)定,而且客戶(hù)端很明確只有一個(gè)的時(shí)候,沒(méi)有必要把VODTO區(qū)分開(kāi)來(lái),這時(shí)候VO可以退隱,用一個(gè)DTO即可,為什么是VO退隱而不是DTO?回到設(shè)計(jì)層面,服務(wù)層的職責(zé)依然不應(yīng)該與展示層耦合,所以,對(duì)于前面的例子,你很容易理解,DTO對(duì)于“性別”來(lái)說(shuō),依然不能用“帥哥美女”,這個(gè)轉(zhuǎn)換應(yīng)該依賴(lài)于頁(yè)面的腳本(如JavaScript)或其他機(jī)制(JSTLELCSS

    l         即使客戶(hù)端可以進(jìn)行定制,或者存在多個(gè)不同的客戶(hù)端,如果客戶(hù)端能夠用某種技術(shù)(腳本或其他機(jī)制)實(shí)現(xiàn)轉(zhuǎn)換,同樣可以讓VO退隱

     

    以下場(chǎng)景需要優(yōu)先考慮VODTO并存:

    l         上述場(chǎng)景的反面場(chǎng)景

    l         因?yàn)槟撤N技術(shù)原因,比如某個(gè)框架(如Flex)提供自動(dòng)把POJO轉(zhuǎn)換為UI中某些Field時(shí),可以考慮在實(shí)現(xiàn)層面定義出VO,這個(gè)權(quán)衡完全取決于使用框架的自動(dòng)轉(zhuǎn)換能力帶來(lái)的開(kāi)發(fā)和維護(hù)效率提升與設(shè)計(jì)多一個(gè)VO所多做的事情帶來(lái)的開(kāi)發(fā)和維護(hù)效率的下降之間的比對(duì)。

    l         如果頁(yè)面出現(xiàn)一個(gè)“大視圖”,而組成這個(gè)大視圖的所有數(shù)據(jù)需要調(diào)用多個(gè)服務(wù),返回多個(gè)DTO來(lái)組裝(當(dāng)然,這同樣可以通過(guò)服務(wù)層提供一次性返回一個(gè)大視圖的DTO來(lái)取代,但在服務(wù)層提供一個(gè)這樣的方法是否合適,需要在設(shè)計(jì)層面進(jìn)行權(quán)衡)。

     

    DTODO的區(qū)別

           首先是概念上的區(qū)別,DTO是展示層和服務(wù)層之間的數(shù)據(jù)傳輸對(duì)象(可以認(rèn)為是兩者之間的協(xié)議),而DO是對(duì)現(xiàn)實(shí)世界各種業(yè)務(wù)角色的抽象,這就引出了兩者在數(shù)據(jù)上的區(qū)別,例如UserInfoUser(對(duì)于DTODO的命名規(guī)則,請(qǐng)參見(jiàn)筆者前面的一篇博文),對(duì)于一個(gè)getUser方法來(lái)說(shuō),本質(zhì)上它永遠(yuǎn)不應(yīng)該返回用戶(hù)的密碼,因此UserInfo至少比User少一個(gè)password的數(shù)據(jù)。而在領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)中,正如第一篇系列文章所說(shuō),DO不是簡(jiǎn)單的POJO,它具有領(lǐng)域業(yè)務(wù)邏輯。

     

    DTODO的應(yīng)用

           從上一節(jié)的例子中,細(xì)心的讀者可能會(huì)發(fā)現(xiàn)問(wèn)題:既然getUser方法返回的UserInfo不應(yīng)該包含password,那么就不應(yīng)該存在password這個(gè)屬性定義,但如果同時(shí)有一個(gè)createUser的方法,傳入的UserInfo需要包含用戶(hù)的password,怎么辦?在設(shè)計(jì)層面,展示層向服務(wù)層傳遞的DTO與服務(wù)層返回給展示層的DTO在概念上是不同的,但在實(shí)現(xiàn)層面,我們通常很少會(huì)這樣做(定義兩個(gè)UserInfo,甚至更多),因?yàn)檫@樣做并不見(jiàn)得很明智,我們完全可以設(shè)計(jì)一個(gè)完全兼容的DTO,在服務(wù)層接收數(shù)據(jù)的時(shí)候,不該由展示層設(shè)置的屬性(如訂單的總價(jià)應(yīng)該由其單價(jià)、數(shù)量、折扣等決定),無(wú)論展示層是否設(shè)置,服務(wù)層都一概忽略,而在服務(wù)層返回?cái)?shù)據(jù)時(shí),不該返回的數(shù)據(jù)(如用戶(hù)密碼),就不設(shè)置對(duì)應(yīng)的屬性。

           對(duì)于DO來(lái)說(shuō),還有一點(diǎn)需要說(shuō)明:為什么不在服務(wù)層中直接返回DO呢?這樣可以省去DTO的編碼和轉(zhuǎn)換工作,原因如下:

    l         兩者在本質(zhì)上的區(qū)別可能導(dǎo)致彼此并不一一對(duì)應(yīng),一個(gè)DTO可能對(duì)應(yīng)多個(gè)DO,反之亦然,甚至兩者存在多對(duì)多的關(guān)系。

    l         DO具有一些不應(yīng)該讓展示層知道的數(shù)據(jù)

    l         DO具有業(yè)務(wù)方法,如果直接把DO傳遞給展示層,展示層的代碼就可以繞過(guò)服務(wù)層直接調(diào)用它不應(yīng)該訪問(wèn)的操作,對(duì)于基于AOP攔截服務(wù)層來(lái)進(jìn)行訪問(wèn)控制的機(jī)制來(lái)說(shuō),這問(wèn)題尤為突出,而在展示層調(diào)用DO的業(yè)務(wù)方法也會(huì)因?yàn)槭聞?wù)的問(wèn)題,讓事務(wù)難以控制。

    l         對(duì)于某些ORM框架(如Hibernate)來(lái)說(shuō),通常會(huì)使用“延遲加載”技術(shù),如果直接把DO暴露給展示層,對(duì)于大部分情況,展示層不在事務(wù)范圍之內(nèi)(Open session in view在大部分情況下不是一種值得推崇的設(shè)計(jì)),如果其嘗試在Session關(guān)閉的情況下獲取一個(gè)未加載的關(guān)聯(lián)對(duì)象,會(huì)出現(xiàn)運(yùn)行時(shí)異常(對(duì)于Hibernate來(lái)說(shuō),就是LazyInitiliaztionException)。

    l         從設(shè)計(jì)層面來(lái)說(shuō),展示層依賴(lài)于服務(wù)層,服務(wù)層依賴(lài)于領(lǐng)域?qū)樱绻?/span>DO暴露出去,就會(huì)導(dǎo)致展示層直接依賴(lài)于領(lǐng)域?qū)樱@雖然依然是單向依賴(lài),但這種跨層依賴(lài)會(huì)導(dǎo)致不必要的耦合。

     

    對(duì)于DTO來(lái)說(shuō),也有一點(diǎn)必須進(jìn)行說(shuō)明,就是DTO應(yīng)該是一個(gè)“扁平的二維對(duì)象”,舉個(gè)例子來(lái)說(shuō)明:如果User會(huì)關(guān)聯(lián)若干個(gè)其他實(shí)體(例如AddressAccountRegion等),那么getUser()返回的UserInfo,是否就需要把其關(guān)聯(lián)的對(duì)象的DTO都一并返回呢?如果這樣的話(huà),必然導(dǎo)致數(shù)據(jù)傳輸量的大增,對(duì)于分布式應(yīng)用來(lái)說(shuō),由于涉及數(shù)據(jù)在網(wǎng)絡(luò)上的傳輸、序列化和反序列化,這種設(shè)計(jì)更不可接受。如果getUser除了要返回User的基本信息外,還需要返回一個(gè)AccountIdAccountNameRegionIdRegionName,那么,請(qǐng)把這些屬性定義到UserInfo中,把一個(gè)“立體”的對(duì)象樹(shù)“壓扁”成一個(gè)“扁平的二維對(duì)象”,筆者目前參與的項(xiàng)目是一個(gè)分布式系統(tǒng),該系統(tǒng)不管三七二十一,把一個(gè)對(duì)象的所有關(guān)聯(lián)對(duì)象都轉(zhuǎn)換為相同結(jié)構(gòu)的DTO對(duì)象樹(shù)并返回,導(dǎo)致性能非常的慢。

     

     

    DOPO的區(qū)別

           DOPO在絕大部分情況下是一一對(duì)應(yīng)的,PO是只含有get/set方法的POJO,但某些場(chǎng)景還是能反映出兩者在概念上存在本質(zhì)的區(qū)別:

    l         DO在某些場(chǎng)景下不需要進(jìn)行顯式的持久化,例如利用策略模式設(shè)計(jì)的商品折扣策略,會(huì)衍生出折扣策略的接口和不同折扣策略實(shí)現(xiàn)類(lèi),這些折扣策略實(shí)現(xiàn)類(lèi)可以算是DO,但它們只駐留在靜態(tài)內(nèi)存,不需要持久化到持久層,因此,這類(lèi)DO是不存在對(duì)應(yīng)的PO的。

    l         同樣的道理,某些場(chǎng)景下,PO也沒(méi)有對(duì)應(yīng)的DO,例如老師Teacher和學(xué)生Student存在多對(duì)多的關(guān)系,在關(guān)系數(shù)據(jù)庫(kù)中,這種關(guān)系需要表現(xiàn)為一個(gè)中間表,也就對(duì)應(yīng)有一個(gè)TeacherAndStudentPOPO,但這個(gè)PO在業(yè)務(wù)領(lǐng)域沒(méi)有任何現(xiàn)實(shí)的意義,它完全不能與任何DO對(duì)應(yīng)上。這里要特別聲明,并不是所有多對(duì)多關(guān)系都沒(méi)有業(yè)務(wù)含義,這跟具體業(yè)務(wù)場(chǎng)景有關(guān),例如:兩個(gè)PO之間的關(guān)系會(huì)影響具體業(yè)務(wù),并且這種關(guān)系存在多種類(lèi)型,那么這種多對(duì)多關(guān)系也應(yīng)該表現(xiàn)為一個(gè)DO,又如:“角色”與“資源”之間存在多對(duì)多關(guān)系,而這種關(guān)系很明顯會(huì)表現(xiàn)為一個(gè)DO——“權(quán)限”。

    l         某些情況下,為了某種持久化策略或者性能的考慮,一個(gè)PO可能對(duì)應(yīng)多個(gè)DO,反之亦然。例如客戶(hù)Customer有其聯(lián)系信息Contacts,這里是兩個(gè)一對(duì)一關(guān)系的DO,但可能出于性能的考慮(極端情況,權(quán)作舉例),為了減少數(shù)據(jù)庫(kù)的連接查詢(xún)操作,把CustomerContacts兩個(gè)DO數(shù)據(jù)合并到一張數(shù)據(jù)表中。反過(guò)來(lái),如果一本圖書(shū)Book,有一個(gè)屬性是封面cover,但該屬性是一副圖片的二進(jìn)制數(shù)據(jù),而某些查詢(xún)操作不希望把cover一并加載,從而減輕磁盤(pán)IO開(kāi)銷(xiāo),同時(shí)假設(shè)ORM框架不支持屬性級(jí)別的延遲加載,那么就需要考慮把cover獨(dú)立到一張數(shù)據(jù)表中去,這樣就形成一個(gè)DO對(duì)應(yīng)對(duì)個(gè)PO的情況。

    l         PO的某些屬性值對(duì)于DO沒(méi)有任何意義,這些屬性值可能是為了解決某些持久化策略而存在的數(shù)據(jù),例如為了實(shí)現(xiàn)“樂(lè)觀鎖”,PO存在一個(gè)version的屬性,這個(gè)version對(duì)于DO來(lái)說(shuō)是沒(méi)有任何業(yè)務(wù)意義的,它不應(yīng)該在DO中存在。同理,DO中也可能存在不需要持久化的屬性。

     

    DOPO的應(yīng)用

           由于ORM框架的功能非常強(qiáng)大而大行其道,而且JavaEE也推出了JPA規(guī)范,現(xiàn)在的業(yè)務(wù)應(yīng)用開(kāi)發(fā),基本上不需要區(qū)分DOPOPO完全可以通過(guò)JPAHibernate Annotations/hbm隱藏在DO之中。雖然如此,但有些問(wèn)題我們還必須注意:

    l         對(duì)于DO中不需要持久化的屬性,需要通過(guò)ORM顯式的聲明,如:在JPA中,可以利用@Transient聲明。

    l         對(duì)于PO中為了某種持久化策略而存在的屬性,例如version,由于DOPO合并了,必須在DO中聲明,但由于這個(gè)屬性對(duì)DO是沒(méi)有任何業(yè)務(wù)意義的,需要讓該屬性對(duì)外隱藏起來(lái),最常見(jiàn)的做法是把該屬性的get/set方法私有化,甚至不提供get/set方法,但對(duì)于Hibernate來(lái)說(shuō),這需要特別注意,由于Hibernate從數(shù)據(jù)庫(kù)讀取數(shù)據(jù)轉(zhuǎn)換為DO時(shí),是利用反射機(jī)制先調(diào)用DO的空參數(shù)構(gòu)造函數(shù)構(gòu)造DO實(shí)例,然后再利用JavaBean的規(guī)范反射出set方法來(lái)為每個(gè)屬性設(shè)值,如果不顯式聲明set方法,或把set方法設(shè)置為private,都會(huì)導(dǎo)致Hibernate無(wú)法初始化DO,從而出現(xiàn)運(yùn)行時(shí)異常,可行的做法是把屬性的set方法設(shè)置為protected

    l         對(duì)于一個(gè)DO對(duì)應(yīng)多個(gè)PO,或者一個(gè)PO對(duì)應(yīng)多個(gè)DO的場(chǎng)景,以及屬性級(jí)別的延遲加載,Hibernate都提供了很好的支持,請(qǐng)參考Hibnate的相關(guān)資料。

     

     

        到目前為止,相信大家都已經(jīng)比較清晰的了解VODTODOPO的概念、區(qū)別和實(shí)際應(yīng)用了。通過(guò)上面的詳細(xì)分析,我們還可以總結(jié)出一個(gè)原則:分析設(shè)計(jì)層面和實(shí)現(xiàn)層面完全是兩個(gè)獨(dú)立的層面,即使實(shí)現(xiàn)層面通過(guò)某種技術(shù)手段可以把兩個(gè)完全獨(dú)立的概念合二為一,在分析設(shè)計(jì)層面,我們?nèi)匀唬ㄖ辽僭陬^腦中)需要把概念上獨(dú)立的東西清晰的區(qū)分開(kāi)來(lái),這個(gè)原則對(duì)于做好分析設(shè)計(jì)非常重要(工具越先進(jìn),往往會(huì)讓我們?cè)铰槟荆5谝黄盗胁┪膾伌u引玉,大唱領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)的優(yōu)勢(shì),但其實(shí)領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)在現(xiàn)實(shí)環(huán)境中還是有種種的限制,需要選擇性的使用,正如我在《田七的智慧》博文中提到,我們不能永遠(yuǎn)的理想化的去選擇所謂“最好的設(shè)計(jì)”,在必要的情況下,我們還是要敢于放棄,因?yàn)樽詈线m的設(shè)計(jì)才是最好的設(shè)計(jì)。本來(lái),系列中的第二篇博文應(yīng)該是討論領(lǐng)取驅(qū)動(dòng)設(shè)計(jì)的限制和如何選擇性的使用,但請(qǐng)?jiān)徫业氖韬觯乱黄盗胁┪臅?huì)把這個(gè)主題補(bǔ)上,敬請(qǐng)關(guān)注。
    posted on 2010-05-27 00:07 Johnny.Liang 閱讀(38247) 評(píng)論(16)  編輯  收藏 所屬分類(lèi): 系統(tǒng)設(shè)計(jì)

    Feedback

    # re: 領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)系列文章(2)——淺析VO、DTO、DO、PO的概念、區(qū)別和用處 2010-05-27 11:26 瀟湘振宇
    很好,講解的很詳細(xì)。理念終歸是理念,實(shí)際應(yīng)用確實(shí)是需要視各各應(yīng)用場(chǎng)景來(lái)定。始終相信“沒(méi)有最好的設(shè)計(jì),只有最合適的設(shè)計(jì)”。
    加油:) 繼續(xù)期待您的下篇博文。  回復(fù)  更多評(píng)論
      

    # re: 領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)系列文章(2)——淺析VO、DTO、DO、PO的概念、區(qū)別和用處 2010-06-25 15:41 Aidan
    不需要password?那我請(qǐng)問(wèn)客戶(hù)端要登錄,你這個(gè)密碼怎么傳入服務(wù)器->DAO進(jìn)行比較?
    還有前面見(jiàn)你對(duì)名字發(fā)表了一篇文章,假如我有VO,DTO,DO,PO都有你是怎么命名的,我見(jiàn)你在前面發(fā)表了一下不應(yīng)該使用DTO為后綴之類(lèi)的。  回復(fù)  更多評(píng)論
      

    # re: 領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)系列文章(2)——淺析VO、DTO、DO、PO的概念、區(qū)別和用處[未登錄](méi) 2010-06-25 20:47 Johnny.Liang
    @Aidan
    很好的問(wèn)題,我逐個(gè)回答:
    1.我所說(shuō)的不需要password,是值在DTO層面,同一個(gè)UserInfo(我在一篇博文中建議以***Info命名DTO,意為***信息),其實(shí)對(duì)于不同的場(chǎng)景,本質(zhì)上是不同的,例如,我有個(gè)注冊(cè)用戶(hù)的方法,需要傳入U(xiǎn)serInfo,那么逐個(gè)DTO必須擁有一些用戶(hù)認(rèn)證或隱私信息的屬性,但對(duì)于查詢(xún)用戶(hù)的方法,它返回的也是一個(gè)UserInfo,但這個(gè)UserInfo,從需求來(lái)說(shuō),它不應(yīng)該包含密碼和隱私信息,那么這兩個(gè)雖然都是UserInfo,但理論上應(yīng)該定義為兩個(gè)獨(dú)立的DTO,但實(shí)際上,這樣做帶來(lái)的負(fù)面影響會(huì)更大,因?yàn)槲以谝粋€(gè)系統(tǒng)中可能要為一個(gè)實(shí)體定義太多的DTO,所以我建議定義一個(gè)包羅萬(wàn)有的DTO,但在返回?cái)?shù)據(jù)時(shí),如果有些數(shù)據(jù)不應(yīng)該返回,就把屬性設(shè)置為null即可,當(dāng)然SOA中的SDO有另外的做法,這里不詳說(shuō),本人也不甚精通。

    2.對(duì)于VO,DTO,DO,PO的命名,我個(gè)人的建議(純屬個(gè)人意見(jiàn)),還是不要太過(guò)技術(shù)化,VO可以叫***View,代表一個(gè)”視圖“,DTO用***Info,代表”***的信息“,DO由于是就是業(yè)務(wù)實(shí)體本身,所以直接給它一個(gè)釋意名稱(chēng),如User、Customer……,至于PO,正如我所說(shuō),現(xiàn)在的ORM框架已經(jīng)可以把這個(gè)東西在實(shí)現(xiàn)層面通過(guò)配置文件(xml)或annonation隱藏起來(lái),所以在實(shí)現(xiàn)層面基本不需要存在,如果確實(shí)需要的話(huà),我覺(jué)得”持久化“本身就是計(jì)算機(jī)世界的一個(gè)非業(yè)務(wù)領(lǐng)域,這里用技術(shù)化命名完全沒(méi)有問(wèn)題,因?yàn)樗_實(shí)是”技術(shù)化產(chǎn)物“,在業(yè)務(wù)領(lǐng)域沒(méi)有這個(gè)概念。這相信也同樣回答了你在另外一篇博文提出的問(wèn)題。

    希望我的回答能讓你滿(mǎn)意。  回復(fù)  更多評(píng)論
      

    # re: 領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)系列文章(2)——淺析VO、DTO、DO、PO的概念、區(qū)別和用處 2010-06-25 23:07 Aidan
    首先非常感謝你這么詳細(xì)的回答。還有一個(gè)問(wèn)題。
    你前一篇貼的做法是BO需要與DAO偶合,這個(gè)時(shí)候我們使用IOC窗口時(shí),你們是怎么來(lái)做的呢?從service構(gòu)造傳過(guò)去嗎?  回復(fù)  更多評(píng)論
      

    # re: 領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)系列文章(2)——淺析VO、DTO、DO、PO的概念、區(qū)別和用處 2010-06-25 23:08 Aidan
    我們使用IOC容器的時(shí)候,你們是如何把DAO對(duì)象注入到BO對(duì)象里面去的。  回復(fù)  更多評(píng)論
      

    # re: 領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)系列文章(2)——淺析VO、DTO、DO、PO的概念、區(qū)別和用處 2010-06-26 00:57 Johnny.Liang
    @Aidan
    呵呵,謝謝你的持續(xù)關(guān)注,你這個(gè)問(wèn)題同樣很好,我也曾經(jīng)被這個(gè)問(wèn)題困擾,你所說(shuō)的從構(gòu)造函數(shù)傳入,從技術(shù)角度來(lái)講,是一種可行的辦法,但我不建議這樣做,原因是:
    1)DO(即你所說(shuō)的BO)從業(yè)務(wù)上來(lái)講,不應(yīng)該與DAO有關(guān)聯(lián),因?yàn)镈AO對(duì)于業(yè)務(wù)來(lái)說(shuō)是沒(méi)有意義的,它屬于應(yīng)用方面的東西。DO構(gòu)造函數(shù)只能包括用于構(gòu)造它的所必須的元素(我后面的博文會(huì)提及)。
    2)這樣做會(huì)讓DO與你的具體實(shí)現(xiàn)耦合,試想,如果某天有某種更好的方法讓你動(dòng)態(tài)注入DAO,意味著你不再需要通過(guò)構(gòu)造函數(shù)傳入DAO了,那么你是繼續(xù)保留這個(gè)參數(shù),還是修改構(gòu)造函數(shù),從而讓所有調(diào)用該構(gòu)造函數(shù)的客戶(hù)程序受到影響呢?

    事實(shí)上,可行的做法有兩種:
    1)利用Spring提供的“動(dòng)態(tài)注入”方式,這種方式的原理是,通過(guò)一個(gè)Annotation,告訴Spring容器,這個(gè)DO是需要注入對(duì)象的,即需要受到SpringIoC容器管理,那么Spring就會(huì)利用“編譯時(shí)織入”或“啟動(dòng)時(shí)織入”的技術(shù)來(lái)為DO的Class類(lèi)織入注入相關(guān)對(duì)象的代碼,這種技術(shù)依賴(lài)于AspectJ,前者更加需要在編譯環(huán)境加入AspectJ的增量編譯器,這種方案是相對(duì)麻煩的,而且我曾經(jīng)在OSGi中應(yīng)用,會(huì)出現(xiàn)一些不可預(yù)知的問(wèn)題導(dǎo)致無(wú)法注入。

    2)在你的應(yīng)用(通常是Web應(yīng)用)加載SpringContext的時(shí)候,設(shè)計(jì)一個(gè)用于保持SpringContext的ContextHolder,利用某種機(jī)制(例如Spring提供的Servlet)來(lái)在加載SpringContext的時(shí)候,把SpringContext的引用保留在該ContextHolder中,然后在你的DO里面,就可以在實(shí)現(xiàn)代碼里面通過(guò)ContextHolder提供的靜態(tài)方法,獲取到你所需要的Bean了。  回復(fù)  更多評(píng)論
      

    # re: 領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)系列文章(2)——淺析VO、DTO、DO、PO的概念、區(qū)別和用處[未登錄](méi) 2010-07-01 14:35 DDD
    我現(xiàn)在有個(gè)疑問(wèn),就是關(guān)于VO是否將頁(yè)面的查詢(xún)條件字段也包括在內(nèi)?想聽(tīng)聽(tīng)博主的見(jiàn)解。。  回復(fù)  更多評(píng)論
      

    # re: 領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)系列文章(2)——淺析VO、DTO、DO、PO的概念、區(qū)別和用處 2010-07-01 17:38 Johnny.Liang
    @DDD
    對(duì),但頁(yè)面查詢(xún)用的VO,與表示某個(gè)實(shí)體的VO不是同一樣?xùn)|西,如果按我的博文中合并VO與DTO的說(shuō)法,舉個(gè)例子,User,對(duì)應(yīng)的信息DTO應(yīng)該是UserInfo,而對(duì)應(yīng)的查詢(xún)User的DTO應(yīng)該是另外一個(gè),通常我用UserSearchCriteria來(lái)代替,為什么要把UserInfo和UserSearchCriteria區(qū)分開(kāi)來(lái)?你可能認(rèn)為,UserInfo中大部分屬性,都是可以用于查詢(xún)的,所以沒(méi)必要弄多一個(gè)UserSearchCriteria,但事實(shí)上,它們本質(zhì)上是兩樣?xùn)|西來(lái)的,比如,UserInfo有一個(gè)birthday的屬性,但對(duì)于查詢(xún)來(lái)說(shuō),系統(tǒng)可能要求查詢(xún)某個(gè)時(shí)間段內(nèi)出生的User,這個(gè)時(shí)候,UserSearchCirteria就要定義兩個(gè)屬性birthdayFrom,birthdayTo了,所以可以看出,兩者只是“表面上相似”,本質(zhì)上是兩樣?xùn)|西,為了設(shè)計(jì)上的靈活性和擴(kuò)展性,即使當(dāng)前情況下兩者的屬性一致,也需要分別進(jìn)行設(shè)計(jì)。  回復(fù)  更多評(píng)論
      

    # re: 領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)系列文章(2)——淺析VO、DTO、DO、PO的概念、區(qū)別和用處 2010-07-23 14:03 isnumeric
    @Johnny.Liang
    請(qǐng)問(wèn)博主,如果日期范圍查詢(xún)的時(shí)候,不能直接用PO去調(diào)用DAO的方法,因?yàn)镻O不會(huì)有開(kāi)始之期和結(jié)束日期這兩個(gè)屬性,HQL語(yǔ)句如果是根據(jù)業(yè)務(wù)邏輯生成的,是否也放在Service層,還是放在DAO里呢?  回復(fù)  更多評(píng)論
      

    # re: 領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)系列文章(2)——淺析VO、DTO、DO、PO的概念、區(qū)別和用處 2010-08-06 00:05 Johnny.Liang
    @isnumeric
    PO應(yīng)該是我系列博文所說(shuō)的DTO,它是實(shí)體的信息封裝對(duì)象,本質(zhì)上與“實(shí)體的查詢(xún)信息封裝對(duì)象”是不同的,因此最好提供一個(gè)Criteria來(lái)封裝查詢(xún)屬性。

    HQL絕對(duì)不能封裝在Service中,因?yàn)镠QL涉及數(shù)據(jù)訪問(wèn)邏輯,應(yīng)該封裝在數(shù)據(jù)訪問(wèn)層中,業(yè)務(wù)層可以傳入生成HQL的相關(guān)數(shù)據(jù),由DAO把這些數(shù)據(jù)轉(zhuǎn)換為HQL,但Service絕對(duì)不要傳入任何與數(shù)據(jù)訪問(wèn)實(shí)現(xiàn)細(xì)節(jié)有關(guān)的數(shù)據(jù),否則Service就被耦合了。  回復(fù)  更多評(píng)論
      

    # re: 領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)系列文章(2)——淺析VO、DTO、DO、PO的概念、區(qū)別和用處[未登錄](méi) 2011-03-04 02:42 Terry
    寫(xiě)的非常好,我收益匪淺啊,解決了我的不少疑惑,尤其是設(shè)計(jì)層面和實(shí)現(xiàn)層面上的區(qū)別。謝謝樓主  回復(fù)  更多評(píng)論
      

    # re: 領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)系列文章(2)——淺析VO、DTO、DO、PO的概念、區(qū)別和用處 2013-10-18 12:50 老唐
    寫(xiě)的不錯(cuò),一看就是做過(guò)n多的項(xiàng)目設(shè)計(jì)才能夠表達(dá)的如此清楚,感謝博主!
    不過(guò)我也有一些問(wèn)題:
    1、我是使用mybatis還操作數(shù)據(jù)庫(kù)的,一般在mapper中直接連表做查詢(xún),這種情況下返回的對(duì)象能否直接是DTO,還是說(shuō)必須返回一個(gè)map,到service層在拼裝成DTO?  回復(fù)  更多評(píng)論
      

    # re: 領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)系列文章(2)——淺析VO、DTO、DO、PO的概念、區(qū)別和用處 2015-06-08 15:56 趙輝
    是級(jí)別(大小)的項(xiàng)目需要嚴(yán)格遵守思想,我感覺(jué)現(xiàn)在中國(guó)的環(huán)境,讓大家都遵照這種思想,還有很長(zhǎng)的路要走。  回復(fù)  更多評(píng)論
      

    # re: 領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)系列文章(2)——淺析VO、DTO、DO、PO的概念、區(qū)別和用處 2015-07-09 20:56 Mango
    請(qǐng)問(wèn)驗(yàn)證(特性)應(yīng)該加在dto還是vo?  回復(fù)  更多評(píng)論
      

    # re: 領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)系列文章(2)——淺析VO、DTO、DO、PO的概念、區(qū)別和用處 2015-10-27 11:14 silymer
    雖然是很久前的文章了,但讀來(lái)仍然獲益匪淺,尤其是下面幾位評(píng)論者與博主的互動(dòng),更是精彩,非常感謝~!  回復(fù)  更多評(píng)論
      

    # re: 領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)系列文章(2)——淺析VO、DTO、DO、PO的概念、區(qū)別和用處[未登錄](méi) 2015-12-21 10:00 小朱
    之前看過(guò)領(lǐng)域驅(qū)動(dòng),云里霧里,后來(lái)放棄了,但是在后來(lái)的工作中出現(xiàn)的一些問(wèn)題當(dāng)初沒(méi)能理解的問(wèn)題突然明白了,一直糾結(jié)的問(wèn)題看你文章就想通了,感謝哈。!另外想問(wèn)問(wèn)DO中能不能能不能直接持有PO? 就是把PO當(dāng)做對(duì)應(yīng)DO的一個(gè)字段或者屬性,還是直接在DO中定義相應(yīng)的屬性,然后用轉(zhuǎn)換的方式把PO的一些屬性賦值給DO的對(duì)應(yīng)屬性?  回復(fù)  更多評(píng)論
      

    主站蜘蛛池模板: 在线观看免费毛片| 2020久久精品国产免费| 免费无码VA一区二区三区| 最近免费最新高清中文字幕韩国| 97人妻无码一区二区精品免费| 日本特黄特色aa大片免费| 亚洲精品在线视频| 99ri精品国产亚洲| 亚洲爆乳AAA无码专区| 一区二区在线视频免费观看| 日本不卡免费新一区二区三区| 日韩免费精品视频| 亚洲国产成人影院播放| 久久久久久久久亚洲| 在线亚洲高清揄拍自拍一品区| 美女被爆羞羞网站在免费观看| 免费观看久久精彩视频 | 男女一边摸一边做爽的免费视频| 外国成人网在线观看免费视频| 免费国产黄线在线观看| 久久精品国产亚洲Aⅴ蜜臀色欲| 亚洲一区二区在线免费观看| 亚洲国产成人久久综合| a级黄色毛片免费播放视频| 国产2021精品视频免费播放| 波多野结衣免费视频观看| 亚洲av日韩av不卡在线观看| 亚洲欧美日韩自偷自拍| 国产在线观看无码免费视频| 在线天堂免费观看.WWW| 伊人久久亚洲综合| 亚洲看片无码在线视频| 中文字幕av免费专区| 成人黄页网站免费观看大全| 亚洲精品无码午夜福利中文字幕 | 亚洲欧洲久久av| 亚洲国产成人精品无码一区二区 | 久久99精品免费一区二区| 久久精品免费全国观看国产| 久久久久亚洲AV无码专区网站| 中文字幕亚洲男人的天堂网络 |