版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
領(lǐng)域驅(qū)動(dòng)建模(EvansDDD)領(lǐng)域驅(qū)動(dòng)建模(EvansDDD)EvansDDD2004年EricEvans發(fā)表Domain-DrivenDesign–TacklingComplexityintheHeartofSoftware(領(lǐng)域驅(qū)動(dòng)設(shè)計(jì))簡(jiǎn)稱EvansDDD領(lǐng)域建模是一種藝術(shù)的技術(shù),它是用來解決復(fù)雜軟件快速應(yīng)付變化的解決之道EvansDDD2004年EricEvans發(fā)表DomEvansDDDEvansDDD領(lǐng)域模型重要性沒有領(lǐng)域模型,只是靠代碼編寫完成一個(gè)又一個(gè)功能,復(fù)雜的領(lǐng)域需求會(huì)使得他們無法交流討論,使工作陷入泥沼。有少許領(lǐng)域模型,但是沒有維護(hù)好模型與代碼直接的聯(lián)系,兩者產(chǎn)生差異,無法實(shí)現(xiàn)。領(lǐng)域模型重要性沒有領(lǐng)域模型,只是靠代碼編寫完成一個(gè)又一個(gè)功能DDD優(yōu)點(diǎn)DDD優(yōu)點(diǎn)分析設(shè)計(jì)發(fā)展的三個(gè)階段第一階段:圍繞數(shù)據(jù)庫的驅(qū)動(dòng)設(shè)計(jì),新項(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)。分析設(shè)計(jì)發(fā)展的三個(gè)階段第一階段:圍繞數(shù)據(jù)庫的驅(qū)動(dòng)設(shè)計(jì),新項(xiàng)目第一階段:傳統(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)的。第一階段:傳統(tǒng)的數(shù)據(jù)庫方式過去軟件系統(tǒng)分析設(shè)計(jì)總是從數(shù)據(jù)庫開第二階段:分析和設(shè)計(jì)分裂第二階段比第一階段進(jìn)步很多,開始采取面向?qū)ο蟮姆椒▉矸治鲈O(shè)計(jì)需求。分析人員的職責(zé):是負(fù)責(zé)從需求領(lǐng)域中收集基本概念。面向需求。設(shè)計(jì)人員的職責(zé):必須指明一組能北項(xiàng)目中適應(yīng)編程工具構(gòu)造的組件,這些組件必須能夠在目標(biāo)環(huán)境中有效執(zhí)行,并能夠正確解決應(yīng)用程序出現(xiàn)的問題兩個(gè)階段目標(biāo)不一致,導(dǎo)致分裂,項(xiàng)目失敗。第二階段:分析和設(shè)計(jì)分裂第二階段比第一階段進(jìn)步很多,開始采取新階段:分析設(shè)計(jì)統(tǒng)一語言統(tǒng)一領(lǐng)域模型,它同時(shí)滿足分析原型和軟件設(shè)計(jì),如果一個(gè)模型實(shí)現(xiàn)時(shí)不實(shí)用,重新尋找新模型。一個(gè)無處不在(ubiquitous)的語言,項(xiàng)目中所有人統(tǒng)一交流的語言。減少溝通疑惑,減少傳達(dá)走樣。使得軟件更加適合需求。新階段:分析設(shè)計(jì)統(tǒng)一語言統(tǒng)一領(lǐng)域模型,它同時(shí)滿足分析原型和軟沒有領(lǐ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ǔ)?沒有領(lǐng)域(邊界)的模型一個(gè)印在大紙張上的完整類圖,整面墻都被領(lǐng)域模型在軟件架構(gòu)中位置領(lǐng)域模型在軟件架構(gòu)中位置什么是領(lǐng)域模型DomainModel?某個(gè)范圍內(nèi)的模型。首先是邊界劃分,在邊界中尋找代表領(lǐng)域本質(zhì)旋律的模型。領(lǐng)域模型只表達(dá)需求真實(shí)世界模型,和軟件架構(gòu)技術(shù)無關(guān)。模型都是有前提和范圍,或者稱為有場(chǎng)景前提的。沒有跨越范圍的永恒不變的模型。由領(lǐng)域?qū)<襾矶x領(lǐng)域模型。名詞==類名動(dòng)詞==類中方法服務(wù)或其他什么是領(lǐng)域模型DomainModel?某個(gè)范圍內(nèi)的模型。機(jī)器人機(jī)器人機(jī)器人的領(lǐng)域模型機(jī)器人的領(lǐng)域模型確定核心領(lǐng)域大型系統(tǒng)中,有很多有用的組件,他們非常復(fù)雜,都是軟件成功不可或缺的,這樣組件實(shí)在太多,以至于領(lǐng)域模型的精髓部分變得不明顯甚至被忽視。不可能所有部分都進(jìn)行提煉,分清輕重緩急,讓領(lǐng)域模型真正成為資產(chǎn)。核心模型必須足夠靈活和充分平衡來創(chuàng)建應(yīng)用程序功能,不要傾向于使用技術(shù)基礎(chǔ)結(jié)構(gòu)如數(shù)據(jù)庫來解決問題。無需專業(yè)業(yè)務(wù)知識(shí)容易能理解能引起程序員的興趣,他們認(rèn)為只有解決這些問題才能積累自己專業(yè)知識(shí),同時(shí)為自己簡(jiǎn)歷增光添彩,這對(duì)于公司是浪費(fèi)。確定核心領(lǐng)域大型系統(tǒng)中,有很多有用的組件,他們非常復(fù)雜,都是不注重核心領(lǐng)域的案例銀團(tuán)貸款系統(tǒng):大多數(shù)技術(shù)天才和技術(shù)高手都對(duì)數(shù)據(jù)庫映射層和消息接口津津樂道,而業(yè)務(wù)模型卻交給一些剛剛涉足面向?qū)ο蠹夹g(shù)的新手們打理。盡管為持久領(lǐng)域?qū)ο筇峁┰敿?xì)注解文字說明,能夠反映設(shè)計(jì)思路,也設(shè)計(jì)了友好的用戶界面。這些特性都是外圍,當(dāng)這個(gè)軟件最終交付用戶使用時(shí),差勁程序員二次開發(fā)拓展時(shí)卻依然搞得一塌糊涂,整個(gè)項(xiàng)目差點(diǎn)失敗。不注重核心領(lǐng)域的案例銀團(tuán)貸款系統(tǒng):大多數(shù)技術(shù)天才和技術(shù)高手都通用子域:非核心領(lǐng)域提煉核心領(lǐng)域,就必須剔除反面通用子域。不同行業(yè)運(yùn)輸業(yè)銀行業(yè)制造業(yè)都需要某種形式組織結(jié)構(gòu)圖。組織結(jié)構(gòu)圖就是通用子域。許多應(yīng)用跟蹤應(yīng)收帳款費(fèi)用分類和其他帳務(wù)信息,這些信息都可以使用通用的會(huì)計(jì)財(cái)務(wù)系統(tǒng)來處理。有兩個(gè)項(xiàng)目處理帶時(shí)區(qū)功能的日期和時(shí)間組件,花費(fèi)最好的程序員數(shù)周時(shí)間,雖然必須做,但不是系統(tǒng)核心??紤]現(xiàn)有解決方案或開源公開模型來替代通用子域。考慮外包,將通用子域外包,自己掌握核心領(lǐng)域。通用子域:非核心領(lǐng)域提煉核心領(lǐng)域,就必須剔除反面通用子域。領(lǐng)域中尋找核心模型找出核心模型,提供一種方法讓我們很容易地從眾多支持模型中將它區(qū)分出來,將最有價(jià)值最體現(xiàn)專門知識(shí)的概念凸顯出來,核心變小。讓最好的程序員來處理核心模型,根據(jù)需要調(diào)整人員的配備,盡力找出核心的深層模型,對(duì)于其他部分投入必須經(jīng)過考慮,是否能為提煉出來的核心提供支持。領(lǐng)域中尋找核心模型找出核心模型,提供一種方法讓我們很容易地從模型的特征模型表達(dá)的“是什么”,是戰(zhàn)略方向性,而不是”怎么做”等技術(shù)細(xì)節(jié)。設(shè)計(jì)中產(chǎn)生了一大堆用來實(shí)現(xiàn)算法解決問題的方法,而描述這個(gè)問題的方法變得模糊不清。怎么做的方法在模型中泛濫成災(zāi),表明模型存在某種問題。算法或計(jì)算非常復(fù)雜,導(dǎo)致設(shè)計(jì)受到了沖擊,模型中的概念變成了用“怎么做”來解釋,而不是用“是什么”表達(dá)。模型的特征模型表達(dá)的“是什么”,是戰(zhàn)略方向性,而不是”怎么做內(nèi)聚物體之所以成為物體,是因?yàn)槠鋬?nèi)聚機(jī)制。內(nèi)聚也就是一種組合組成關(guān)系,某個(gè)物體由哪些部分組成,或者說由這些部分內(nèi)聚聚合在一起。通過內(nèi)聚方式來切分領(lǐng)域,切分模型,尋找核心模型。算法計(jì)算機(jī)制本身存在內(nèi)聚性,使用策略模式等框架把這些內(nèi)聚計(jì)算分離出來,用一個(gè)明確接口來說明這個(gè)框架的功能,將怎么做復(fù)雜細(xì)節(jié)交給框架去完成。內(nèi)聚物體之所以成為物體,是因?yàn)槠鋬?nèi)聚機(jī)制。領(lǐng)域模型切割1.將復(fù)雜大的領(lǐng)域分割成子領(lǐng)域。2.抓住子領(lǐng)域的核心,建立核心模型。3.對(duì)核心模型實(shí)現(xiàn)靈活性細(xì)節(jié)設(shè)計(jì)領(lǐng)域模型切割1.將復(fù)雜大的領(lǐng)域分割成子領(lǐng)域。旁門左道的快速開發(fā)沒有分層架構(gòu)的快速開發(fā)基本是旁門左道,不如返回Foxpro和Delphi/VB兩層時(shí)代。將本屬于業(yè)務(wù)層的邏輯交由表現(xiàn)層來處理的快速UI方式也是一種旁門左道??焖匍_發(fā)必須基于良好的質(zhì)量,雖然良好的分層架構(gòu)帶來開發(fā)效率的降低,但是這些也是可以有方法解決。旁門左道的快速開發(fā)沒有分層架構(gòu)的快速開發(fā)基本是旁門左道,不如模型元素實(shí)體(Entity)Athreadofcontinuityandidentity.在時(shí)間上一系列連續(xù)性(continuity)和標(biāo)識(shí)(identity
ID)來定義。值對(duì)象(ValueObject):如果一個(gè)對(duì)象代表了領(lǐng)域的某種描述性特征,且沒有概念性的標(biāo)識(shí)。Description原型。服務(wù)(Service):行為接口。模型元素實(shí)體(Entity)實(shí)體實(shí)體就是在客觀世界中有實(shí)體內(nèi)容的物體對(duì)象。經(jīng)過時(shí)間延續(xù)一直保持其特點(diǎn)不變。軟件實(shí)際是客觀世界的拷貝或鏡子,實(shí)體就是鏡子中那個(gè)實(shí)物。必須擁有自己的唯一ID,主鍵,如果沒有一個(gè)ID標(biāo)識(shí),為每個(gè)實(shí)例加上一個(gè)具有唯一性ID,可能是內(nèi)部使用。由于對(duì)象主觀認(rèn)定性,在特殊情況下,我們可能會(huì)主觀劃分一些實(shí)體。
實(shí)體實(shí)體就是在客觀世界中有實(shí)體內(nèi)容的物體對(duì)象。經(jīng)過時(shí)間延續(xù)一實(shí)體建模實(shí)體最基本職責(zé)是保證連續(xù)性,以便使之有清晰可預(yù)見的行為。關(guān)注重點(diǎn)不是它們的屬性或行為,而是找出固有的特征,提出其他細(xì)節(jié)。這個(gè)固有特征包括:可以唯一標(biāo)識(shí)對(duì)象的特征;經(jīng)常用來查找或匹配對(duì)象的特征。只留下和特征相關(guān)的行為和屬性,其他則轉(zhuǎn)移到與該實(shí)體相關(guān)聯(lián)的其他對(duì)象。目的:保持實(shí)體高度精簡(jiǎn)。實(shí)體建模實(shí)體最基本職責(zé)是保證連續(xù)性,以便使之有清晰可預(yù)見的特征核心特征核心值對(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è)都可以畫畫。值對(duì)象許多對(duì)象沒有標(biāo)識(shí),只是事物的某些性質(zhì)描述。地址值對(duì)象郵購軟件中的地址是值對(duì)象:用地址作為發(fā)貨目的地。如果住在一起多個(gè)室友郵購,不影響郵遞,有名字作為標(biāo)識(shí)。郵政軟件中的地址是實(shí)體:將地區(qū)分層次結(jié)構(gòu),區(qū)城市街道郵編個(gè)人地址。電力運(yùn)營(yíng)軟件中地址是實(shí)體:如果住在一起多個(gè)室友申請(qǐng)電力服務(wù),電力公司必須區(qū)分。地址值對(duì)象郵購軟件中的地址是值對(duì)象:用地址作為發(fā)貨目的地。如值對(duì)象和實(shí)體是整體值對(duì)象和實(shí)體是整體值對(duì)象設(shè)計(jì)由于不關(guān)心軟件運(yùn)行時(shí)使用的是值對(duì)象的哪個(gè)實(shí)例,沒有了分辨拘束,可提升性能和優(yōu)化。值對(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ì)象設(shè)計(jì)由于不關(guān)心軟件運(yùn)行時(shí)使用的是值對(duì)象的哪個(gè)實(shí)例,沒有值對(duì)象共享值對(duì)象非常巨大,每個(gè)電源插座都是一個(gè)值對(duì)象,一個(gè)房子有上百個(gè)插座對(duì)象,由于值對(duì)象可以互換共享,只使用一個(gè)插座實(shí)例就可以。Flyweight模式:避免大量擁有相同內(nèi)容的小類的開銷(如耗費(fèi)內(nèi)存),使大家共享一個(gè)類(元類)。不適用于實(shí)體。值對(duì)象共享值對(duì)象非常巨大,每個(gè)電源插座都是一個(gè)值對(duì)象,一個(gè)房值對(duì)象復(fù)制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ù)制減少鎖處理,共享需要精妙的鎖處理技巧。值對(duì)象復(fù)制Prototype模式允許一個(gè)對(duì)象再創(chuàng)建另外一個(gè)可實(shí)體和值對(duì)象區(qū)分區(qū)分實(shí)體和值對(duì)象有助于我們?cè)诜治鲂枨髸r(shí)抓住重點(diǎn)(實(shí)體),有主次之分,綱舉目張。由于關(guān)注重點(diǎn)不同,就會(huì)對(duì)值對(duì)象定義不同。消費(fèi)拿起一瓶牛奶喝,這時(shí)我們關(guān)注的是他喝牛奶之外一些重點(diǎn),至于選擇哪個(gè)牛奶瓶不是我們關(guān)注重點(diǎn),隨便哪一個(gè)都行,這是值對(duì)象。對(duì)于牛奶生產(chǎn)商而言,每瓶牛奶都很重要,生產(chǎn)日期有效期等等,因此,這里牛奶瓶就成了實(shí)體。實(shí)體和值對(duì)象區(qū)分區(qū)分實(shí)體和值對(duì)象有助于我們?cè)诜治鲂枨髸r(shí)抓住重實(shí)體之間關(guān)系高內(nèi)聚低關(guān)聯(lián)是設(shè)計(jì)基本原則。是重構(gòu)的準(zhǔn)則。找出關(guān)聯(lián)是細(xì)分模型的一種方式,從而更恰當(dāng)?shù)囟x模型邊界。關(guān)聯(lián)不是手頭任務(wù)本質(zhì)或不能反映模型對(duì)象基本含義,完全取消它。少用雙向關(guān)聯(lián),除非技術(shù)性能要求。模型中關(guān)聯(lián)越少、越簡(jiǎn)單越好。完全擺脫數(shù)據(jù)庫影子,SQL語句作為規(guī)則封裝在模型中。實(shí)體之間關(guān)系高內(nèi)聚低關(guān)聯(lián)是設(shè)計(jì)基本原則。是重構(gòu)的準(zhǔn)則。聚合Aggregate一個(gè)聚合是一簇相關(guān)聯(lián)的對(duì)象,出于數(shù)據(jù)變化的目的,將這些對(duì)象視為一個(gè)單元。每個(gè)聚合都有一個(gè)根和一個(gè)邊界。邊界定義了聚合中應(yīng)該包含什么。根是包含在聚合中的單個(gè)特定實(shí)體。根是聚合中唯一允許被外部引用的元素,在聚合邊界內(nèi),對(duì)象之間可以相互引用。實(shí)際就是整體和部分的關(guān)系。聚合Aggregate一個(gè)聚合是一簇相關(guān)聯(lián)的對(duì)象,出于數(shù)據(jù)變轎車根轎車根聚合中的不變性不變性Invariants定義:無論何時(shí)數(shù)據(jù)發(fā)生變化,都必須滿足所有一致變化的規(guī)則,俗話:同生死。聚合內(nèi)部的不變量必須在每次事務(wù)完成時(shí)滿足。這可有倉儲(chǔ)來實(shí)現(xiàn)。一些依賴關(guān)系只能在某些特定的時(shí)刻通過事件借助有事務(wù)支持的服務(wù)來完成,或通過線程安全模式實(shí)現(xiàn)原子操作。聚合中的不變性不變性Invariants定義:無論何時(shí)數(shù)據(jù)發(fā)如何做到不變性根實(shí)體具有全局標(biāo)識(shí),并最終負(fù)責(zé)對(duì)不變量的檢查。根實(shí)體有全局標(biāo)識(shí),而邊界之內(nèi)實(shí)體有本地標(biāo)識(shí),這些標(biāo)識(shí)僅在聚合內(nèi)部是唯一的。聚合邊界外任何對(duì)象除了可以引用根實(shí)體,不能持有任何對(duì)其內(nèi)部對(duì)象的引用。根實(shí)體可以把內(nèi)部其他實(shí)體引用傳遞給其他對(duì)象,只能臨時(shí)使用。根實(shí)體可以復(fù)制內(nèi)部一個(gè)值對(duì)象實(shí)例副本給外部另外一個(gè)對(duì)象,副本再也與聚合無關(guān)系了。如何做到不變性根實(shí)體具有全局標(biāo)識(shí),并最終負(fù)責(zé)對(duì)不變量的檢查。CRUD中不變性約束通過數(shù)據(jù)庫查詢直接獲得的對(duì)象只有聚合的根,其他所有聚合內(nèi)對(duì)象可以通過聚合關(guān)系找到,性能上可采取懶加載防止大對(duì)象。刪除必須一次性刪除聚合邊界內(nèi)所有對(duì)象。當(dāng)在聚合邊界內(nèi)發(fā)生的任何對(duì)象修改被提交時(shí),整個(gè)聚合的所有不變量必須被滿足,也就是統(tǒng)一修改。CRUD中不變性約束通過數(shù)據(jù)庫查詢直接獲得的對(duì)象只有聚合的根聚合根和不變性聚合根和不變性采購訂單采購訂單訂單不變量約束所以采購單項(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?訂單不變量約束所以采購單項(xiàng)的金額之和不得超過采購單的最高限額并發(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ú)列出一個(gè)對(duì)象,比如Price經(jīng)常修改,就成為Price對(duì)象,鎖定Price這個(gè)小對(duì)象,無需鎖定整個(gè)PO。并發(fā)鎖粒度如果多個(gè)用戶同時(shí)修改一個(gè)PO,我們必須對(duì)這個(gè)PO實(shí)新訂單模型新訂單模型不變性的實(shí)現(xiàn)方式在生命周期中維護(hù)對(duì)象的完整性。避免模型由于管理生命周期的復(fù)雜性而陷入困境。三個(gè)模式來處理:
1.聚合(Aggregate):定義清晰的所有權(quán)和邊界使模型更加緊湊,避免出現(xiàn)盤根錯(cuò)節(jié)的對(duì)象關(guān)系網(wǎng)。聚合圈出一個(gè)范圍,在這個(gè)范圍中,對(duì)象無論在哪個(gè)生命周期,保持不變性。
2.工廠(Factory)
3.倉儲(chǔ)(Respository)生命周期之始,使用工廠和組合提供了訪問和控制模型對(duì)象的方法不變性的實(shí)現(xiàn)方式在生命周期中維護(hù)對(duì)象的完整性。避免模型由于管生命周期邊界和管理聚合圈出一個(gè)范圍如前圖中紅線,在這個(gè)范圍中,對(duì)象無論在哪個(gè)生命周期,保持不變性。也就是子對(duì)象和父對(duì)象的生命周期是一致不變的。建立聚合的模型,并且把工廠和組合加入設(shè)計(jì)中來,可以使我們系統(tǒng)地對(duì)模型對(duì)象生命周期進(jìn)行管理。生命周期之始,使用工廠和Repository提供了訪問和控制模型對(duì)象的方法。生命周期邊界和管理聚合圈出一個(gè)范圍如前圖中紅線,在這個(gè)范圍中工廠生命周期管理具有復(fù)雜的職責(zé),如果讓一個(gè)復(fù)雜對(duì)象來負(fù)責(zé)自身的創(chuàng)建工作,會(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)建方法必須是原子的,保證其不變量得到滿足。工廠生命周期管理具有復(fù)雜的職責(zé),如果讓一個(gè)復(fù)雜對(duì)象來負(fù)責(zé)自身專門工廠創(chuàng)建聚合如果聚合根需要一個(gè)工廠創(chuàng)建,又不適合充當(dāng)工廠,也就是沒有一個(gè)自然地方容納工廠,那么就創(chuàng)建一個(gè)專門的工廠對(duì)象或服務(wù)。專門工廠創(chuàng)建聚合如果聚合根需要一個(gè)工廠創(chuàng)建,又不適合充當(dāng)工廠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ù)庫能夠保存的格式。Repository由來數(shù)據(jù)庫只是對(duì)象的永久保存方式,就象我Repository和查詢不需要為通過導(dǎo)航方法能夠獲得持久對(duì)象提供查詢?cè)L問,聚合內(nèi)部對(duì)象可以通過根來導(dǎo)航。值對(duì)象無需全局查詢獲得,比較少見,值對(duì)象生命周期很短,屬于臨時(shí)對(duì)象,一般通過聚合根獲得。倉儲(chǔ)可以實(shí)現(xiàn)數(shù)據(jù)庫新增修改刪除和查詢CRUD,倉儲(chǔ)可以實(shí)現(xiàn)不同標(biāo)準(zhǔn)的各種查詢。Repository和查詢不需要為通過導(dǎo)航方法能夠獲得持久對(duì)Repository和工廠Repository和工廠Repository定義為客戶端訪問某一聚合類對(duì)象提供全局訪問接口Repository,Repository主要是在內(nèi)存中建立一系列的聚合對(duì)象。Repository提供CRUD等通用對(duì)象操作方法,把數(shù)據(jù)庫數(shù)據(jù)存儲(chǔ)插入和刪除等方法封裝起來。但是不插手事務(wù)。提供符合對(duì)象方式篩選查詢,僅為確實(shí)需要直接訪問的聚合根提供倉儲(chǔ),其他則不必。讓客戶端只關(guān)心模型,而不是數(shù)據(jù)存儲(chǔ)。存儲(chǔ)和訪問都交給Repository完成。Repository定義為客戶端訪問某一聚合類對(duì)象提供全局訪倉儲(chǔ)統(tǒng)一語言忽視持久化InfrastructureUIDomainDataAccessApplication/
Service倉儲(chǔ)統(tǒng)一語言忽視持久化InfrastructureUIDo查詢倉儲(chǔ)Specification模式查詢存在大量項(xiàng)目,但必須是圍繞實(shí)體聚合根對(duì)象的查詢,可以使用專門框架。引入Specification制定,用來讓客戶端將它希望獲得的查詢結(jié)果描述出來,也就是制定出來。輸入?yún)?shù)使用Criteria來封裝各種查詢輸入?yún)?shù),提供Criteria的查詢框架比較復(fù)雜,如Hibernate的Criteria。如果聚合中有大數(shù)據(jù),可通過懶加載lazy延遲加載,只返回一個(gè)代理,使用時(shí),再進(jìn)行加載。查詢倉儲(chǔ)Specification模式查詢存在大量項(xiàng)目,但必Specification模式業(yè)務(wù)規(guī)則不適合放入實(shí)體和值對(duì)象,規(guī)則的變化和組合會(huì)很多,包括各種算法或者條件判斷,這些會(huì)掩蓋領(lǐng)域?qū)ο蟮幕竞x,這些就放入專門對(duì)象Specification中。Specification表示業(yè)務(wù)規(guī)則,有指定要求的意思。Specification類似圍繞實(shí)體的值對(duì)象。Specification模式業(yè)務(wù)規(guī)則不適合放入實(shí)體和值對(duì)象第三種模型服務(wù)將行為放入對(duì)象才是真正對(duì)象,這樣可防止面向過程編程。但是放入不確當(dāng)行為,會(huì)破壞對(duì)象的清晰概念。有些對(duì)象側(cè)重于操作動(dòng)作行為,沒有狀態(tài),就象四色圖中MI,是一種活動(dòng)事件,這些對(duì)象應(yīng)該被標(biāo)記為服務(wù)。服務(wù)來源現(xiàn)實(shí):加油服務(wù)快遞服務(wù),服務(wù)不是一個(gè)過程化編程的概念。分應(yīng)用服務(wù)(事務(wù)安全)和領(lǐng)域服務(wù)。第三種模型服務(wù)將行為放入對(duì)象才是真正對(duì)象,這樣可防止面向過服務(wù)類型領(lǐng)域?qū)臃?wù):與業(yè)務(wù)有關(guān),需要協(xié)調(diào)多個(gè)實(shí)體完成的功能,比如資金轉(zhuǎn)賬;帖子CRUD;CashSales;下訂單等。應(yīng)用層服務(wù):與軟件設(shè)計(jì)有關(guān)的,在業(yè)務(wù)領(lǐng)域中沒有實(shí)際意義的行為活動(dòng),比如兩個(gè)業(yè)務(wù)系統(tǒng)的接口;實(shí)體和值對(duì)象由于過于細(xì)化松耦合,就無法提供一個(gè)訪問自身領(lǐng)域?qū)拥姆奖闳肟?,這時(shí)需要應(yīng)用服務(wù)。類似MVC中Controller職責(zé)?;A(chǔ)層服務(wù):比如發(fā)送Email,打印輸出等等,。服務(wù)類型領(lǐng)域?qū)臃?wù):與業(yè)務(wù)有關(guān),需要協(xié)調(diào)多個(gè)實(shí)體完成的功能,實(shí)體和行為操作的問題將業(yè)務(wù)行為都使用服務(wù)實(shí)現(xiàn),實(shí)體中除了setter/getter方法以外,就沒有任何實(shí)質(zhì)業(yè)務(wù)行為,這是貧血失血模型。如果將所有行為操作都塞入實(shí)體對(duì)象,那么實(shí)體對(duì)象變得非常龐大臃腫,失去靈活性。有很多行為操作無法被封裝進(jìn)實(shí)體,但是又涉及多個(gè)實(shí)體,呈現(xiàn)面向函數(shù)式特點(diǎn)(function)。實(shí)體和行為操作的問題將業(yè)務(wù)行為都使用服務(wù)實(shí)現(xiàn),實(shí)體中除了se職責(zé)驅(qū)動(dòng)開發(fā)面向?qū)ο笤O(shè)計(jì)方法很多,但是很少有關(guān)注行為過程。roles-and-responsibilities模型:對(duì)象扮演不同角色,實(shí)現(xiàn)不同職責(zé)。把應(yīng)用的職責(zé)切分到接口中成為其方法。然后實(shí)現(xiàn)職責(zé)行為之間的交互。用接口實(shí)現(xiàn)職責(zé),一個(gè)實(shí)體實(shí)現(xiàn)不同職責(zé)的接口。職責(zé)驅(qū)動(dòng)開發(fā)面向?qū)ο笤O(shè)計(jì)方法很多,但是很少有關(guān)注行為過程。什么是職責(zé)定義:對(duì)象執(zhí)行的動(dòng)作;對(duì)象包含的知識(shí):算法約束規(guī)格描述;當(dāng)前對(duì)象影響其他對(duì)象的主要因素。特征:知道knowing什么;做doing什么;決定deciding什么。構(gòu)造invention、約束表達(dá)、規(guī)格Specification和描述Description都可以成為職責(zé)。什么是職責(zé)定義:對(duì)象執(zhí)行的動(dòng)作;對(duì)象包含的知識(shí):算法約束分配職責(zé)將職責(zé)分配給對(duì)象,使得對(duì)象有形有態(tài)。按照高凝聚原則分配。遵循假設(shè):“如果沒有這個(gè)職責(zé),會(huì)怎樣”。如果發(fā)現(xiàn)職責(zé)太廣泛,不能分配到單個(gè)對(duì)象中,那么就切分職責(zé),由這些小職責(zé)組合成更大職責(zé)。分配職責(zé)將職責(zé)分配給對(duì)象,使得對(duì)象有形有態(tài)。職責(zé)實(shí)現(xiàn)一個(gè)對(duì)象能夠扮演多個(gè)角色使用方法行為來實(shí)現(xiàn)職責(zé)。不同角色有不同方法,如何解決這個(gè)矛盾?職責(zé)實(shí)現(xiàn)一個(gè)對(duì)象能夠扮演多個(gè)角色DCI架構(gòu)數(shù)據(jù)Data:領(lǐng)域模型。
場(chǎng)景Context:領(lǐng)域模型活動(dòng)存在的場(chǎng)景,或者前提條件。交互Interactions:模型在特定場(chǎng)景下以某種角色活動(dòng)的行為操作。不同角色有不同的交互。DCI架構(gòu)數(shù)據(jù)Data:領(lǐng)域模型。
DCI架構(gòu)和服務(wù)@Stateless
@Context
public
classForecastingContextimplementsForecastingContextLocal{
/**
*anasynchrounousmethodfordeterminingtheenergyrequirementsofthegiventrip.
*/
@Asynchronous
publicFutureforecastEnergyRequired(Triptrip){
BehaviourInjectorbi=newBehaviourInjector(this);
//場(chǎng)景將實(shí)體對(duì)象下塑為角色,開始交互行為DCI典型調(diào)用方式
EnergyConciousTript=bi.assignRole(trip,EnergyConciousTrip.class);
doubleenergy=t.forecastEnergyRequirements();
return
newAsyncResult(energy);
}
}DCI架構(gòu)和服務(wù)@Stateless
@Context
puDomainEvents領(lǐng)域事件領(lǐng)域事件是在不同場(chǎng)景下由實(shí)體發(fā)出事件驅(qū)動(dòng)服務(wù),通過類似異步消息機(jī)制實(shí)現(xiàn)松耦合。場(chǎng)景隱含,事件代表場(chǎng)景出頭牽線。DCI架構(gòu)是主動(dòng)將功能實(shí)現(xiàn)的參與者(數(shù)據(jù)模型角色和行為場(chǎng)景)進(jìn)行動(dòng)態(tài)組合。領(lǐng)域時(shí)間和DCI架構(gòu)都將薄化服務(wù)模型,減少服務(wù)模型臃腫的現(xiàn)象(或者M(jìn)VC的控制器)。DomainEvents領(lǐng)域事件領(lǐng)域事件是在不同場(chǎng)景下由實(shí)DomainEventsDownloadSourceDomainEventsDownloadSourceDomainEvents工作原理DomainModel@ModelListerner@ComponentJavaconcurrentFutureDomainMessagePool.run開源框架JdonFramework提供DE機(jī)制/jdonframework/
DomainEvents工作原理DomainModeCQRS架構(gòu)(CommandQueryResponsibilitySegregation)讀寫分離;更加伸縮:(1)寫==Commands命令==主要是改變模型狀態(tài),無返回結(jié)果。(2)讀==Queries查詢==純粹讀取,不改變?nèi)魏文P蜖顟B(tài)。使用基于DomainEvents的EDA架構(gòu)(Event-DrivenArchitecture)??蓴U(kuò)展至消息或異步系統(tǒng)。CQRS架構(gòu)(CommandQueryResponsibCQRS(命令查詢分離)架構(gòu)UserinterfaceServiceDomainEvent/MessageBUSInfrastructureQuery/ReportingCommandsCommandsEventsCQRS(命令查詢分離)架構(gòu)UserinterfaceSe更多資料和資源DDD領(lǐng)域驅(qū)動(dòng)設(shè)計(jì):/jivejdon/tags/272
CQRS架構(gòu):/jivejdon/tags/9958
DCI架構(gòu):/jivejdon/tags/10443
DDD開放源碼案例系統(tǒng)JiveJdon:/jdonframework/jivejdon3/index.html
更多資料和資源DDD領(lǐng)域驅(qū)動(dòng)設(shè)計(jì):領(lǐng)域驅(qū)動(dòng)建模(EvansDDD)領(lǐng)域驅(qū)動(dòng)建模(EvansDDD)EvansDDD2004年EricEvans發(fā)表Domain-DrivenDesign–TacklingComplexityintheHeartofSoftware(領(lǐng)域驅(qū)動(dòng)設(shè)計(jì))簡(jiǎn)稱EvansDDD領(lǐng)域建模是一種藝術(shù)的技術(shù),它是用來解決復(fù)雜軟件快速應(yīng)付變化的解決之道EvansDDD2004年EricEvans發(fā)表DomEvansDDDEvansDDD領(lǐng)域模型重要性沒有領(lǐng)域模型,只是靠代碼編寫完成一個(gè)又一個(gè)功能,復(fù)雜的領(lǐng)域需求會(huì)使得他們無法交流討論,使工作陷入泥沼。有少許領(lǐng)域模型,但是沒有維護(hù)好模型與代碼直接的聯(lián)系,兩者產(chǎn)生差異,無法實(shí)現(xiàn)。領(lǐng)域模型重要性沒有領(lǐng)域模型,只是靠代碼編寫完成一個(gè)又一個(gè)功能DDD優(yōu)點(diǎn)DDD優(yōu)點(diǎn)分析設(shè)計(jì)發(fā)展的三個(gè)階段第一階段:圍繞數(shù)據(jù)庫的驅(qū)動(dòng)設(shè)計(jì),新項(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)。分析設(shè)計(jì)發(fā)展的三個(gè)階段第一階段:圍繞數(shù)據(jù)庫的驅(qū)動(dòng)設(shè)計(jì),新項(xiàng)目第一階段:傳統(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)的。第一階段:傳統(tǒng)的數(shù)據(jù)庫方式過去軟件系統(tǒng)分析設(shè)計(jì)總是從數(shù)據(jù)庫開第二階段:分析和設(shè)計(jì)分裂第二階段比第一階段進(jìn)步很多,開始采取面向?qū)ο蟮姆椒▉矸治鲈O(shè)計(jì)需求。分析人員的職責(zé):是負(fù)責(zé)從需求領(lǐng)域中收集基本概念。面向需求。設(shè)計(jì)人員的職責(zé):必須指明一組能北項(xiàng)目中適應(yīng)編程工具構(gòu)造的組件,這些組件必須能夠在目標(biāo)環(huán)境中有效執(zhí)行,并能夠正確解決應(yīng)用程序出現(xiàn)的問題兩個(gè)階段目標(biāo)不一致,導(dǎo)致分裂,項(xiàng)目失敗。第二階段:分析和設(shè)計(jì)分裂第二階段比第一階段進(jìn)步很多,開始采取新階段:分析設(shè)計(jì)統(tǒng)一語言統(tǒng)一領(lǐng)域模型,它同時(shí)滿足分析原型和軟件設(shè)計(jì),如果一個(gè)模型實(shí)現(xiàn)時(shí)不實(shí)用,重新尋找新模型。一個(gè)無處不在(ubiquitous)的語言,項(xiàng)目中所有人統(tǒng)一交流的語言。減少溝通疑惑,減少傳達(dá)走樣。使得軟件更加適合需求。新階段:分析設(shè)計(jì)統(tǒng)一語言統(tǒng)一領(lǐng)域模型,它同時(shí)滿足分析原型和軟沒有領(lǐ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ǔ)?沒有領(lǐng)域(邊界)的模型一個(gè)印在大紙張上的完整類圖,整面墻都被領(lǐng)域模型在軟件架構(gòu)中位置領(lǐng)域模型在軟件架構(gòu)中位置什么是領(lǐng)域模型DomainModel?某個(gè)范圍內(nèi)的模型。首先是邊界劃分,在邊界中尋找代表領(lǐng)域本質(zhì)旋律的模型。領(lǐng)域模型只表達(dá)需求真實(shí)世界模型,和軟件架構(gòu)技術(shù)無關(guān)。模型都是有前提和范圍,或者稱為有場(chǎng)景前提的。沒有跨越范圍的永恒不變的模型。由領(lǐng)域?qū)<襾矶x領(lǐng)域模型。名詞==類名動(dòng)詞==類中方法服務(wù)或其他什么是領(lǐng)域模型DomainModel?某個(gè)范圍內(nèi)的模型。機(jī)器人機(jī)器人機(jī)器人的領(lǐng)域模型機(jī)器人的領(lǐng)域模型確定核心領(lǐng)域大型系統(tǒng)中,有很多有用的組件,他們非常復(fù)雜,都是軟件成功不可或缺的,這樣組件實(shí)在太多,以至于領(lǐng)域模型的精髓部分變得不明顯甚至被忽視。不可能所有部分都進(jìn)行提煉,分清輕重緩急,讓領(lǐng)域模型真正成為資產(chǎn)。核心模型必須足夠靈活和充分平衡來創(chuàng)建應(yīng)用程序功能,不要傾向于使用技術(shù)基礎(chǔ)結(jié)構(gòu)如數(shù)據(jù)庫來解決問題。無需專業(yè)業(yè)務(wù)知識(shí)容易能理解能引起程序員的興趣,他們認(rèn)為只有解決這些問題才能積累自己專業(yè)知識(shí),同時(shí)為自己簡(jiǎn)歷增光添彩,這對(duì)于公司是浪費(fèi)。確定核心領(lǐng)域大型系統(tǒng)中,有很多有用的組件,他們非常復(fù)雜,都是不注重核心領(lǐng)域的案例銀團(tuán)貸款系統(tǒng):大多數(shù)技術(shù)天才和技術(shù)高手都對(duì)數(shù)據(jù)庫映射層和消息接口津津樂道,而業(yè)務(wù)模型卻交給一些剛剛涉足面向?qū)ο蠹夹g(shù)的新手們打理。盡管為持久領(lǐng)域?qū)ο筇峁┰敿?xì)注解文字說明,能夠反映設(shè)計(jì)思路,也設(shè)計(jì)了友好的用戶界面。這些特性都是外圍,當(dāng)這個(gè)軟件最終交付用戶使用時(shí),差勁程序員二次開發(fā)拓展時(shí)卻依然搞得一塌糊涂,整個(gè)項(xiàng)目差點(diǎn)失敗。不注重核心領(lǐng)域的案例銀團(tuán)貸款系統(tǒng):大多數(shù)技術(shù)天才和技術(shù)高手都通用子域:非核心領(lǐng)域提煉核心領(lǐng)域,就必須剔除反面通用子域。不同行業(yè)運(yùn)輸業(yè)銀行業(yè)制造業(yè)都需要某種形式組織結(jié)構(gòu)圖。組織結(jié)構(gòu)圖就是通用子域。許多應(yīng)用跟蹤應(yīng)收帳款費(fèi)用分類和其他帳務(wù)信息,這些信息都可以使用通用的會(huì)計(jì)財(cái)務(wù)系統(tǒng)來處理。有兩個(gè)項(xiàng)目處理帶時(shí)區(qū)功能的日期和時(shí)間組件,花費(fèi)最好的程序員數(shù)周時(shí)間,雖然必須做,但不是系統(tǒng)核心??紤]現(xiàn)有解決方案或開源公開模型來替代通用子域。考慮外包,將通用子域外包,自己掌握核心領(lǐng)域。通用子域:非核心領(lǐng)域提煉核心領(lǐng)域,就必須剔除反面通用子域。領(lǐng)域中尋找核心模型找出核心模型,提供一種方法讓我們很容易地從眾多支持模型中將它區(qū)分出來,將最有價(jià)值最體現(xiàn)專門知識(shí)的概念凸顯出來,核心變小。讓最好的程序員來處理核心模型,根據(jù)需要調(diào)整人員的配備,盡力找出核心的深層模型,對(duì)于其他部分投入必須經(jīng)過考慮,是否能為提煉出來的核心提供支持。領(lǐng)域中尋找核心模型找出核心模型,提供一種方法讓我們很容易地從模型的特征模型表達(dá)的“是什么”,是戰(zhàn)略方向性,而不是”怎么做”等技術(shù)細(xì)節(jié)。設(shè)計(jì)中產(chǎn)生了一大堆用來實(shí)現(xiàn)算法解決問題的方法,而描述這個(gè)問題的方法變得模糊不清。怎么做的方法在模型中泛濫成災(zāi),表明模型存在某種問題。算法或計(jì)算非常復(fù)雜,導(dǎo)致設(shè)計(jì)受到了沖擊,模型中的概念變成了用“怎么做”來解釋,而不是用“是什么”表達(dá)。模型的特征模型表達(dá)的“是什么”,是戰(zhàn)略方向性,而不是”怎么做內(nèi)聚物體之所以成為物體,是因?yàn)槠鋬?nèi)聚機(jī)制。內(nèi)聚也就是一種組合組成關(guān)系,某個(gè)物體由哪些部分組成,或者說由這些部分內(nèi)聚聚合在一起。通過內(nèi)聚方式來切分領(lǐng)域,切分模型,尋找核心模型。算法計(jì)算機(jī)制本身存在內(nèi)聚性,使用策略模式等框架把這些內(nèi)聚計(jì)算分離出來,用一個(gè)明確接口來說明這個(gè)框架的功能,將怎么做復(fù)雜細(xì)節(jié)交給框架去完成。內(nèi)聚物體之所以成為物體,是因?yàn)槠鋬?nèi)聚機(jī)制。領(lǐng)域模型切割1.將復(fù)雜大的領(lǐng)域分割成子領(lǐng)域。2.抓住子領(lǐng)域的核心,建立核心模型。3.對(duì)核心模型實(shí)現(xiàn)靈活性細(xì)節(jié)設(shè)計(jì)領(lǐng)域模型切割1.將復(fù)雜大的領(lǐng)域分割成子領(lǐng)域。旁門左道的快速開發(fā)沒有分層架構(gòu)的快速開發(fā)基本是旁門左道,不如返回Foxpro和Delphi/VB兩層時(shí)代。將本屬于業(yè)務(wù)層的邏輯交由表現(xiàn)層來處理的快速UI方式也是一種旁門左道。快速開發(fā)必須基于良好的質(zhì)量,雖然良好的分層架構(gòu)帶來開發(fā)效率的降低,但是這些也是可以有方法解決。旁門左道的快速開發(fā)沒有分層架構(gòu)的快速開發(fā)基本是旁門左道,不如模型元素實(shí)體(Entity)Athreadofcontinuityandidentity.在時(shí)間上一系列連續(xù)性(continuity)和標(biāo)識(shí)(identity
ID)來定義。值對(duì)象(ValueObject):如果一個(gè)對(duì)象代表了領(lǐng)域的某種描述性特征,且沒有概念性的標(biāo)識(shí)。Description原型。服務(wù)(Service):行為接口。模型元素實(shí)體(Entity)實(shí)體實(shí)體就是在客觀世界中有實(shí)體內(nèi)容的物體對(duì)象。經(jīng)過時(shí)間延續(xù)一直保持其特點(diǎn)不變。軟件實(shí)際是客觀世界的拷貝或鏡子,實(shí)體就是鏡子中那個(gè)實(shí)物。必須擁有自己的唯一ID,主鍵,如果沒有一個(gè)ID標(biāo)識(shí),為每個(gè)實(shí)例加上一個(gè)具有唯一性ID,可能是內(nèi)部使用。由于對(duì)象主觀認(rèn)定性,在特殊情況下,我們可能會(huì)主觀劃分一些實(shí)體。
實(shí)體實(shí)體就是在客觀世界中有實(shí)體內(nèi)容的物體對(duì)象。經(jīng)過時(shí)間延續(xù)一實(shí)體建模實(shí)體最基本職責(zé)是保證連續(xù)性,以便使之有清晰可預(yù)見的行為。關(guān)注重點(diǎn)不是它們的屬性或行為,而是找出固有的特征,提出其他細(xì)節(jié)。這個(gè)固有特征包括:可以唯一標(biāo)識(shí)對(duì)象的特征;經(jīng)常用來查找或匹配對(duì)象的特征。只留下和特征相關(guān)的行為和屬性,其他則轉(zhuǎn)移到與該實(shí)體相關(guān)聯(lián)的其他對(duì)象。目的:保持實(shí)體高度精簡(jiǎn)。實(shí)體建模實(shí)體最基本職責(zé)是保證連續(xù)性,以便使之有清晰可預(yù)見的特征核心特征核心值對(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è)都可以畫畫。值對(duì)象許多對(duì)象沒有標(biāo)識(shí),只是事物的某些性質(zhì)描述。地址值對(duì)象郵購軟件中的地址是值對(duì)象:用地址作為發(fā)貨目的地。如果住在一起多個(gè)室友郵購,不影響郵遞,有名字作為標(biāo)識(shí)。郵政軟件中的地址是實(shí)體:將地區(qū)分層次結(jié)構(gòu),區(qū)城市街道郵編個(gè)人地址。電力運(yùn)營(yíng)軟件中地址是實(shí)體:如果住在一起多個(gè)室友申請(qǐng)電力服務(wù),電力公司必須區(qū)分。地址值對(duì)象郵購軟件中的地址是值對(duì)象:用地址作為發(fā)貨目的地。如值對(duì)象和實(shí)體是整體值對(duì)象和實(shí)體是整體值對(duì)象設(shè)計(jì)由于不關(guān)心軟件運(yùn)行時(shí)使用的是值對(duì)象的哪個(gè)實(shí)例,沒有了分辨拘束,可提升性能和優(yōu)化。值對(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ì)象設(shè)計(jì)由于不關(guān)心軟件運(yùn)行時(shí)使用的是值對(duì)象的哪個(gè)實(shí)例,沒有值對(duì)象共享值對(duì)象非常巨大,每個(gè)電源插座都是一個(gè)值對(duì)象,一個(gè)房子有上百個(gè)插座對(duì)象,由于值對(duì)象可以互換共享,只使用一個(gè)插座實(shí)例就可以。Flyweight模式:避免大量擁有相同內(nèi)容的小類的開銷(如耗費(fèi)內(nèi)存),使大家共享一個(gè)類(元類)。不適用于實(shí)體。值對(duì)象共享值對(duì)象非常巨大,每個(gè)電源插座都是一個(gè)值對(duì)象,一個(gè)房值對(duì)象復(fù)制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ù)制減少鎖處理,共享需要精妙的鎖處理技巧。值對(duì)象復(fù)制Prototype模式允許一個(gè)對(duì)象再創(chuàng)建另外一個(gè)可實(shí)體和值對(duì)象區(qū)分區(qū)分實(shí)體和值對(duì)象有助于我們?cè)诜治鲂枨髸r(shí)抓住重點(diǎn)(實(shí)體),有主次之分,綱舉目張。由于關(guān)注重點(diǎn)不同,就會(huì)對(duì)值對(duì)象定義不同。消費(fèi)拿起一瓶牛奶喝,這時(shí)我們關(guān)注的是他喝牛奶之外一些重點(diǎn),至于選擇哪個(gè)牛奶瓶不是我們關(guān)注重點(diǎn),隨便哪一個(gè)都行,這是值對(duì)象。對(duì)于牛奶生產(chǎn)商而言,每瓶牛奶都很重要,生產(chǎn)日期有效期等等,因此,這里牛奶瓶就成了實(shí)體。實(shí)體和值對(duì)象區(qū)分區(qū)分實(shí)體和值對(duì)象有助于我們?cè)诜治鲂枨髸r(shí)抓住重實(shí)體之間關(guān)系高內(nèi)聚低關(guān)聯(lián)是設(shè)計(jì)基本原則。是重構(gòu)的準(zhǔn)則。找出關(guān)聯(lián)是細(xì)分模型的一種方式,從而更恰當(dāng)?shù)囟x模型邊界。關(guān)聯(lián)不是手頭任務(wù)本質(zhì)或不能反映模型對(duì)象基本含義,完全取消它。少用雙向關(guān)聯(lián),除非技術(shù)性能要求。模型中關(guān)聯(lián)越少、越簡(jiǎn)單越好。完全擺脫數(shù)據(jù)庫影子,SQL語句作為規(guī)則封裝在模型中。實(shí)體之間關(guān)系高內(nèi)聚低關(guān)聯(lián)是設(shè)計(jì)基本原則。是重構(gòu)的準(zhǔn)則。聚合Aggregate一個(gè)聚合是一簇相關(guān)聯(lián)的對(duì)象,出于數(shù)據(jù)變化的目的,將這些對(duì)象視為一個(gè)單元。每個(gè)聚合都有一個(gè)根和一個(gè)邊界。邊界定義了聚合中應(yīng)該包含什么。根是包含在聚合中的單個(gè)特定實(shí)體。根是聚合中唯一允許被外部引用的元素,在聚合邊界內(nèi),對(duì)象之間可以相互引用。實(shí)際就是整體和部分的關(guān)系。聚合Aggregate一個(gè)聚合是一簇相關(guān)聯(lián)的對(duì)象,出于數(shù)據(jù)變轎車根轎車根聚合中的不變性不變性Invariants定義:無論何時(shí)數(shù)據(jù)發(fā)生變化,都必須滿足所有一致變化的規(guī)則,俗話:同生死。聚合內(nèi)部的不變量必須在每次事務(wù)完成時(shí)滿足。這可有倉儲(chǔ)來實(shí)現(xiàn)。一些依賴關(guān)系只能在某些特定的時(shí)刻通過事件借助有事務(wù)支持的服務(wù)來完成,或通過線程安全模式實(shí)現(xiàn)原子操作。聚合中的不變性不變性Invariants定義:無論何時(shí)數(shù)據(jù)發(fā)如何做到不變性根實(shí)體具有全局標(biāo)識(shí),并最終負(fù)責(zé)對(duì)不變量的檢查。根實(shí)體有全局標(biāo)識(shí),而邊界之內(nèi)實(shí)體有本地標(biāo)識(shí),這些標(biāo)識(shí)僅在聚合內(nèi)部是唯一的。聚合邊界外任何對(duì)象除了可以引用根實(shí)體,不能持有任何對(duì)其內(nèi)部對(duì)象的引用。根實(shí)體可以把內(nèi)部其他實(shí)體引用傳遞給其他對(duì)象,只能臨時(shí)使用。根實(shí)體可以復(fù)制內(nèi)部一個(gè)值對(duì)象實(shí)例副本給外部另外一個(gè)對(duì)象,副本再也與聚合無關(guān)系了。如何做到不變性根實(shí)體具有全局標(biāo)識(shí),并最終負(fù)責(zé)對(duì)不變量的檢查。CRUD中不變性約束通過數(shù)據(jù)庫查詢直接獲得的對(duì)象只有聚合的根,其他所有聚合內(nèi)對(duì)象可以通過聚合關(guān)系找到,性能上可采取懶加載防止大對(duì)象。刪除必須一次性刪除聚合邊界內(nèi)所有對(duì)象。當(dāng)在聚合邊界內(nèi)發(fā)生的任何對(duì)象修改被提交時(shí),整個(gè)聚合的所有不變量必須被滿足,也就是統(tǒng)一修改。CRUD中不變性約束通過數(shù)據(jù)庫查詢直接獲得的對(duì)象只有聚合的根聚合根和不變性聚合根和不變性采購訂單采購訂單訂單不變量約束所以采購單項(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?訂單不變量約束所以采購單項(xiàng)的金額之和不得超過采購單的最高限額并發(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ú)列出一個(gè)對(duì)象,比如Price經(jīng)常修改,就成為Price對(duì)象,鎖定Price這個(gè)小對(duì)象,無需鎖定整個(gè)PO。并發(fā)鎖粒度如果多個(gè)用戶同時(shí)修改一個(gè)PO,我們必須對(duì)這個(gè)PO實(shí)新訂單模型新訂單模型不變性的實(shí)現(xiàn)方式在生命周期中維護(hù)對(duì)象的完整性。避免模型由于管理生命周期的復(fù)雜性而陷入困境。三個(gè)模式來處理:
1.聚合(Aggregate):定義清晰的所有權(quán)和邊界使模型更加緊湊,避免出現(xiàn)盤根錯(cuò)節(jié)的對(duì)象關(guān)系網(wǎng)。聚合圈出一個(gè)范圍,在這個(gè)范圍中,對(duì)象無論在哪個(gè)生命周期,保持不變性。
2.工廠(Factory)
3.倉儲(chǔ)(Respository)生命周期之始,使用工廠和組合提供了訪問和控制模型對(duì)象的方法不變性的實(shí)現(xiàn)方式在生命周期中維護(hù)對(duì)象的完整性。避免模型由于管生命周期邊界和管理聚合圈出一個(gè)范圍如前圖中紅線,在這個(gè)范圍中,對(duì)象無論在哪個(gè)生命周期,保持不變性。也就是子對(duì)象和父對(duì)象的生命周期是一致不變的。建立聚合的模型,并且把工廠和組合加入設(shè)計(jì)中來,可以使我們系統(tǒng)地對(duì)模型對(duì)象生命周期進(jìn)行管理。生命周期之始,使用工廠和Repository提供了訪問和控制模型對(duì)象的方法。生命周期邊界和管理聚合圈出一個(gè)范圍如前圖中紅線,在這個(gè)范圍中工廠生命周期管理具有復(fù)雜的職責(zé),如果讓一個(gè)復(fù)雜對(duì)象來負(fù)責(zé)自身的創(chuàng)建工作,會(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)建方法必須是原子的,保證其不變量得到滿足。工廠生命周期管理具有復(fù)雜的職責(zé),如果讓一個(gè)復(fù)雜對(duì)象來負(fù)責(zé)自身專門工廠創(chuàng)建聚合如果聚合根需要一個(gè)工廠創(chuàng)建,又不適合充當(dāng)工廠,也就是沒有一個(gè)自然地方容納工廠,那么就創(chuàng)建一個(gè)專門的工廠對(duì)象或服務(wù)。專門工廠創(chuàng)建聚合如果聚合根需要一個(gè)工廠創(chuàng)建,又不適合充當(dāng)工廠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ù)庫能夠保存的格式。Repository由來數(shù)據(jù)庫只是對(duì)象的永久保存方式,就象我Repository和查詢不需要為通過導(dǎo)航方法能夠獲得持久對(duì)象提供查詢?cè)L問,聚合內(nèi)部對(duì)象可以通過根來導(dǎo)航。值對(duì)象無需全局查詢獲得,比較少見,值對(duì)象生命周期很短,屬于臨時(shí)對(duì)象,一般通過聚合根獲得。倉儲(chǔ)可以實(shí)現(xiàn)數(shù)據(jù)庫新增修改刪除和查詢CRUD,倉儲(chǔ)可以實(shí)現(xiàn)不同標(biāo)準(zhǔn)的各種查詢。Repository和查詢不需要為通過導(dǎo)航方法能夠獲得持久對(duì)Repository和工廠Repository和工廠Repository定義為客戶端訪問某一聚合類對(duì)象提供全局訪問接口Repository,Repository主要是在內(nèi)存中建立一系列的聚合對(duì)象。Repository提供CRUD等通用對(duì)象操作方法,把數(shù)據(jù)庫數(shù)據(jù)存儲(chǔ)插入和刪除等方法封裝起來。但是不插手事務(wù)。提供符合對(duì)象方式篩選查詢,僅為確實(shí)需要直接訪問的聚合根提供倉儲(chǔ),其他則不必。讓客戶端只關(guān)心模型,而不是數(shù)據(jù)存儲(chǔ)。存儲(chǔ)和訪問都交給Repository完成。Repository定義為客戶端訪問某一聚合類對(duì)象提供全局訪倉儲(chǔ)統(tǒng)一語言忽視持久化InfrastructureUIDomainDataAccessApplication/
Service倉儲(chǔ)統(tǒng)一語言忽視持久化InfrastructureUIDo查詢倉儲(chǔ)Specification模式查詢存在大量項(xiàng)目,但必須是圍繞實(shí)體聚合根對(duì)象的查詢,可以使用專門框架。引入Specification制定,用來讓客戶端將它希望獲得的查詢結(jié)果描述出來,也就是制定出來。輸入?yún)?shù)使用Criteria來封裝各種查詢輸入?yún)?shù),提供Criteria的查詢框架比較復(fù)雜,如Hibernate的Criteria。如果聚合中有大數(shù)據(jù),可通過懶加載lazy延遲加載,只返回一個(gè)代理,使用時(shí),再進(jìn)行加載。查詢倉儲(chǔ)Specification模式查詢存在大量項(xiàng)目,但必Specification模式業(yè)務(wù)規(guī)則不適合放入實(shí)體和值對(duì)象,規(guī)則的變化和組合會(huì)很多,包括各種算法或者條件判斷,這些會(huì)掩蓋領(lǐng)域?qū)ο蟮幕竞x,這些就放入專門對(duì)象Specification中。Specification表示業(yè)務(wù)規(guī)則,有指定要求的意思。Specification類似圍繞實(shí)體的值對(duì)象。Specification模式業(yè)務(wù)規(guī)則不適合放入實(shí)體和值對(duì)象第三種模型服務(wù)將行為放入對(duì)象才是真正對(duì)象,這樣可防止面向過程編程。但是放入不確當(dāng)行為,會(huì)破壞對(duì)象的清晰概念。有些對(duì)象側(cè)重于操作動(dòng)作行為,沒有狀態(tài),就象四色圖中MI,是一種活動(dòng)事件,這些對(duì)象應(yīng)該被標(biāo)記為服務(wù)。服務(wù)來源現(xiàn)實(shí):加油服務(wù)快遞服務(wù),服務(wù)不是一個(gè)過程化編程的概念。分應(yīng)用服務(wù)(事務(wù)安全)和領(lǐng)域服務(wù)。第三種模型服務(wù)將行為放入對(duì)象才是真正對(duì)象,這樣可防止面向過服務(wù)類型領(lǐng)域?qū)臃?wù):與業(yè)務(wù)有關(guān),需要協(xié)調(diào)多個(gè)實(shí)體完成的功能,比如資金轉(zhuǎn)賬;帖子CRUD;CashSales;下訂單等。應(yīng)用層服務(wù):與軟件設(shè)計(jì)有關(guān)的,在業(yè)務(wù)領(lǐng)域中沒有實(shí)際意義的行為活動(dòng),比如兩個(gè)業(yè)務(wù)系統(tǒng)的接口;實(shí)體和值對(duì)象由于過于細(xì)化松耦合,就無法提供一個(gè)訪問自身領(lǐng)域?qū)拥姆奖闳肟?,這時(shí)需要應(yīng)用服務(wù)。類似MVC中Controller職責(zé)?;A(chǔ)層服務(wù):比如發(fā)送Email,打印輸出等等,。服務(wù)類型領(lǐng)域?qū)臃?wù):與業(yè)務(wù)有關(guān),需要協(xié)調(diào)多個(gè)實(shí)體完成的功能,實(shí)體和行為操作的問題將業(yè)務(wù)行為都使用服務(wù)實(shí)現(xiàn),實(shí)體中除了setter/getter方法以外,就沒有任何實(shí)質(zhì)業(yè)務(wù)行為,這是貧血失血模型。如果將所有行為操作都塞入實(shí)體對(duì)象,那么實(shí)體對(duì)象變得非常龐大臃腫,失去靈活性。有很多行為操作無法被封裝進(jìn)實(shí)體,但是又涉及多個(gè)實(shí)體,呈現(xiàn)面向函數(shù)式特點(diǎn)(function)。實(shí)體和行為操作的問題將業(yè)務(wù)行為都使用服務(wù)實(shí)現(xiàn),實(shí)體中除了se職責(zé)驅(qū)動(dòng)開發(fā)面向?qū)ο笤O(shè)計(jì)方法很多,但是很少有關(guān)注行為過程。roles-a
溫馨提示
- 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ì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 2025屆北京市西城區(qū)北京第四十四中學(xué)高考沖刺模擬數(shù)學(xué)試題含解析
- 定金罰則法律風(fēng)險(xiǎn)
- 誠(chéng)實(shí)保證字萬能保證書
- 招標(biāo)文件條款的全面解讀與實(shí)踐
- 招標(biāo)文件商務(wù)評(píng)分的操作流程
- 正規(guī)訂餐服務(wù)合同樣本
- 非受雇關(guān)系非固定員工聲明書
- 技術(shù)支持服務(wù)合同樣本
- 招標(biāo)房屋租賃信息
- 招標(biāo)信息格式技巧
- 社區(qū)衛(wèi)生服務(wù)中心十四五發(fā)展規(guī)劃
- DB37T 5127-2018 裝配式建筑評(píng)價(jià)標(biāo)準(zhǔn)
- 鐵藝圍墻主要施工方法
- 帶教老師評(píng)價(jià)模板
- 大數(shù)據(jù)與政務(wù)信息共享應(yīng)用(PPT-58頁)課件
- GB∕T 2099.1-2021 家用和類似用途插頭插座 第1部分:通用要求
- 名中醫(yī)工作室跟師醫(yī)案記錄 (27)
- 中國(guó)古代文學(xué)史_袁行霈_隋唐五代文學(xué)
- ISO9000質(zhì)量管理體系培訓(xùn)資料
- 日標(biāo)法蘭尺寸表
- MSD(濕敏器件防護(hù))控制技術(shù)規(guī)范
評(píng)論
0/150
提交評(píng)論