領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)與模型驅(qū)動(dòng)開(kāi)發(fā).ppt

上傳人:xt****7 文檔編號(hào):14927876 上傳時(shí)間:2020-08-01 格式:PPT 頁(yè)數(shù):142 大?。?5.23MB
收藏 版權(quán)申訴 舉報(bào) 下載
領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)與模型驅(qū)動(dòng)開(kāi)發(fā).ppt_第1頁(yè)
第1頁(yè) / 共142頁(yè)
領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)與模型驅(qū)動(dòng)開(kāi)發(fā).ppt_第2頁(yè)
第2頁(yè) / 共142頁(yè)
領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)與模型驅(qū)動(dòng)開(kāi)發(fā).ppt_第3頁(yè)
第3頁(yè) / 共142頁(yè)

下載文檔到電腦,查找使用更方便

14.9 積分

下載資源

還剩頁(yè)未讀,繼續(xù)閱讀

資源描述:

《領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)與模型驅(qū)動(dòng)開(kāi)發(fā).ppt》由會(huì)員分享,可在線閱讀,更多相關(guān)《領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)與模型驅(qū)動(dòng)開(kāi)發(fā).ppt(142頁(yè)珍藏版)》請(qǐng)?jiān)谘b配圖網(wǎng)上搜索。

1、領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)與模型驅(qū)動(dòng)開(kāi)發(fā),鐘瑋軍 2015年3月,致謝: 此培訓(xùn)材料借鑒了來(lái)自參考文獻(xiàn)以及互聯(lián)網(wǎng)的大量資料,部分資料的參考來(lái)源未能盡數(shù)列舉,謹(jǐn)在此對(duì)那些在網(wǎng)絡(luò)中無(wú)私分享自己知識(shí)的人表達(dá)我的衷心感謝!,培訓(xùn)內(nèi)容,領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)簡(jiǎn)介 領(lǐng)域通用語(yǔ)言 領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)的構(gòu)造塊 領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)編程實(shí)踐 CQRS架構(gòu) 模型驅(qū)動(dòng)開(kāi)發(fā),領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)思想的發(fā)展,2002年Martin Fower在其出版企業(yè)應(yīng)用架構(gòu)模式中,歸納總結(jié)了40多種企業(yè)應(yīng)用架構(gòu)的設(shè)計(jì)模式。其中所提到的多種設(shè)計(jì)模式和概念,如事務(wù)腳本、活動(dòng)記錄和領(lǐng)域模型等,對(duì)業(yè)界產(chǎn)生了深遠(yuǎn)的影響。 2004年著名建模專(zhuān)家Eric Evans發(fā)表了他最具影響力

2、的著名書(shū)籍:Domain-Driven Design Tackling Complexity in the Heart of Software(中文譯名:領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)軟件核心復(fù)雜性應(yīng)對(duì)之道),書(shū)中提出了“領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)(簡(jiǎn)稱(chēng)DDD)”的概念。 2010年Greg Young在“CQRS, Task Based UIs, Event Sourcing agh!”一文中對(duì)Betrand Meyer的CQS模式進(jìn)行改造,提出CQRS模式。 此后Jimmy Nilsson的Applying Domain-Driven Design and Patterns、Abel Avram和Floyd Marine

3、scu合作的Domain-Driven Design Quickly、Dan Haywood的Domain-Driven Design Using Naked Objects、以及Vaughn Vernon的Implementing Domain-Driven Design等書(shū)籍的出版,豐富了領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)的實(shí)踐和指導(dǎo)。,領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)是什么,領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)事實(shí)上針對(duì)是OOAD的一個(gè)擴(kuò)展和延伸,DDD基于面向?qū)ο蠓治雠c設(shè)計(jì)技術(shù),對(duì)技術(shù)框架進(jìn)行了分層規(guī)劃,同時(shí)對(duì)每個(gè)類(lèi)進(jìn)行了策略和類(lèi)型的劃分。 Its a set of proven modeling techniques especially targ

4、eted to complex applications. Its a set of principles and practices supporting the development process. Its a set of patterns that support a clean and coherent view of the domain model. Its a set of pragmatic strategies allowing applications to scale in size and complexity maintaining their integrit

5、y.,領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)的特性,領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)分層規(guī)劃(一),領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)分層規(guī)劃,領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)分層規(guī)劃(二),領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)是對(duì)傳統(tǒng)N層架構(gòu)模式的繼承和發(fā)展,領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)分層規(guī)劃(三),領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)是對(duì)傳統(tǒng)N層架構(gòu)模式的繼承和發(fā)展,Core J2EE Patterns,例:J2EE參考分層架構(gòu),傳統(tǒng)J2EE或Spring+Hibernate等事務(wù)性編程模型只關(guān)心數(shù)據(jù),這些數(shù)據(jù)對(duì)象除了簡(jiǎn)單sette/getter方法外,沒(méi)有任何業(yè)務(wù)方法,被比喻成“失血模型”。,領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)分層規(guī)劃(四),分布式領(lǐng)域驅(qū)動(dòng)設(shè)計(jì),領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)分層規(guī)劃(五),分布式領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)與DotNET技術(shù)架構(gòu)體系之間的關(guān)系映射,面向?qū)ο?/p>

6、分析與設(shè)計(jì)技術(shù),面向過(guò)程vs.面向?qū)ο?事務(wù)腳本模式把業(yè)務(wù)邏輯組織成單個(gè)過(guò)程,在過(guò)程中直接調(diào)用數(shù)據(jù)庫(kù),業(yè)務(wù)邏輯在服務(wù)(Service)層處理。 事務(wù)腳本模式的特點(diǎn)是簡(jiǎn)單容易理解,面向過(guò)程設(shè)計(jì)。對(duì)于少量邏輯的業(yè)務(wù)應(yīng)用來(lái)說(shuō),事務(wù)腳本模式簡(jiǎn)單自然,性能良好,容易理解,而且一個(gè)事務(wù)的處理不會(huì)影響其他事務(wù)。 不過(guò)缺點(diǎn)也很明顯,對(duì)于復(fù)雜的業(yè)務(wù)邏輯處理力不從心,難以保持良好的設(shè)計(jì),事務(wù)之間的冗余代碼不斷增多,通過(guò)復(fù)制粘貼方式進(jìn)行復(fù)用??删S護(hù)性和擴(kuò)展性變差。,對(duì)類(lèi)的策略和類(lèi)型的劃分,對(duì)類(lèi)進(jìn)行StereoType(“構(gòu)造型”)劃分的好處在于: (1)指導(dǎo)設(shè)計(jì) (2)幫助命令對(duì)象 (3)輔助理

7、解,按照策略和類(lèi)型對(duì)類(lèi)進(jìn)行劃分,六邊形架構(gòu),以領(lǐng)域模型為核心的六邊形架構(gòu),領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)中的設(shè)計(jì)模式,有助于獲得柔性設(shè)計(jì)的設(shè)計(jì)模式,每個(gè)元素的名稱(chēng)都提供了一次揭示設(shè)計(jì)意圖的機(jī)會(huì)。站在客戶(hù)開(kāi)發(fā)人員的角度上來(lái)思考它。,人們?yōu)榱耸顾蓄?lèi)和操作都具有相似的規(guī)模而尋找一種一致的力度。粒度的大小并不是唯一要考慮的問(wèn)題,我們還要考慮粒度在哪種場(chǎng)合下使用。 隨著代碼重構(gòu)不斷適合新理解的概念或需求,概念輪廓也就逐漸形成了。搞內(nèi)聚低耦合原則既適用于代碼,也適用于概念。,領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)軟件核心復(fù)雜性應(yīng)對(duì)之道第10章,任何對(duì)未來(lái)操作產(chǎn)生影響的系統(tǒng)狀態(tài)的改變都可以成為副作用。 把命令和查詢(xún)嚴(yán)格地放到不同操作中;創(chuàng)建并返回V

8、alue Object。 允許我們安全地對(duì)多個(gè)操作進(jìn)行組合。,使用斷言把副作用明確表示出來(lái),使它們更易于處理。 尋找在概念上內(nèi)聚的模型,更易推出預(yù)期ASSERTION,從而加快學(xué)習(xí)過(guò)程并避免代碼矛盾。,盡一切可能保持低耦合。把所有無(wú)關(guān)概念提取到對(duì)象之外,類(lèi)就變成完全孤立的了,使得我們可以單獨(dú)地研究和理解它。每個(gè)孤立類(lèi)都極大減輕了因理解Module而帶來(lái)的負(fù)擔(dān)。,操作閉合:在適當(dāng)?shù)那闆r下,在定義操作時(shí)讓它的返回類(lèi)型與其參數(shù)相同。閉合操作提供了一個(gè)高層接口,同時(shí)又不會(huì)引入對(duì)其他概念的任何依賴(lài)性。,培訓(xùn)內(nèi)容,領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)簡(jiǎn)介 領(lǐng)域通用語(yǔ)言 領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)的構(gòu)造塊 領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)編程實(shí)踐 CQRS架構(gòu) 模

9、型驅(qū)動(dòng)開(kāi)發(fā),使用通用語(yǔ)言的重要性,Talking different languages makes projects fail. Programmers speak using technical jargon (design patterns, acronyms, geeky in-jokes) Domain experts use terminology specific to their field of expertise Computers speak programming languages 大家必須妥協(xié),領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)的關(guān)鍵點(diǎn),關(guān)注核心領(lǐng)域(Core Domain) 領(lǐng)域?qū)<液?/p>

10、軟件從業(yè)者共同開(kāi)發(fā)模型 在一個(gè)明確的限界上下文(Bounded Context)中使用領(lǐng)域通用語(yǔ)言(ubiquitous language),通用語(yǔ)言(一),通用語(yǔ)言(UBIQUITOUS LANGUAGE)是團(tuán)隊(duì)共享的語(yǔ)言。領(lǐng)域?qū)<液烷_(kāi)發(fā)者使用相同的通用語(yǔ)言進(jìn)行交流。事實(shí)上,團(tuán)隊(duì)中每個(gè)人都使用相同的通用語(yǔ)言。不管你在團(tuán)隊(duì)中的角色如何,只要你是團(tuán)隊(duì)的一員,你都將使用通用語(yǔ)言。 通用語(yǔ)言是團(tuán)隊(duì)自己創(chuàng)建的公用語(yǔ)言。團(tuán)隊(duì)中同時(shí)包含領(lǐng)域?qū)<液蛙浖_(kāi)發(fā)人員。 通用語(yǔ)言更多地是關(guān)于業(yè)務(wù)本身如何思考和運(yùn)作的,領(lǐng)域?qū)<覍?duì)通用語(yǔ)言有很大影響。不同領(lǐng)域?qū)<視?huì)在概念和術(shù)語(yǔ)上產(chǎn)生分歧,甚至也會(huì)犯錯(cuò),當(dāng)領(lǐng)域?qū)<液烷_(kāi)發(fā)者

11、一起創(chuàng)建領(lǐng)域模型的時(shí)候,他們有時(shí)會(huì)達(dá)成一致,有時(shí)會(huì)做一些妥協(xié),但最終目的都是為了創(chuàng)造最適合項(xiàng)目的通用語(yǔ)言。團(tuán)隊(duì)成員們妥協(xié)的絕對(duì)不應(yīng)是通用語(yǔ)言的質(zhì)量,而是概念、術(shù)語(yǔ)和含義。最初的一致并不表示始終一致,通用語(yǔ)言也會(huì)隨著時(shí)間推移而不斷演化改變。 領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)的一個(gè)核心思想就是使用基于模型的共同語(yǔ)言。因?yàn)槟P褪擒浖M足領(lǐng)域的共同點(diǎn),它很適合作為這種通用語(yǔ)言的構(gòu)造基礎(chǔ)。使用模型作為語(yǔ)言的核心骨架,要求團(tuán)隊(duì)在進(jìn)行所有的交流都是使用一致的語(yǔ)言,在代碼中也是這樣。在共享知識(shí)和推敲模型時(shí),團(tuán)隊(duì)會(huì)使用語(yǔ)言、文字和圖形。這兒需要確保團(tuán)隊(duì)使用的語(yǔ)言在所有的交流形式中看上去都是一致的,這種語(yǔ)言被稱(chēng)為“通用語(yǔ)言(Ubiq

12、uitous Language)”。 通用語(yǔ)言的詞匯表包括類(lèi)名稱(chēng)和主要操作。語(yǔ)言中包含術(shù)語(yǔ),有些術(shù)語(yǔ)用來(lái)討論模型中已經(jīng)明確的規(guī)則,還有一些術(shù)語(yǔ)則來(lái)自施加于模型上的高級(jí)組織原則。最后,團(tuán)隊(duì)一致應(yīng)用于領(lǐng)域模型的模式名稱(chēng)使這種語(yǔ)言更為豐富。模型之間的關(guān)系成為所有語(yǔ)言都具有的組合規(guī)則,詞和短語(yǔ)的意義反映了模型的語(yǔ)義。,通用語(yǔ)言(二),在應(yīng)用通用語(yǔ)言時(shí),應(yīng)注意: 將模型作為語(yǔ)言的中心。確保團(tuán)隊(duì)在所有交流活動(dòng)和代碼中堅(jiān)持使用這種語(yǔ)言。在畫(huà)圖、寫(xiě)東西特別是講話時(shí)也要使用這種語(yǔ)言。 通過(guò)嘗試不同的表示方法(它們反映了不同模型)來(lái)消除難點(diǎn)。然后重構(gòu)代碼,并對(duì)類(lèi)、方法和模塊重新命名,以便與新模型相一致。解決交談中

13、的術(shù)語(yǔ)混淆問(wèn)題,就像我們對(duì)普通詞匯形成一個(gè)公認(rèn)的理解一樣。 要認(rèn)識(shí)到UBIQUITOUS LANGUAGE中的更改就是對(duì)模型的更改。 領(lǐng)域?qū)<覒?yīng)該避免使用拗口或無(wú)法表達(dá)領(lǐng)域理解的術(shù)語(yǔ)或結(jié)構(gòu),開(kāi)發(fā)人員應(yīng)該密切監(jiān)視那些將會(huì)妨礙設(shè)計(jì)的有歧義和不一致的地方 有了通用語(yǔ)言,模型就不僅僅是一個(gè)設(shè)計(jì)工作了。它成為開(kāi)發(fā)人員和領(lǐng)域?qū)<夜餐瓿傻拿宽?xiàng)工作中的不可或缺的部分。語(yǔ)言以動(dòng)態(tài)形式傳遞知識(shí)。使用這種語(yǔ)言進(jìn)行討論能夠更清楚地表達(dá)圖和代碼背后的真實(shí)含義。 通用語(yǔ)言是那些不以代碼形式出現(xiàn)的設(shè)計(jì)方面的主要載體,這些方面包括把整個(gè)系統(tǒng)組織在一起的比例結(jié)構(gòu)、定義了不同系統(tǒng)和模型之間關(guān)系的Bounded Context,

14、以及在模型和設(shè)計(jì)中使用的其他模式。,通用語(yǔ)言的應(yīng)用,通用語(yǔ)言貫穿于項(xiàng)目的各個(gè)環(huán)節(jié) User Stories Project Meetings Team Emails Instant Messages Schedule Plan Software Documents 在限界上下文中,保持語(yǔ)言的一致性(如口語(yǔ)、圖形(如UML圖等)、文字、代碼等)。,通用語(yǔ)言的應(yīng)用示例(一),User Stories,NOWhen User logs on with valid credentials, an empty panel is displayed.,YESWhen Player logs on with

15、 valid credentials, an empty board game is displayed. (from a Tic Tac Toe Game software example),通用語(yǔ)言的應(yīng)用示例(二),Code Example,NO. Integer i = new Integer();. String char1 = new String();. public class GameDAO() . catch (Exception e),YES. String realMeaningOfMyString = new String(); . public class Score

16、DataLoader() . catch (Exception NotLoggedInException),NO. Ambiguities. Inconsistencies. Synonyms. Abbreviations,YES. Clarity. Precision. Reuse. Full Names,package tictactoe.client.userInterface; /** * Add the string O or X to a cell in the grid. */ public class ShowCellGrid public static void displa

17、yUser (Grid grid, Cell cell) if (!Initialization.flag (...) ,A class BEFORE and AFTER Ubiquitous Language,package tictactoe.client.userInterface; /** * Performs a move in the game. */ public class PlayerMove /** * When the player clicks in a cell, the game draws an O or a X on the * game grid depend

18、ing on which players turn it is. */ public static void makeMove (GameGrid gameGrid, Cell cell) if (!GameInitialization.waitingMoveFlag (...) ,(Excerpted from a Tic Tac Toe Game source code),Which one would a Stakeholder better understand?,Player Move Performs a move in the game. Make Move When the p

19、layer clicks in a cell, the game draws an O or a X on the game grid depending on which players turn it is. Is Cell Empty The Player can select a cell only if it wasnt already selected.,Show Cell Grid Add the String O or X to a cell in the grid. Display User Is Empty,(Excerpted from a Tic Tac Toe Ga

20、me source code),模型的統(tǒng)一,模型的內(nèi)部一致性又叫做“統(tǒng)一”,這樣每個(gè)術(shù)語(yǔ)都不會(huì)有模棱兩可的意義,也不會(huì)有規(guī)則沖突。除非模型在邏輯上是一致的,否則它就沒(méi)有意義。 識(shí)別限界上下文中的不一致:重復(fù)的概念和假同源 重復(fù)的概念是指兩個(gè)模型元素(以及伴隨的實(shí)現(xiàn))實(shí)際上表示同一個(gè)概念。每當(dāng)這個(gè)概念的信息發(fā)生改變時(shí),都必須要更新兩個(gè)地方。每次由于新的知識(shí)導(dǎo)致一個(gè)對(duì)象被修改時(shí),也必須重新分析和修改另一個(gè)對(duì)象。如果不進(jìn)行實(shí)際的重新分析,結(jié)果就會(huì)出現(xiàn)同一個(gè)概念的兩個(gè)版本,它們遵守不同的規(guī)則,甚至不同的數(shù)據(jù)。更重要的是,團(tuán)隊(duì)成員必須學(xué)習(xí)同一操作的兩種方法,以及保持這兩種方法同步的各種方式。 假同源是指

21、使用相同術(shù)語(yǔ)(或已實(shí)現(xiàn)的對(duì)象)的兩個(gè)人認(rèn)為他們是在談?wù)撏患虑椋珜?shí)際上并不是這樣。但是,當(dāng)兩個(gè)定義都與同一個(gè)領(lǐng)域方面相關(guān),而只是在概念上稍有區(qū)別時(shí),這種沖突更難以發(fā)現(xiàn)。假同源會(huì)導(dǎo)致開(kāi)發(fā)團(tuán)隊(duì)互相干擾對(duì)方的代碼,也可能導(dǎo)致數(shù)據(jù)庫(kù)中含有奇怪的矛盾,還會(huì)引起團(tuán)隊(duì)溝通的混淆。 注意用詞詞匯 注意正確用詞,不要歪曲詞義 開(kāi)發(fā)人員經(jīng)常習(xí)慣于使用增/刪/改/查(CRUD)此類(lèi)動(dòng)詞詞匯,也許有時(shí)候它們也確實(shí)屬于通用語(yǔ)言,但大多數(shù)情況下,它們并不能正確反映業(yè)務(wù),用詞上混淆了業(yè)務(wù)概念。,模型的分裂,在理想的世界中,我們可以有一種把整個(gè)企業(yè)領(lǐng)域包含進(jìn)來(lái)的單一模型;這個(gè)模型將是統(tǒng)一的,沒(méi)有任何相互矛盾或相互重疊的術(shù)

22、語(yǔ)定義;每個(gè)有關(guān)領(lǐng)域的邏輯聲明都將是一致的。但大型系統(tǒng)開(kāi)發(fā)并不是這樣理想。 大型系統(tǒng)領(lǐng)域模型的完全統(tǒng)一是不可行的,也不是一種經(jīng)濟(jì)有效的做法。我們可以采用限界上下文(Bounded Context)定義每個(gè)模型的應(yīng)用范圍,采用上下文映射(Context Map)給出項(xiàng)目上下文以及它們之間關(guān)系的總體視圖。 任何一個(gè)大型項(xiàng)目都會(huì)存在多個(gè)模型。而當(dāng)基于不同模型的代碼被組合到一起后,軟件就會(huì)出現(xiàn)bug、變得不可靠和難以理解。團(tuán)隊(duì)成員之間的溝通變得混亂。人們往往弄不清楚一個(gè)模型不應(yīng)該在哪個(gè)上下文中使用。 明確地定義模型所應(yīng)用的上下文。根據(jù)團(tuán)隊(duì)的組織、軟件系統(tǒng)的各個(gè)部分的用法以及物理表現(xiàn)(代碼和數(shù)據(jù)庫(kù)模式等

23、)來(lái)設(shè)置模型的邊界。在這些邊界中嚴(yán)格保持模型的一致性,而不要受到邊界之外問(wèn)題的干擾和混淆。在Context中,要保證模型在邏輯上統(tǒng)一,而不用考慮它是不是適用于邊界之外的情況。在其他Context中,會(huì)使用其他的模型,這些模型具有不同的術(shù)語(yǔ)、概念、規(guī)則和UBIQUITOUS LANGUAGE的技術(shù)行話。 定義Bounded Context:視察項(xiàng)目的現(xiàn)狀,而不是它的理想狀態(tài)。,領(lǐng)域、子域和限界上下文,核心域、支撐域和通用域,A Core Domain is a part of the business Domain that is of primary importance to the suc

24、cess of the organization. It is of utmost importance to the ongoing success of the business. If a domain models some aspect of the business that is essential, yet not Core, it is a Supporting Subdomain. if a domain captures nothing special to the business, yet is required for the overall business so

25、lution, it is a Generic Subdomain. Focus on the core domain,戰(zhàn)術(shù)建模與戰(zhàn)略建模,領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)的綜合應(yīng)用,共享內(nèi)核(Shared Kernel),當(dāng)不同團(tuán)隊(duì)開(kāi)發(fā)一些緊密相關(guān)的應(yīng)用程序時(shí),如果團(tuán)隊(duì)之間不進(jìn)行協(xié)調(diào),即使短時(shí)間內(nèi)能夠取得快速進(jìn)展,他們開(kāi)發(fā)出的產(chǎn)品也可能互相不適合,最后可能不得不在轉(zhuǎn)換層上花費(fèi)大量時(shí)間,而且得到的產(chǎn)品也五花八門(mén)。 從領(lǐng)域模型中選出兩個(gè)團(tuán)隊(duì)都同意共享的一個(gè)子集。當(dāng)然,除了模型的這個(gè)子集以外,這還包括與該模型部分相關(guān)的代碼子集,或數(shù)據(jù)庫(kù)設(shè)計(jì)的子集。這部分明確共享的內(nèi)容具有特殊的狀態(tài),而且一個(gè)團(tuán)隊(duì)在沒(méi)與另一個(gè)團(tuán)隊(duì)商量的

26、情況下不應(yīng)擅自更改它。 功能系統(tǒng)要經(jīng)常進(jìn)行集成,但集成的頻率應(yīng)該比團(tuán)隊(duì)中Continuous Integration的頻率低一些。在進(jìn)行這些集成的時(shí)候,兩個(gè)團(tuán)隊(duì)都要運(yùn)行測(cè)試。 Shared Kernel通常是Core Domain,或是一組Generic Subdomain(通用子領(lǐng)域),也可能二者兼有。,企業(yè)架構(gòu)方法與領(lǐng)域驅(qū)動(dòng)設(shè)計(jì),架構(gòu)開(kāi)發(fā) 方法,,,架構(gòu)開(kāi)發(fā)指引和技術(shù),兩者都強(qiáng)調(diào)Business和IT的高度統(tǒng)一,很多企業(yè)架構(gòu)方法對(duì)于領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)“戰(zhàn)略設(shè)計(jì)”的具體實(shí)施辦法具有詳實(shí)的指導(dǎo)意義。如TOGAF V9構(gòu)件:,eTOM業(yè)務(wù)建模,,Level 0 Processes,Level 1 Pr

27、ocesses,Level 2 Processes,,,,,業(yè)務(wù)流程解耦/分解,eTOM業(yè)務(wù)建模,BSS業(yè)務(wù)流程框架,領(lǐng)域解決特定問(wèn)題,eTOM信息數(shù)據(jù)模型,eTOM 0級(jí)視圖,SID 1級(jí)視圖,,ABE:Aggregate Business Entity,ABE是SID中一組定義良好的實(shí)體,具有高內(nèi)聚、低耦合的特征。,共享內(nèi)核,eTOM信息數(shù)據(jù)模型,參考讀物,領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)軟件核心復(fù)雜性應(yīng)對(duì)之道及實(shí)現(xiàn)領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)中的相關(guān)章節(jié) 軟件方法-業(yè)務(wù)建模和需求第三章“業(yè)務(wù)建模”中的相關(guān)內(nèi)容 參考模型范例: TMForum的eTOM模型:,培訓(xùn)內(nèi)容,領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)簡(jiǎn)介 領(lǐng)域通用語(yǔ)言 領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)的構(gòu)造塊 領(lǐng)

28、域驅(qū)動(dòng)設(shè)計(jì)編程實(shí)踐 CQRS架構(gòu) 模型驅(qū)動(dòng)開(kāi)發(fā),領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)的構(gòu)造塊,Entity(實(shí)體),實(shí)體是一個(gè)具有唯一身份標(biāo)識(shí)的對(duì)象,并且可以在相當(dāng)長(zhǎng)的一段時(shí)間內(nèi)持續(xù)地變化。我們可以對(duì)實(shí)體做多次修改,故一個(gè)實(shí)體對(duì)象可能和它先前的對(duì)象大不相同,但是由于它們擁有相同的身份標(biāo)識(shí)(identity),它們依然是同一個(gè)實(shí)體。 我們通過(guò)標(biāo)識(shí)對(duì)對(duì)象進(jìn)行區(qū)分,而不是屬性,此時(shí)我們應(yīng)該將標(biāo)識(shí)作為主要的模型定義。同時(shí)我們需要保持簡(jiǎn)單的類(lèi)定義,并且關(guān)注對(duì)象在其生命周期中的連續(xù)性和唯一標(biāo)識(shí)性。 隨著對(duì)象的改變,我們可能會(huì)跟蹤這樣的改變,比如什么時(shí)候發(fā)生了改變,發(fā)生了什么改變,是誰(shuí)做出的改變等。我們應(yīng)該慎重對(duì)待在對(duì)象整個(gè)生命周

29、期中所發(fā)生的合法改變。 唯一的身份標(biāo)識(shí)和可變性(mutability)特征將實(shí)體對(duì)象和值對(duì)象(Value Objects)區(qū)分開(kāi)來(lái)。 很多時(shí)候,一個(gè)領(lǐng)域概念應(yīng)該建模成值對(duì)象,而不是實(shí)體對(duì)象。 實(shí)體和值對(duì)象是領(lǐng)域模型概念,而不是數(shù)據(jù)存儲(chǔ)模型概念。,Value Objects(值對(duì)象),值對(duì)象的特征 它度量或者描述了領(lǐng)域中的一件東西。 它可以作為不變量。 它將不同的相關(guān)的屬性組合成一個(gè)概念整體 當(dāng)度量和描述改變時(shí),可以用另一個(gè)值對(duì)象予以替換 它可以和其他值對(duì)象進(jìn)行相等性比較 它不會(huì)對(duì)協(xié)作對(duì)象造成副作用。 當(dāng)我們只關(guān)心一個(gè)模型元素的屬性時(shí),應(yīng)把它歸類(lèi)為值對(duì)象。我們應(yīng)該使這個(gè)模型元素能夠表示出其屬性的

30、意義,并為它提供相關(guān)功能。值對(duì)象應(yīng)該是不可變的。不要為它分配任何標(biāo)識(shí),而且不要把它設(shè)計(jì)成Entity那么復(fù)雜。 應(yīng)該盡量使用值對(duì)象來(lái)建模而不是實(shí)體對(duì)象,即便一個(gè)領(lǐng)域概念必須建模成實(shí)體,在設(shè)計(jì)時(shí)也應(yīng)該更偏向于將其作為值對(duì)象容器,而不是子實(shí)體容器。 實(shí)體對(duì)象與值對(duì)象是領(lǐng)域概念,而不是數(shù)據(jù)存儲(chǔ)模型概念 值對(duì)象可以與其所在的實(shí)體對(duì)象保存在同一張表中,值對(duì)象的每一個(gè)屬性保存為一列;值對(duì)象也可以獨(dú)立于其所在的實(shí)體對(duì)象保存在另一張表中,值對(duì)象獲得委派主鍵,該主鍵對(duì)客戶(hù)端是不可見(jiàn)的。,Entity和Value Object示例,Aggregates(聚合),在具有復(fù)雜關(guān)聯(lián)的模型中,要想保證對(duì)象更改的一致性是很

31、困難的。不僅互不關(guān)聯(lián)的對(duì)象需要遵守一些固定規(guī)則,而且緊密關(guān)聯(lián)的各組對(duì)象也要遵守一些固定規(guī)則。然而,過(guò)于謹(jǐn)慎的鎖定機(jī)制又會(huì)導(dǎo)致多個(gè)用戶(hù)之間毫無(wú)意義地互相關(guān)繞,從而使系統(tǒng)不可用。在任何具有持久化數(shù)據(jù)存儲(chǔ)的系統(tǒng)中,對(duì)數(shù)據(jù)進(jìn)行修改的事務(wù)必須要有一個(gè)范圍,而且要有一種保持?jǐn)?shù)據(jù)一致性的方式。 聚合(Aggregate)是一組相關(guān)對(duì)象的集合,我們把它作為數(shù)據(jù)修改的單元。每個(gè)聚合都有一個(gè)根和一個(gè)邊界,邊界定義了聚合的內(nèi)部都有什么,根則是聚合中所包含的一個(gè)特定實(shí)體。在聚合中,根是唯一允許外部對(duì)象保持對(duì)它的引用的元素,而邊界內(nèi)部的對(duì)象之間則可以互相引用。除根以外的其他Entity都有本地表示,但這些標(biāo)識(shí)只有在聚合

32、內(nèi)部才需要加以區(qū)別,因?yàn)橥獠繉?duì)象除了根Entity之外看不到其他對(duì)象。 聚合行為視為是一個(gè)整體,在每個(gè)事務(wù)完成時(shí),必須要滿足聚合內(nèi)所應(yīng)用的固定規(guī)則的要求,即保證數(shù)據(jù)變化的一致性。根實(shí)體最終檢查固定規(guī)則;刪除操作必須一次刪除聚合邊界之內(nèi)的所有對(duì)象;當(dāng)提交對(duì)聚合邊界內(nèi)部的任何對(duì)象的修改時(shí),整個(gè)聚合中的所有固定規(guī)則都必須被滿足。 原則:在一致性邊界之內(nèi)建模真正的不變條件;設(shè)計(jì)小聚合;通過(guò)唯一標(biāo)識(shí)引用其他聚合;在邊界之外使用最終一致性 盡量將根實(shí)體所包含的其他聚合建模成值對(duì)象,而不是實(shí)體。,Aggregates(聚合)示例,Domain Event(領(lǐng)域事件),Domain Event(領(lǐng)域事件) 有

33、時(shí)候應(yīng)用需要記錄跟蹤事情的發(fā)生 領(lǐng)域事件經(jīng)常被建模為Value Object,但這些Value Object并不能被共享,因?yàn)轭I(lǐng)域事件本身是“唯一”的。 一個(gè)領(lǐng)域事件是指一個(gè)在領(lǐng)域中“有意義”的事件 Hints UML四色原型中有一個(gè)相近概念,稱(chēng)為時(shí)刻-時(shí)段原型(Moment-interval),即表示事物在某個(gè)時(shí)刻或某一段時(shí)間內(nèi)發(fā)生。,參考:四色原型,四色原型是誕生于90年代,現(xiàn)在被廣泛使用的一種系統(tǒng)分析方法,如Borland的Together架構(gòu)師版,準(zhǔn)確地說(shuō),是由Peter Coad 和 Mark Mayfield首先提出,然后由David North拓展。,Repositories(資

34、源庫(kù)/倉(cāng)儲(chǔ)),客戶(hù)需要以一種符合實(shí)際的方式來(lái)獲取對(duì)以存在的領(lǐng)域?qū)ο蟮囊?。為每種需要全局訪問(wèn)的對(duì)象類(lèi)型創(chuàng)建一個(gè)對(duì)象,這個(gè)對(duì)象就相當(dāng)于該類(lèi)型的所有對(duì)象在內(nèi)存中的一個(gè)集合的“替身”。通過(guò)一個(gè)眾所周知的接口來(lái)提供訪問(wèn)。提供添加和刪除對(duì)象的方法,用這些方法來(lái)封裝在數(shù)據(jù)存儲(chǔ)中實(shí)際插入或刪除數(shù)據(jù)的操作。提供根據(jù)具體標(biāo)準(zhǔn)來(lái)挑選對(duì)象的方法,并返回屬性值滿足查詢(xún)標(biāo)準(zhǔn)的對(duì)象或?qū)ο蠹希ㄋ祷氐膶?duì)象是完全實(shí)例化的),從而將實(shí)際的存儲(chǔ)和查詢(xún)技術(shù)封裝起來(lái)。只為那些確實(shí)需要直接訪問(wèn)的聚合提供Repository。讓客戶(hù)始終聚焦于模型,而將所有對(duì)象的存儲(chǔ)和訪問(wèn)操作交給Repository來(lái)完成。 Repository的接口

35、應(yīng)當(dāng)采用領(lǐng)域通用語(yǔ)言。作為客戶(hù)端,不應(yīng)當(dāng)知道數(shù)據(jù)庫(kù)實(shí)現(xiàn)的細(xì)節(jié)。 Repository和DAO的作用類(lèi)似,二者的主要區(qū)別: DAO是比Repository更低的一層,包含了如何從數(shù)據(jù)庫(kù)中提取數(shù)據(jù)的代碼。 Repository以“領(lǐng)域”為中心,所描述的是“領(lǐng)域語(yǔ)言”。Repository把ORM框架與領(lǐng)域模型隔離,對(duì)外隱藏封裝了數(shù)據(jù)訪問(wèn)機(jī)制。,Repositories(資源庫(kù)/倉(cāng)儲(chǔ))示例,public interface AccountRepository Account findAccount(String accountId); void addAccount(Account accoun

36、t); ,public class HibernateAccountRepository implements AccountRepository private HibernateTemplate hibernateTemplate; public HibernateAccountRepository(HibernateTemplate template) hibernateTemplate = template; public void addAccount(Account account) hibernateTemplate.save(account); public

37、 Account findAccount(final String accountId) return (Account) DataAccessUtils.uniqueResult(hibernateTemplate. findByNamedQueryAndNamedParam( “Account.findAccountByAccountId”, “accountId”, accountId)); ,Services(領(lǐng)域服務(wù)),當(dāng)領(lǐng)域中的某個(gè)操作過(guò)程或轉(zhuǎn)換過(guò)程不是實(shí)體或值對(duì)象的職責(zé)時(shí),我們便應(yīng)該將該操作放在一個(gè)單獨(dú)的接口中,即領(lǐng)域服務(wù)。如果勉強(qiáng)地把這些重要的領(lǐng)域功能歸為E

38、ntity或ValueObject的職責(zé),那么不是歪曲了基于模型的對(duì)象的定義,就是人為地增加了一些無(wú)意義的對(duì)象。應(yīng)確保領(lǐng)域服務(wù)和通用語(yǔ)言是一致的,并且保證它是無(wú)狀態(tài)的。 正確區(qū)分領(lǐng)域服務(wù)(Domain Service)和應(yīng)用服務(wù)(Application Service): 我們不應(yīng)把業(yè)務(wù)邏輯置于應(yīng)用服務(wù),但我們會(huì)把業(yè)務(wù)邏輯置于領(lǐng)域服務(wù)中。(應(yīng)用)服務(wù)要做“薄”。 領(lǐng)域服務(wù)職責(zé):跨聚合實(shí)例業(yè)務(wù)邏輯;沒(méi)辦法合理放到實(shí)體中的其它業(yè)務(wù)邏輯。 應(yīng)用服務(wù)職責(zé):跨限界上下文的業(yè)務(wù)邏輯;DTO轉(zhuǎn)換;事務(wù)AOP、權(quán)限AOP、日志AOP、異常AOP;外部系統(tǒng)訪問(wèn)(郵件、消息隊(duì)列)。 領(lǐng)域服務(wù)設(shè)計(jì)原則:用來(lái)組織業(yè)務(wù)

39、邏輯,面向業(yè)務(wù)邏輯;細(xì)粒度;內(nèi)部視圖看系統(tǒng);一個(gè)請(qǐng)求對(duì)應(yīng)多個(gè)服務(wù)的多個(gè)方法;服務(wù)之間會(huì)存在依賴(lài); 應(yīng)用服務(wù)設(shè)計(jì)原則:用來(lái)封裝業(yè)務(wù)邏輯;面向用例;粗粒度;外部視圖看系統(tǒng);一個(gè)請(qǐng)求對(duì)應(yīng)一個(gè)方法;服務(wù)之間互不依賴(lài)。 應(yīng)用服務(wù)和領(lǐng)域服務(wù)區(qū)分非常敏感,有時(shí)候需要在快速性/方便性上做折衷。,Services(領(lǐng)域服務(wù))示例,public interface MoneyTransferService BankingTransaction transfer(String fromAccountId, String toAccountId, double amount); ,public class Mone

40、yTransferServiceImpl implements MoneyTransferService private final AccountRepository accountRepository; private final BankingTransactionRepository bankingTransactionRepository; public MoneyTransferServiceImpl(AccountRepository accountRepository, BankingTransactionRepository bankingTransactionRe

41、pository) BankingTransaction transfer(String fromAccountId, String toAccountId, double amount) ,應(yīng)用服務(wù)、領(lǐng)域服務(wù)和基礎(chǔ)設(shè)施服務(wù),Factories(工廠),當(dāng)創(chuàng)建一個(gè)對(duì)象或創(chuàng)建整個(gè)聚合時(shí),如果創(chuàng)建工作很復(fù)雜,或者暴露了過(guò)多的內(nèi)部結(jié)構(gòu),則可以使用Factory進(jìn)行封裝。應(yīng)該將創(chuàng)建復(fù)雜對(duì)象的實(shí)例和聚合的職責(zé)轉(zhuǎn)移到一個(gè)單獨(dú)的對(duì)象,這個(gè)對(duì)象本身在領(lǐng)域模型中可能沒(méi)有職責(zé),但它仍是領(lǐng)域設(shè)計(jì)的一部分。 不同類(lèi)型的工廠模式: 工廠類(lèi) 工廠方法,Modules(模塊),Module為人們提供了

42、兩種觀察模型的方式,一是可以在Module中查看細(xì)節(jié),而不會(huì)被整個(gè)模型淹沒(méi),二是觀察Module之間的關(guān)系,而不考慮其內(nèi)部細(xì)節(jié)。 模塊之間應(yīng)該是低耦合的,而在模塊內(nèi)部則是高內(nèi)聚的。模塊并不僅僅是代碼的劃分,而且也是概念的劃分。一個(gè)人一次考慮的事情是有限的(因此才有低耦合);不連貫的思想和“一鍋粥”似的思想同樣難于理解(因此才有高內(nèi)聚)。 選擇能夠描述系統(tǒng)的Module,并使之包含一個(gè)內(nèi)聚的概念集合。這通常會(huì)實(shí)現(xiàn)Module之間的低耦合,但如果效果不理想,則應(yīng)尋找一種更改模型的方式來(lái)消除概念之間的耦合,或者找到一個(gè)可作為Module基礎(chǔ)的概念,基于這個(gè)概念組織的模型可以以一種有意義的方式將元素集

43、中到一起。找到一種低耦合的概念組織方式,從而可以相互獨(dú)立地理解和分析這些概念。對(duì)模型進(jìn)行精化,直到可以根據(jù)高層領(lǐng)域概念對(duì)模型進(jìn)行劃分,同時(shí)相應(yīng)的代碼也不會(huì)產(chǎn)生耦合。 Module的名稱(chēng)應(yīng)該是領(lǐng)域通用語(yǔ)言中的術(shù)語(yǔ)。模塊及其名稱(chēng)應(yīng)反映出領(lǐng)域的深層知識(shí)。,培訓(xùn)內(nèi)容,領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)簡(jiǎn)介 領(lǐng)域通用語(yǔ)言 領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)的構(gòu)造塊 領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)編程實(shí)踐 CQRS架構(gòu) 模型驅(qū)動(dòng)開(kāi)發(fā),概念辨析-VO/DTO/DO/PO(一),View Object(視圖對(duì)象):視圖對(duì)象,用于展示層,其作用是把某個(gè)指定頁(yè)面(或組件)的所有數(shù)據(jù)封裝起來(lái)。 Data Transfer Object(數(shù)據(jù)傳輸對(duì)象):這個(gè)概念來(lái)源于J2EE的

44、設(shè)計(jì)模式,原來(lái)的目的是為了EJB的分布式應(yīng)用提供粗粒度的數(shù)據(jù)實(shí)體,以減少分布式調(diào)用的次數(shù),從而提高分布式調(diào)用的性能和降低網(wǎng)絡(luò)負(fù)載,但在這里,我泛指用于展示層與服務(wù)層之間的數(shù)據(jù)傳輸對(duì)象。 Domain Object(領(lǐng)域?qū)ο螅簭默F(xiàn)實(shí)世界中抽象出來(lái)的有形或無(wú)形的業(yè)務(wù)實(shí)體、值對(duì)象或領(lǐng)域服務(wù)。 Persistent 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è))屬性。,Ref: ,概念辨析-VO/DTO/DO/PO(二),VO與DTO:絕大多數(shù)應(yīng)用場(chǎng)景下,VO與DT

45、O的屬性值基本一致,但對(duì)于設(shè)計(jì)層面來(lái)說(shuō),概念上還是存在VO和DTO的區(qū)別,DTO代表服務(wù)層需要接收的數(shù)據(jù)和返回的數(shù)據(jù),而VO代表展示層需要顯示的數(shù)據(jù)。 示例:服務(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ù)同

46、時(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í)現(xiàn)層面是否需要區(qū)分二者概念?具體問(wèn)題具體分析,概念辨析-VO/DTO/DO/PO(三),DTO與DO:DTO是展示層和服務(wù)層之間的數(shù)據(jù)傳輸對(duì)象(可以認(rèn)為是兩者之間的協(xié)議),而DO是對(duì)現(xiàn)實(shí)世界各種業(yè)務(wù)角色的抽象,這就引出了兩者在數(shù)據(jù)上的區(qū)別,例如UserInfo和User,對(duì)于一個(gè)getUser方法來(lái)說(shuō),本質(zhì)上它永遠(yuǎn)不應(yīng)該返回用戶(hù)的密碼,因此UserInfo至少比Use

47、r少一個(gè)password的數(shù)據(jù)。而在領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)中,DO不是簡(jiǎn)單的POJO,它具有領(lǐng)域業(yè)務(wù)邏輯。 在設(shè)計(jì)層面,展示層向服務(wù)層傳遞的DTO與服務(wù)層返回給展示層的DTO在概念上是不同的(如返回UserInfo應(yīng)該不包含password,但創(chuàng)建User傳入的參數(shù)需要包含password),但在實(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ù)密

48、碼),就不設(shè)置對(duì)應(yīng)的屬性。 為什么不在服務(wù)層中直接返回DO:DO具有一些不應(yīng)該讓展示層知道的數(shù)據(jù);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ù)難以控制;ORM框架(如Hibernate)“延遲加載”技術(shù),如果直接把DO暴露給展示層,對(duì)于大部分情況,展示層不在事務(wù)范圍之內(nèi),如果其嘗試在Session關(guān)閉的情況下獲取一個(gè)未加載的關(guān)聯(lián)對(duì)象,會(huì)出現(xiàn)運(yùn)行時(shí)異常(對(duì)于Hibernate來(lái)說(shuō),就是LazyInitiliaztionE

49、xception);從設(shè)計(jì)層面來(lái)說(shuō),展示層依賴(lài)于服務(wù)層,服務(wù)層依賴(lài)于領(lǐng)域?qū)?,如果把DO暴露出去,就會(huì)導(dǎo)致展示層直接依賴(lài)于領(lǐng)域?qū)?,這雖然依然是單向依賴(lài),但這種跨層依賴(lài)會(huì)導(dǎo)致不必要的耦合。 DTO應(yīng)該是一個(gè)“扁平的二維對(duì)象”,概念辨析-VO/DTO/DO/PO(四),DO與PO:DO和PO在絕大部分情況下是一一對(duì)應(yīng)的,PO是只含有g(shù)et/set方法的POJO,但某些場(chǎng)景還是能反映出兩者在概念上存在本質(zhì)的區(qū)別。 DO在某些場(chǎng)景下不需要進(jìn)行顯式的持久化,例如利用策略模式設(shè)計(jì)的商品折扣策略,會(huì)衍生出折扣策略的接口和不同折扣策略實(shí)現(xiàn)類(lèi),這些折扣策略實(shí)現(xiàn)類(lèi)可以算是DO,但它們只駐留在靜態(tài)內(nèi)存,不需要持久化到

50、持久層,因此,這類(lèi)DO是不存在對(duì)應(yīng)的PO的。同樣的道理,某些場(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è)TeacherAndStudentPO的PO,但這個(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)限”。 某些情況

51、下,為了某種持久化策略或者性能的考慮,一個(gè)PO可能對(duì)應(yīng)多個(gè)DO,反之亦然。例如客戶(hù)Customer有其聯(lián)系信息Contacts,這里是兩個(gè)一對(duì)一關(guān)系的DO,但可能出于性能的考慮(極端情況,權(quán)作舉例),為了減少數(shù)據(jù)庫(kù)的連接查詢(xún)操作,把Customer和Contacts兩個(gè)DO數(shù)據(jù)合并到一張數(shù)據(jù)表中。反過(guò)來(lái),如果一本圖書(shū)B(niǎo)ook,有一個(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的情況。 PO的某些屬性值

52、對(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中也可能存在不需要持久化的屬性。 現(xiàn)在的業(yè)務(wù)應(yīng)用開(kāi)發(fā),基本上不需要區(qū)分DO與PO,PO完全可以通過(guò)JPA,Hibernate Annotations/hbm隱藏在DO之中。,概念辨析-VO/DTO/DO/PO(五),VO/DTO/DO/PO轉(zhuǎn)換: 工廠類(lèi)或工廠方法; 構(gòu)造函數(shù); 工具類(lèi),如BeanUtils; 轉(zhuǎn)換實(shí)現(xiàn)中應(yīng)注意類(lèi)層次概念的依賴(lài)關(guān)系。,DO,DTO,VO,PO,Ent

53、ity(一),Entity的標(biāo)識(shí)生成: 用戶(hù)提供 應(yīng)用程序生成 持久化機(jī)制生成 另一個(gè)限界上下文提供 在JPA中,有下面四種策略: 容器自動(dòng)生成 (GenerationType.AUTO):由JPA自動(dòng)生成 使用數(shù)據(jù)庫(kù)的自動(dòng)增長(zhǎng)字段生成(GenerationType.IDENTITY):需要數(shù)據(jù)庫(kù)支持 根據(jù)數(shù)據(jù)庫(kù)序列號(hào)(GenerationType.SEQUENCE):Oracle支持對(duì)序列號(hào)的支持 使用數(shù)據(jù)庫(kù)表的字段生成(GenerationType.TABLE):使用數(shù)據(jù)庫(kù)中指定表的某個(gè)字段記錄實(shí)體對(duì)象的標(biāo)識(shí),通過(guò)該字段的增長(zhǎng)為新增加的實(shí)體對(duì)象賦唯一值。,Entity(二),繼承關(guān)系:因?yàn)?/p>

54、關(guān)系數(shù)據(jù)庫(kù)的表之間不存在繼承關(guān)系,Entity提供三種基本的繼承映射策略: Single Table Joined Table per Class,Ref: http://docs.jboss.org/hibernate/orm/4.3/manual/en-US/html/ch05.html,Entity(三),繼承關(guān)系:Single Table,SuppressWarnings(serial) Entity Table(name=Vehicle_Hierarchy) Inheritance(strategy=InheritanceType.SINGLE_TABLE) Discriminato

55、rColumn(name=Discriminator, discriminatorType = DiscriminatorType.STRING,length=30) DiscriminatorValue(Vehicle) public class Vehicle implements Serializable //基類(lèi) privateLong id; privateShort speed;//速度 Id GeneratedValue Column(columnDefinition=integer)//指定使用適配Integer長(zhǎng)度的數(shù)據(jù)類(lèi)型 public Long getId() ret

56、urnid; public void setId(Long id) this.id = id; SuppressWarnings(serial) Entity DiscriminatorValue(Car) public class Car extends Vehicle //Vehicle的子類(lèi) privateString engine;//發(fā)動(dòng)機(jī) Column(nullable=true,length=30) publi cString getEngine() returnengine; public void setEngine(String engine) this.

57、engine = engine; SuppressWarnings(serial) Entity DiscriminatorValue(Camion) public class Camion extendsCar //Car的子類(lèi) private String container;//集裝箱 Column(nullable=true,length=30) public String getContainer() returncontainer; public void setContainer(String container) this.container = container; ,

58、Entity(四),繼承關(guān)系:Joined,SuppressWarnings(“serial”) Entity Inheritance(strategy=InheritanceType.JOINED) Table(name=Vehicle) public class Vehicle implements Serializable //基類(lèi) private Long id; private Short speed;//速度 Id GeneratedValue Column(columnDefinition=integer) public Long getId() returnid; pub

59、lic void setId(Long id) this.id = id; public Short getSpeed() returnspeed; public void setSpeed(Short speed) this.speed = speed; SuppressWarnings(serial) Entity Table(name=Car) PrimaryKeyJoinColumn(name=CarID) //把主鍵對(duì)應(yīng)的列名更改為CarID public class Car extends Vehicle //Vehicle的子類(lèi) private String

60、engine;//發(fā)動(dòng)機(jī) Column(nullable=true,length=30) public String getEngine() returnengine; public void setEngine(String engine) this.engine = engine; SuppressWarnings(serial) Entity Table(name=Camion) PrimaryKeyJoinColumn(name=CamionID) //把主鍵對(duì)應(yīng)的列名更改為CamionID public class Camion extends Car //Car的子

61、類(lèi) privateString container; Column(nullable=true,length=30) public String getContainer() return container; public void setContainer(String container) this.container = container; ,Entity(五),繼承關(guān)系:Table per Class 一旦使用這種策略,意味著你不能使用AUTO generator 和IDENTITY generator,即主鍵值不能采用數(shù)據(jù)庫(kù)自動(dòng)生成。,SuppressWarnings(

62、serial) Entity //或MappedSuperclass Inheritance(strategy=InheritanceType.TABLE_PER_CLASS) Table(name=“Vehicle”) //當(dāng)為MappedSuperclass時(shí),不要Table標(biāo)注 public class Vehicle implementsSerializable //基類(lèi) private Long id; private Short speed;//速度 Id Column(columnDefinition=integer) public Long getId() return i

63、d; public void setId(Long id) this.id = id; public Short getSpeed() return speed; public void setSpeed(Short speed) this.speed = speed; SuppressWarnings(serial) Entity Table(name=Car) public class Car extends Vehicle //Vehicle的子類(lèi) private String engine;//發(fā)動(dòng)機(jī) Column(nullable=true,length=30) pub

64、lic String getEngine() returnengine; public void setEngine(String engine) this.engine = engine; SuppressWarnings(serial) Entity Table(name=Camion) public class Camion extends Car //Car的子類(lèi) private String container;//集裝箱 Column(nullable=true,length=30) publicString getContainer() returncontainer;

65、 public void setContainer(String container) this.container = container; ,Entity(六),審計(jì)(Audit):最近一次修改時(shí)間,最近一次修改人。,Entity EntityListeners( JodaAuditListener.class ) public class Cargo extends AbstractDomainObject implements JodaAuditable, Identifiable public interface JodaAuditable public void setC

66、reatedBy(String createdBy); public String getCreatedBy(); public void setCreatedDate(DateTime createdDate); public DateTime getCreatedDate(); public void setLastUpdatedBy(String updatedBy); public String getLastUpdatedBy(); public void setLastUpdated(DateTime updateDate); public DateTime getLastUpdated(); public class JodaAuditListener PreUpdate PrePersist private void changeAuditInformation(JodaAuditable auditableEntity) DateTime lastUpdated = new DateTime(); auditableEntity.setLastUp

展開(kāi)閱讀全文
溫馨提示:
1: 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
2: 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶(hù)所有。
3.本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
5. 裝配圖網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶(hù)上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶(hù)上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶(hù)因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

最新文檔

相關(guān)資源

更多
正為您匹配相似的精品文檔
關(guān)于我們 - 網(wǎng)站聲明 - 網(wǎng)站地圖 - 資源地圖 - 友情鏈接 - 網(wǎng)站客服 - 聯(lián)系我們

copyright@ 2023-2025  zhuangpeitu.com 裝配圖網(wǎng)版權(quán)所有   聯(lián)系電話:18123376007

備案號(hào):ICP2024067431號(hào)-1 川公網(wǎng)安備51140202000466號(hào)


本站為文檔C2C交易模式,即用戶(hù)上傳的文檔直接被用戶(hù)下載,本站只是中間服務(wù)平臺(tái),本站所有文檔下載所得的收益歸上傳人(含作者)所有。裝配圖網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶(hù)上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)上載內(nèi)容本身不做任何修改或編輯。若文檔所含內(nèi)容侵犯了您的版權(quán)或隱私,請(qǐng)立即通知裝配圖網(wǎng),我們立即給予刪除!