分析設(shè)計(jì)(00002)課件_第1頁
分析設(shè)計(jì)(00002)課件_第2頁
分析設(shè)計(jì)(00002)課件_第3頁
分析設(shè)計(jì)(00002)課件_第4頁
分析設(shè)計(jì)(00002)課件_第5頁
已閱讀5頁,還剩117頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

1、領(lǐng)域驅(qū)動(dòng)建模(Evans DDD)彭晨陽Evans DDD2004年Eric Evans 發(fā)表Domain-Driven Design Tackling Complexity in the Heart of Software (領(lǐng)域驅(qū)動(dòng)設(shè)計(jì) )簡(jiǎn)稱Evans DDD領(lǐng)域建模是一種藝術(shù)的技術(shù),它是用來解決復(fù)雜軟件快速應(yīng)付變化的解決之道 Evans DDD領(lǐng)域模型重要性沒有領(lǐng)域模型,只是靠代碼編寫完成一個(gè)又一個(gè)功能,復(fù)雜的領(lǐng)域需求會(huì)使得他們無法交流討論,使工作陷入泥沼。有少許領(lǐng)域模型,但是沒有維護(hù)好模型與代碼直接的聯(lián)系,兩者產(chǎn)生差異,無法實(shí)現(xiàn)。分析設(shè)計(jì)發(fā)展的三個(gè)階段第一階段:圍繞數(shù)據(jù)庫的驅(qū)動(dòng)設(shè)計(jì),

2、新項(xiàng)目總是從設(shè)計(jì)數(shù)據(jù)庫及其字段開始。第二層次:面向?qū)ο蟮姆治鲈O(shè)計(jì)方法誕生后,有了專門的分析和設(shè)計(jì)階段之分,分析階段和設(shè)計(jì)階段是斷裂的。第三階段:融合了分析階段和設(shè)計(jì)階段的領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)(Evans: DDD)。第一階段:傳統(tǒng)的數(shù)據(jù)庫方式過去軟件系統(tǒng)分析設(shè)計(jì)總是從數(shù)據(jù)庫開始,這種圍繞數(shù)據(jù)庫分析設(shè)計(jì)的缺點(diǎn)非常明顯:1.分析方面:不能迅速有效全面分析需求。2. 設(shè)計(jì)方面:導(dǎo)致過程化設(shè)計(jì)編程,喪失了面向?qū)ο笤O(shè)計(jì)的優(yōu)點(diǎn)。2. 運(yùn)行方面:導(dǎo)致軟件運(yùn)行時(shí)負(fù)載集中在數(shù)據(jù)庫端,系統(tǒng)性能難于擴(kuò)展,閑置了中間件J2EE服務(wù)器處理性能。對(duì)象和關(guān)系數(shù)據(jù)庫存在阻抗,本身是矛盾競(jìng)爭(zhēng)的。分析模型分析模型會(huì)有知識(shí)不斷消化的過程,

3、但在編碼時(shí)這些知識(shí)會(huì)被遺棄。開發(fā)人員被迫為設(shè)計(jì)進(jìn)行新的抽象,那么分析人員嵌入模型中知識(shí)不能保留和重新發(fā)現(xiàn)。分析模型很多重要發(fā)現(xiàn)更改往往出現(xiàn)在設(shè)計(jì)實(shí)現(xiàn)過程,預(yù)先的模型可能深入研究無關(guān)主題,忽視重要主題。蜘蛛網(wǎng)式模型類圖問題一個(gè)印在大紙張上的完整類圖,整面墻都被它覆蓋,花幾個(gè)月分析開發(fā)的領(lǐng)域模型,模型大多數(shù)對(duì)象都與其中三四個(gè)對(duì)象有錯(cuò)綜復(fù)雜的關(guān)系,且關(guān)系網(wǎng)幾乎沒有自然邊界。分析人員是忠于領(lǐng)域需求本質(zhì)。問題:開發(fā)人員開始實(shí)現(xiàn)應(yīng)用程序時(shí),彼此糾纏的關(guān)系根本無法轉(zhuǎn)換成可存儲(chǔ) 可檢索的實(shí)現(xiàn)。是不是基于概念的模型類圖不能成為程序設(shè)計(jì)的基礎(chǔ)?DDD領(lǐng)域模型特點(diǎn)統(tǒng)一領(lǐng)域模型:同時(shí)滿足分析原型和軟件設(shè)計(jì) ,如果一個(gè)

4、模型實(shí)現(xiàn)時(shí)不實(shí)用,重新尋找新模型。如果模型沒有忠實(shí)表達(dá)領(lǐng)域關(guān)鍵概念時(shí),也必須重新尋找新的模型。 統(tǒng)一語言:一個(gè)無處不在(ubiquitous )的語言,項(xiàng)目中所有人統(tǒng)一交流的語言。減少溝通疑惑,減少傳達(dá)走樣。使得軟件更加適合需求。建模和設(shè)計(jì)成為單個(gè)迭代循環(huán)。將領(lǐng)域模型和設(shè)計(jì)緊密聯(lián)系。因此,建模專家必須懂設(shè)計(jì)。Cargo需求跟蹤顧客貨物的關(guān)鍵裝卸事件對(duì)貨物進(jìn)行實(shí)現(xiàn)預(yù)約當(dāng)貨物在運(yùn)輸?shù)诌_(dá)某點(diǎn)時(shí),自動(dòng)向顧客發(fā)送信息。這是一個(gè)跟蹤物體流動(dòng)的軟件系統(tǒng),關(guān)注重點(diǎn)是跟蹤事件;顧客預(yù)約;貨物裝卸過程中。傳統(tǒng)分析思路是面向?qū)ο髥幔咳毕荩篊argo和CargoService 首身分離。貨物的裝卸系列事件或行為應(yīng)該被

5、封裝在貨物這個(gè)邊界內(nèi)。維持邏輯上的一致性。因?yàn)椴煌b卸事件會(huì)引發(fā)貨物本身狀態(tài)變化。無邏輯一致封裝的失血模型public class A private int lower, upper; /兩個(gè)狀態(tài)值 public int getLower() return lower; public int getUpper() return upper; .setter方法. A模型要求邏輯上一致性是:狀態(tài)值lower必須小于狀態(tài)值upper,lower a.getLower() a.setUpper(value); public void setALower(int value) if (value a

6、.getUpper() a.setLower(value); 邏輯一致性判斷被放在了客戶端或service中,而不是在模型A內(nèi)部,這樣問題造成A的狀態(tài)結(jié)果混亂,會(huì)出現(xiàn)A.upperA.lower情況。破壞A的邏輯一致性假設(shè)A的lower和upper的初始值是(0, 5);同時(shí)下面兩個(gè)請(qǐng)求事件發(fā)生:一個(gè)客戶端請(qǐng)求線程A: setLower(4) 一個(gè)客戶端請(qǐng)求線程B: setUpper(3) A的狀態(tài)是:lower和upper是 (4, 3) 破壞A模型邏輯一致性要求lower a.getLower() a.setUpper(value); public void setALower(int v

7、alue) if (value a.getUpper() a.setLower(value); 更嚴(yán)格的悲觀鎖synchronization,值對(duì)象比synchronization更優(yōu)雅。內(nèi)聚與邊界無名天地之始,有名萬物之母。故常無欲以觀其妙; 常有欲以觀其徼(jio)。事物因內(nèi)聚而有邊界,故而有名。領(lǐng)域模型的核心目標(biāo)模型 = “是什么(名)” 。模型 != “怎么做”。程序 = 算法 + 數(shù)據(jù)結(jié)構(gòu) ?算法 = “怎么做”,算法也是被設(shè)計(jì)的對(duì)象。數(shù)據(jù)結(jié)構(gòu) = “僵尸”模型在哪里呢?領(lǐng)域模型切割1.將復(fù)雜大的領(lǐng)域分割成子領(lǐng)域。2.抓住子領(lǐng)域的核心,建立核心模型,用聚合劃定邊界。3.對(duì)核心模型實(shí)現(xiàn)

8、靈活性細(xì)節(jié)設(shè)計(jì)聚合Aggregates聚合代表業(yè)務(wù)核心模型。聚合= 聚合根 + 聚合邊界。組 = 組長(zhǎng) + 小組邊界聚合因內(nèi)聚而存在聚合內(nèi)部維持邏輯一致性DDD核心是找出聚合。代表內(nèi)聚組成的關(guān)聯(lián)關(guān)系關(guān)聯(lián)要反映最本質(zhì)的關(guān)系。如學(xué)生 課程 車和馬達(dá)。關(guān)聯(lián)不是手頭任務(wù)本質(zhì)或不能反映模型對(duì)象基本含義,完全取消它?,F(xiàn)實(shí)世界中存在大量雙向多對(duì)多關(guān)聯(lián)關(guān)系,雙向關(guān)聯(lián)和實(shí)現(xiàn)和維護(hù)帶來很大困難,雙向關(guān)聯(lián)極少將聯(lián)系本質(zhì)體現(xiàn)出來,少用雙向關(guān)聯(lián)。盡可能約束關(guān)聯(lián),通過指定導(dǎo)航方向,減少不必要關(guān)聯(lián)。模型中關(guān)聯(lián)越少、越簡(jiǎn)單越好。高內(nèi)聚低關(guān)聯(lián)高內(nèi)聚低關(guān)聯(lián)是設(shè)計(jì)基本原則。是重構(gòu)的準(zhǔn)則。找出關(guān)聯(lián)是細(xì)分模型的一種方式,從而更恰當(dāng)?shù)囟?/p>

9、義模型邊界。關(guān)聯(lián)不是手頭任務(wù)本質(zhì)或不能反映模型對(duì)象基本含義,完全取消它。少用雙向關(guān)聯(lián),除非技術(shù)性能要求。模型中關(guān)聯(lián)越少、越簡(jiǎn)單越好。完全擺脫數(shù)據(jù)庫影子,SQL語句作為規(guī)則封裝在模型中。找出聚合論壇關(guān)聯(lián)關(guān)系的提純與精煉四色原型:輔助找出聚合四色使用顏色這種直觀對(duì)事物進(jìn)行分類。類似于名詞和動(dòng)詞等語義分類。四色能夠?qū)?dòng)靜分離,考慮人機(jī)交互。四色的特點(diǎn)是能夠比較全面宏觀認(rèn)識(shí)需求。原型建模分析步驟四色圖屬于分析建模,屬于Archetypes原型。在成千上百的業(yè)務(wù)和工程系統(tǒng)由四種原型組成: 1. 橙色的Moment-Interval簡(jiǎn)稱MI 2. 黃色的角色簡(jiǎn)稱Role 3. 藍(lán)色的description

10、 4. 綠色的party, place, or thing .四色原型DNC大多數(shù)業(yè)務(wù)系統(tǒng)是由多個(gè)四色圖反復(fù)拼裝而成,我們稱為這種現(xiàn)象是Domain-Neutral Component模式 用這種基于語義的類圖模板進(jìn)行任何系統(tǒng)的域建模 。異常的簡(jiǎn)單好用 ,指導(dǎo)幫助更加完整地對(duì)復(fù)雜系統(tǒng)建模 。四色原型詳細(xì)MI:時(shí)刻時(shí)段,表示活動(dòng) 事件,粉紅色核心MI實(shí)現(xiàn)類有些類似:/* MI */ public class Sale public BigDecimal calcTotal() private int number; private Date date; 角色 描述 PPT角色:參與方 人或組織機(jī)

11、構(gòu)描述description:分類目錄,一組反復(fù)使用的值,值對(duì)象。比如:你的車(序列號(hào) 購買日期 顏色)屬于車輛描述分類:制造商 型號(hào) 制造日期和可選顏色,后者是描述。PPT: party 指人或組織 place可能是零售處或批發(fā)處, thing 在不同業(yè)務(wù)活動(dòng)不同角色。四色原型圖藍(lán)色包含類型 描述 個(gè)數(shù)和缺省值。綠色PPT則表達(dá)藍(lán)色在當(dāng)前這個(gè)系統(tǒng)中扮演的一個(gè)特定實(shí)例對(duì)象,包含它的序列號(hào) 名稱 地址和顧客。黃色:被分配的編號(hào)和狀態(tài)粉紅色:編號(hào) 日期段 總價(jià)和狀態(tài)藍(lán) 綠 黃 紅序列上圖描述意思是:很多數(shù)量的具有類型 描述(藍(lán)色)特征的東西被某個(gè)角色(黃色)分配,分配活動(dòng)有一個(gè)日期以及所有東西總價(jià)

12、計(jì)算(粉紅),具體分配活動(dòng)結(jié)果貼在了這個(gè)東西(綠色PPT)上,包括顧客名稱和地址等。PPT更象一個(gè)參與者參與系統(tǒng)活動(dòng)的結(jié)果、關(guān)聯(lián)結(jié)果體。什么東西被什么人做了什么事情,產(chǎn)生了一個(gè)什么結(jié)果。什么人對(duì)什么東西做了什么事情,產(chǎn)生了什么結(jié)果。藍(lán) 綠 黃 紅序列1.藍(lán):它是不是屬于一種種類性質(zhì)的描述,或者代表一組呢可以反復(fù)使用的概念。2.綠:如果需要單獨(dú)著重跟蹤參與方或某個(gè)地方或某個(gè)物品,不只是單獨(dú)記錄數(shù)量這樣簡(jiǎn)單事情,需要特別關(guān)注。3.黃:是否有和角色相關(guān)的職責(zé)。4.紅:需要記住相應(yīng)的時(shí)刻和時(shí)段,它是不是依賴時(shí)間上瞬間或一段短時(shí)間存在的。Cash sales用例提煉Cash sales四色原型模板:什么

13、人對(duì)什么東西做了什么事情, 產(chǎn)生了什么結(jié)果。收銀員賣商品(包括:掃描條形碼 計(jì)算總價(jià) 收錢支付)。本案中,我們無需跟蹤結(jié)果,所以沒有PPT,側(cè)重是賣商品這個(gè)過程涉及的一系列操作和狀態(tài)改變。四色與聚合四色與聚合 上下文有界上下文場(chǎng)景在場(chǎng)景中,可以對(duì)聚合的狀態(tài)進(jìn)行斷言,驗(yàn)證聚合設(shè)計(jì)的正確性。場(chǎng)景能對(duì)模型進(jìn)行驗(yàn)證,但是因?yàn)榈?xì)節(jié)無法左右模型設(shè)計(jì)。聚合根Aggregate一個(gè)聚合是一簇相關(guān)聯(lián)的對(duì)象,出于數(shù)據(jù)變化的目的,將這些對(duì)象視為一個(gè)單元。每個(gè)聚合都有一個(gè)根和一個(gè)邊界。邊界定義了聚合中應(yīng)該包含什么。根是包含在聚合中的單個(gè)特定實(shí)體。根是聚合中唯一允許被外部引用的元素,在聚合邊界內(nèi),對(duì)象之間可以相互引用

14、。實(shí)際就是整體和部分的關(guān)系。轎車根Cargo貨運(yùn)路線案例聚合內(nèi)之間不可隨意關(guān)聯(lián)聚合體之間 只引用對(duì)方的聚合根聚合體內(nèi)部模型元素實(shí)體(Entity) A thread of continuity and identity.在時(shí)間上一系列連續(xù)性(continuity)和標(biāo)識(shí)(identityID)來定義。值對(duì)象(Value Object):如果一個(gè)對(duì)象代表了領(lǐng)域的某種描述性特征,且沒有概念性的標(biāo)識(shí)。Description原型。實(shí)體實(shí)體就是在客觀世界中有實(shí)體內(nèi)容的物體對(duì)象。經(jīng)過時(shí)間延續(xù)一直保持其特點(diǎn)不變。軟件實(shí)際是客觀世界的拷貝或鏡子,實(shí)體就是鏡子中那個(gè)實(shí)物。必須擁有自己的唯一ID,主鍵,如果沒有一

15、個(gè)ID標(biāo)識(shí),為每個(gè)實(shí)例加上一個(gè)具有唯一性ID,可能是內(nèi)部使用。由于對(duì)象主觀認(rèn)定性,在特殊情況下,我們可能會(huì)主觀劃分一些實(shí)體。聚合體內(nèi)部切分值對(duì)象許多對(duì)象沒有標(biāo)識(shí),只是事物的某些性質(zhì)描述。四色原型中的藍(lán)色des直接對(duì)應(yīng)值對(duì)象。將所有對(duì)象都加上標(biāo)識(shí),會(huì)影響系統(tǒng)的性能,增加復(fù)雜性,使所有對(duì)象看上去都是一個(gè)模式,混亂。只關(guān)心what,不關(guān)心who 或 which,只關(guān)心對(duì)象是什么?如果有多個(gè)這樣對(duì)象排列在一起,我們不用去分辨它們。只關(guān)心what:有兩只相同顏色和粗細(xì)的筆,隨便拿一個(gè)都可以畫畫。實(shí)體切分實(shí)體和值對(duì)象值對(duì)象設(shè)計(jì)由于不關(guān)心軟件運(yùn)行時(shí)使用的是值對(duì)象的哪個(gè)實(shí)例,沒有了分辨拘束,可提升性能和優(yōu)化。

16、值對(duì)象復(fù)制性:兩個(gè)人具有相同名字,表示名字的值對(duì)象可以互換復(fù)制,不會(huì)使他們成為一個(gè)人。值對(duì)象共享性:兩個(gè)Person對(duì)象不需要自己各自的Name值對(duì)象,可以共用一個(gè)Name值對(duì)象。值對(duì)象不變性:值對(duì)象屬于實(shí)體,當(dāng)實(shí)體把它的值對(duì)象傳遞給其他對(duì)象時(shí),如果其他對(duì)象對(duì)這個(gè)傳過來的值對(duì)象修改不當(dāng),就會(huì)破壞其所有者的不變性約束,從而破壞它的所有者實(shí)體對(duì)象。值對(duì)象共享值對(duì)象非常巨大,每個(gè)電源插座都是一個(gè)值對(duì)象,一個(gè)房子有上百個(gè)插座對(duì)象,由于值對(duì)象可以互換 共享,只使用一個(gè)插座實(shí)例就可以。Flyweight模式:避免大量擁有相同內(nèi)容的小類的開銷(如耗費(fèi)內(nèi)存),使大家共享一個(gè)類(元類)。不適用于實(shí)體。值對(duì)象復(fù)制

17、Prototype模式允許一個(gè)對(duì)象再創(chuàng)建另外一個(gè)可定制的對(duì)象,根本無需知道任何如何創(chuàng)建的細(xì)節(jié)。Java的clone也是一種復(fù)制。復(fù)制產(chǎn)生大量對(duì)象會(huì)阻塞系統(tǒng),但適合在分布式系統(tǒng)中,相反,使用共享,會(huì)降低性能;高并發(fā)系統(tǒng)中,復(fù)制減少鎖處理,共享需要精妙的鎖處理技巧。狀態(tài)用值對(duì)象表達(dá)狀態(tài)的改變是原子性的。狀態(tài)具有不可變性。一旦構(gòu)成不再改變class MyState private final int lower; private final int upper; public MyState(int lower, int upper) this.lower = lower this.upper =

18、upper; 采購訂單訂單不變量約束所以采購單項(xiàng)的金額之和不得超過采購單的最高限額。不變量保證:當(dāng)加入新子項(xiàng)時(shí),PO對(duì)總金額檢查,如果不對(duì),把自己標(biāo)記非法,不好。變更管理:刪除PO時(shí),子項(xiàng)同時(shí)刪除,但是它們關(guān)聯(lián)關(guān)系何時(shí)終止,模型沒有指示。不同時(shí)間修改商品價(jià)格會(huì)造成哪些影響無法評(píng)估。并發(fā)共享:如何解決多個(gè)用戶同時(shí)修改一個(gè)PO?并發(fā)鎖粒度如果多個(gè)用戶同時(shí)修改一個(gè)PO,我們必須對(duì)這個(gè)PO實(shí)例鎖定,以讓某個(gè)時(shí)刻只能一個(gè)用戶修改。通過數(shù)據(jù)庫鎖機(jī)制或者使用線程鎖機(jī)制實(shí)現(xiàn),關(guān)鍵是鎖PO整個(gè)實(shí)例帶來問題,這種鎖排他性的,就無法允許其他用戶也許對(duì)PO其他部分進(jìn)行訪問,性能差。更改模型,根據(jù)修改頻繁程度單獨(dú)列出一

19、個(gè)對(duì)象,比如Price經(jīng)常修改,就成為Price對(duì)象,鎖定Price這個(gè)小對(duì)象,無需鎖定整個(gè)PO。狀態(tài)作為獨(dú)立對(duì)象Jdon分析法與四色在語義上的一致蜘蛛網(wǎng)式模型類圖購書需求分析一個(gè)系統(tǒng)要從Jdon分析法的橫向和縱向方向:首先縱向,用DDD找出聚合根實(shí)體,代表這個(gè)系統(tǒng)的結(jié)構(gòu)本質(zhì),很顯然這里是BOOK。再從橫向:用戶發(fā)出操作命令產(chǎn)生事件,在這個(gè)系統(tǒng)中,用戶發(fā)出挑選或購買書籍BOOK的命令,也就是購書活動(dòng),改變了聚合根BOOK的狀態(tài)。什么狀態(tài)呢?1. 挑選命令致使BOOK放入購物車,2.購買書籍命令致使BOOK加入了訂單。選書場(chǎng)景買書場(chǎng)景Cargo用例:什么人做什么事Cargo四色圖Jdon分析法聚

20、合粗圖深入細(xì)節(jié)重構(gòu)突破隱式和顯式在需求中找到隱式概念,把它轉(zhuǎn)為顯式就是一種突破。不斷細(xì)化,當(dāng)開發(fā)人員識(shí)別出某個(gè)概念,就會(huì)對(duì)設(shè)計(jì)和代碼進(jìn)行修改,加入一個(gè)或多個(gè)對(duì)象和關(guān)系,將這個(gè)概念顯式表達(dá)出來。檢查不協(xié)調(diào)的地方。研究矛盾之處。顯式約束找出規(guī)格規(guī)格代表一種事物的特征,事物區(qū)別于其他事物的特征約束。很多業(yè)務(wù)規(guī)則和算法,包括復(fù)雜查詢都可以Specification模式來實(shí)現(xiàn)。大量使用Specification模式,將Specification模式整入領(lǐng)域模型,變成充血真正對(duì)象模型。細(xì)化直至模型有一定的靈活性靈活性就是抓住本質(zhì),考慮長(zhǎng)遠(yuǎn)拓展。領(lǐng)域中一定某個(gè)地方存在一種旋律和共鳴,存在內(nèi)在一致性,模型要與

21、領(lǐng)域某個(gè)部分發(fā)生共振。靈活設(shè)計(jì)可以使模型更加趨近這個(gè)旋律,隨著項(xiàng)目開發(fā)的進(jìn)行,感到速度越來越快,而不是越來越慢 。沒有通用菜譜式的規(guī)則,粒度大小是否適當(dāng)?是否符合具體情況。過度復(fù)雜過度工程(overengineering)打著靈活性旗號(hào),多余的抽象和間接層次弄巧成拙反復(fù)重構(gòu)帶來柔性。Specification規(guī)格模式業(yè)務(wù)規(guī)則不適合放入實(shí)體和值對(duì)象,規(guī)則的變化和組合會(huì)很多,包括各種算法或者條件判斷,這些會(huì)掩蓋領(lǐng)域?qū)ο蟮幕竞x,這些就放入專門對(duì)象Specification中。Specification表示業(yè)務(wù)規(guī)則,有指定要求的意思。Specification類似圍繞實(shí)體的值對(duì)象。Specific

22、ation種類驗(yàn)證:驗(yàn)證一個(gè)對(duì)象,看它是否滿足某些業(yè)務(wù)要求,或者是否已經(jīng)準(zhǔn)備就緒,與狀態(tài)有關(guān)。篩選過濾:從一個(gè)集合中篩選出符合指定要求的對(duì)象。類似SQL的Where語句按需創(chuàng)建:創(chuàng)建一個(gè)對(duì)象時(shí)指定該對(duì)象必須滿足某種要求。下訂單要求廠家按照指定規(guī)格生產(chǎn)產(chǎn)品。運(yùn)輸規(guī)格Specification運(yùn)輸路線或目的地屬于一種對(duì)貨運(yùn)運(yùn)輸?shù)囊?guī)劃。運(yùn)輸規(guī)格:目的地和抵達(dá)時(shí)間。在運(yùn)輸目的地和Cargo之間引入第三者規(guī)格類,可以實(shí)現(xiàn)靈活的運(yùn)輸路線策略替換。運(yùn)輸具體行為可能復(fù)雜多樣,單獨(dú)抽象作為一個(gè)類,能夠應(yīng)付復(fù)雜變化的運(yùn)輸方式。將“做什么”和“怎么做”分離。更改完善后四色圖增加細(xì)節(jié)前面類圖是一個(gè)細(xì)化的靜態(tài)類圖。主要

23、增加了下面幾個(gè)類:Delivery History 這是一個(gè)貨物的運(yùn)輸歷史記錄實(shí)體,用來記錄Cargo的裝卸事件。Carrier Movement特定運(yùn)輸工具卡車或貨輪從一個(gè)地點(diǎn)到另外一個(gè)地點(diǎn),這是確定好的,Cargo是否能夠搭上Carrier ,需要預(yù)約。這個(gè)對(duì)象屬于預(yù)約應(yīng)用模塊。區(qū)分實(shí)體和值對(duì)象該需求是為貨物的預(yù)約運(yùn)輸以及裝卸事件,顯然Cargo是一個(gè)聚合根。而Delivery Specification是從Cargo中分離出來,無疑屬于聚合邊界內(nèi)Delivery Specification 是實(shí)體還是值對(duì)象? Delivery Specification實(shí)際是一個(gè)運(yùn)輸規(guī)則,如果兩個(gè)貨物的

24、目的地相同,它們可以共享同一個(gè)Delivery Specification 。因此Delivery Specification是值對(duì)象。聚合Repository定義數(shù)據(jù)庫只是對(duì)象的永久保存方式,就象我們打字時(shí)經(jīng)常需要存盤一樣,我們不能因?yàn)橐按姹P”而去關(guān)心“存盤文件格式(數(shù)據(jù)表結(jié)構(gòu))”。我們應(yīng)該更聚焦在模型這個(gè)對(duì)象,把所有對(duì)象的保存(冬眠)和調(diào)用(激活)交由Respository完成。對(duì)象保存到數(shù)據(jù)庫交由專門的Repository倉儲(chǔ)來完成,由Repository負(fù)責(zé)如何將對(duì)象分解成數(shù)據(jù)庫能夠保存的格式。查詢倉儲(chǔ)Specification查詢存在大量項(xiàng)目,但必須是圍繞實(shí)體聚合根對(duì)象的查詢,可以

25、使用專門框架。引入Specification制定,用來讓客戶端將它希望獲得的查詢結(jié)果描述出來,也就是制定出來。輸入?yún)?shù)使用Criteria來封裝各種查詢輸入?yún)?shù),提供Criteria的查詢框架比較復(fù)雜,如Hibernate的Criteria。如果聚合中有大數(shù)據(jù),可通過懶加載lazy延遲加載,只返回一個(gè)代理,使用時(shí),再進(jìn)行加載。Repository需求改變:貨物目的地改變有顧客打電話說:希望將原來送貨到Hackensack,現(xiàn)在必須把它送到Hoboken,系統(tǒng)必須支持這種改變。由于Delivery Specification是一個(gè)值對(duì)象,可以扔掉再新建一個(gè),再調(diào)用Cargo的settet方法把原

26、來Delivery Specification替換成新的。重復(fù)業(yè)務(wù)用戶告訴我們:同一個(gè)顧客多次重復(fù)預(yù)訂往往類似的,他們希望用舊的Cargo作為原型創(chuàng)建新的Cargo。使用原型模式Prototype來復(fù)制Cargo。Cargo是一個(gè)聚合的根,因此有其他子對(duì)象,復(fù)制時(shí)必須小心。邊界內(nèi)每個(gè)子對(duì)象都要逐個(gè)處理。值對(duì)象Delivery Specification直接創(chuàng)建新的。復(fù)制時(shí)原則是不要對(duì)聚合邊界意外的任何對(duì)象產(chǎn)生影響。聚合的生命周期在生命周期中維護(hù)對(duì)象的完整性。避免模型由于管理生命周期的復(fù)雜性而陷入困境。三個(gè)模式來處理: 1. 聚合(Aggregate):定義清晰的所有權(quán)和邊界使模型更加緊湊,避免

27、出現(xiàn)盤根錯(cuò)節(jié)的對(duì)象關(guān)系網(wǎng)。聚合圈出一個(gè)范圍,在這個(gè)范圍中,對(duì)象無論在哪個(gè)生命周期,保持不變性。 2. 工廠(Factory) 3. 倉儲(chǔ)(Respository) 生命周期之始,使用工廠和組合提供了訪問和控制模型對(duì)象的方法生命周期邊界和管理聚合圈出一個(gè)范圍如前圖中紅線,在這個(gè)范圍中,對(duì)象無論在哪個(gè)生命周期,保持不變性。也就是子對(duì)象和父對(duì)象的生命周期是一致不變的。建立聚合的模型,并且把工廠和組合加入設(shè)計(jì)中來,可以使我們系統(tǒng)地對(duì)模型對(duì)象生命周期進(jìn)行管理。生命周期之始,使用工廠和Repository提供了訪問和控制模型對(duì)象的方法。工廠生命周期管理具有復(fù)雜的職責(zé),如果讓一個(gè)復(fù)雜對(duì)象來負(fù)責(zé)自身的創(chuàng)建工作

28、,會(huì)由于職責(zé)過載產(chǎn)生問題,人不能拎著自己頭發(fā)拔高,孫猴子也是從石頭縫里出來的,不是從自己身體鉆出來的。復(fù)雜對(duì)象的創(chuàng)建和組裝應(yīng)該由單獨(dú)工廠實(shí)現(xiàn),也就是工廠模式。將對(duì)象創(chuàng)建和使用分離。工廠屬于領(lǐng)域?qū)?,工廠把聚合作為一個(gè)整體創(chuàng)建出來,創(chuàng)建方法必須是原子的,保證其不變量得到滿足。專門工廠創(chuàng)建聚合如果聚合根需要一個(gè)工廠創(chuàng)建,又不適合充當(dāng)工廠,也就是沒有一個(gè)自然地方容納工廠,那么就創(chuàng)建一個(gè)專門的工廠對(duì)象或服務(wù)。Cargo工廠無論為Cargo創(chuàng)建一個(gè)強(qiáng)大工廠還是用復(fù)制原型來作為工廠,我們都需要一個(gè)基本構(gòu)造方法。構(gòu)造方法產(chǎn)生的對(duì)象能夠滿足自身不變性。HandlingEvent當(dāng)貨物發(fā)生裝卸事件時(shí),用戶會(huì)通過界

29、面或系統(tǒng)Incident Logging Application輸入一個(gè)Handling Event。Cargo和裝卸完成時(shí)間以及事件類型可以組成一個(gè)Handling Event對(duì)象HandlingEvent工廠創(chuàng)建一個(gè)新裝卸事件,是使用Carrier Movement進(jìn)行運(yùn)輸?shù)难b卸事件,將貨物裝到Carrier ,下一步由Carrier 運(yùn)輸。裝卸事件類型有:裝貨 卸貨 加封條 存放。下面是莊家一個(gè)裝貨事件的工廠代碼避免同時(shí)修改引起的競(jìng)爭(zhēng)每當(dāng)增加HandlingEvent時(shí),需要把這個(gè)新事件加入Delivery History, Delivery History是保存以往所有裝卸事件。這樣我

30、們才能從Delivery History中跟蹤裝卸事件。如果某個(gè)其他用戶正在修改Cargo,當(dāng)前HandlingEvent正在將自身通過Cargo加入Delivery History的HandlingEvent集合(如addHistory)。這樣就發(fā)生兩個(gè)同時(shí)并發(fā)修改,其中一個(gè)事務(wù)將失敗或被推遲。增加HandlingEvent進(jìn)入Delivery History是一個(gè)很重要的事務(wù)過程,必須確保沒有干擾下無競(jìng)爭(zhēng)環(huán)境中安全可靠執(zhí)行。輸入HandlingEvent必須是簡(jiǎn)單快捷。將Delivery History的HandlingEvent集合用查詢替代查詢還是關(guān)聯(lián)獲得一個(gè)對(duì)象有兩種方式:通過聚合根

31、;通過直接查詢。原來我們將HandlingEvent加入DeliveryHistory的集合中,兩者是一個(gè)多對(duì)一關(guān)聯(lián)聚合。DeliveryHistory和Cargo是一對(duì)一關(guān)聯(lián),記錄Cargo的運(yùn)輸歷史。 HandlingEvent和Cargo又是一個(gè)關(guān)聯(lián),形成一個(gè)封閉循環(huán)。將HandlingEvent和DeliveryHistory的多對(duì)一聚合關(guān)聯(lián)去除,用查詢來替代。查詢Repository替代關(guān)聯(lián)HandlingEvent倉儲(chǔ)HandlingEvent Repository提供根據(jù)一個(gè)給定的ID來查詢Cargo來功能。如findCargoByTimeType or findCargoByTracingID來查詢。獲得HandlingEvent集合。然后用戶輸入新的HandlingEvent,只要直接加入這個(gè)查詢出來的集合就可以。加入HandlingEvent就不再受其他事務(wù)干擾。這個(gè)集合可以保存在內(nèi)存中。模型完整性實(shí)現(xiàn)大型系統(tǒng)領(lǐng)域模型的完全同意是不可行的或者代價(jià)太高。需要統(tǒng)一的部分保持一致性,而不需要統(tǒng)一的部分不會(huì)引起誤解甚

溫馨提示

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

最新文檔

評(píng)論

0/150

提交評(píng)論