.NET領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)—初嘗(二)
***部分:.NET領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)—初嘗
【1.3】原則
原則對于任何一項(xiàng)技術(shù)實(shí)現(xiàn)來說都是至關(guān)重要的,在設(shè)計(jì)某一個(gè)系統(tǒng)功能的時(shí)候我們講究的是設(shè)計(jì)原則: |
【單一職責(zé)原則Single Responsibility Principle、里氏替換原則Liskov Substitution Principle、依賴倒置原則Dependence Inversion Principle、接口隔離原則Interface Segregation Principle、迪米特法則Law Of Demeter、開閉原則Open Close Principle】。
在架構(gòu)設(shè)計(jì)的時(shí)候我們也講究架構(gòu)原則:
【分層原則、避免循環(huán)依賴】。
不僅僅在技術(shù)領(lǐng)域在做人做事都要講究原則,違背原則那么等待你的將是無情的懲罰。
對于DDD的設(shè)計(jì)我們也有相應(yīng)的原則需要遵守,當(dāng)然如果不遵守在前期看不出什么區(qū)別,但是到開發(fā)階段問題就會(huì)暴露出來。
我們來看兩個(gè)基本的設(shè)計(jì)原則問題。
【精簡聚合】
精簡聚合的設(shè)計(jì)原則無疑是最重要的。一些軟件工程方法論書籍經(jīng)常指導(dǎo)我們進(jìn)行UML業(yè)務(wù)建模,"在這個(gè)階段不需要考慮任何技術(shù)實(shí)現(xiàn)問題”,我按照這樣的指導(dǎo)原則進(jìn)行了UML的設(shè)計(jì)然后順利的創(chuàng)建出ER關(guān)系圖,結(jié)果發(fā)現(xiàn)那樣的數(shù)據(jù)庫結(jié)構(gòu)根本不能作為最終的項(xiàng)目開發(fā)數(shù)據(jù)庫。哪里出問題了?我反復(fù)查詢指導(dǎo)書籍后來在專業(yè)的DDD書籍上看到了一句大概這樣的話:
【“不以技術(shù)實(shí)現(xiàn)為前提的設(shè)計(jì)都是紙上談兵”】。
我想這句話很真實(shí)的描述了方法論與企業(yè)應(yīng)用之間的鴻溝,很多技術(shù)思想或者理論確實(shí)很好,但是要想用起來需要解決很多問題。DDD也避免不了這個(gè)問題,怎么避免在設(shè)計(jì)UML模型的時(shí)候不會(huì)導(dǎo)致設(shè)計(jì)過度的問題,這里我們只需要遵守【精簡聚合】原則就不會(huì)導(dǎo)致設(shè)計(jì)過度問題。
在前面的例子當(dāng)中我們設(shè)計(jì)一個(gè)完整的UML領(lǐng)域模型,但是我們并沒有對它進(jìn)行【精簡聚合】重構(gòu),所以它存在的問題就是無法進(jìn)行項(xiàng)目開發(fā)。
1.1圖
我們構(gòu)建出來的領(lǐng)域模型初步版本應(yīng)該是上圖這樣的,實(shí)體與實(shí)體之間是有強(qiáng)聯(lián)系的,聚合之間的關(guān)聯(lián)太大,導(dǎo)致牽一發(fā)而動(dòng)全身。如果按照這種關(guān)系創(chuàng)建數(shù)據(jù)庫那么數(shù)據(jù)庫之間的主\外鍵肯定很多,對數(shù)據(jù)庫的設(shè)計(jì)造成了影響。這樣的關(guān)系如果在程序中使用也會(huì)存在很多問題,我們無法進(jìn)行少數(shù)聚合的使用,當(dāng)我們使用某一個(gè)聚合的時(shí)候它會(huì)接二連三的把相關(guān)聯(lián)的聚合都給拖出來,不僅在查詢的時(shí)候妨礙而且在Factory創(chuàng)建聚合的時(shí)候也會(huì)存在無法構(gòu)造的問題,不管在對聚合Repository進(jìn)行任何操作的時(shí)候都會(huì)影響程序邏輯,所以我們需要對一個(gè)復(fù)雜的龐大的關(guān)系進(jìn)行拆分。
將紅線的部分全部斷開,聚合之間通過Id進(jìn)行關(guān)聯(lián),這樣就會(huì)變的很清晰。因?yàn)楹苌俪绦蛑袝?huì)在某一個(gè)業(yè)務(wù)邏輯點(diǎn)上需要所有的業(yè)務(wù)模型參與,這樣既方便了程序的開發(fā)也方便了數(shù)據(jù)庫的設(shè)計(jì),更方便了ORM的使用。ORM的延遲加載其實(shí)就是為了聚合之間的依賴,可以在需要的時(shí)候在去查詢需要的模型。但是這樣雖然程序可以說的過去,那么數(shù)據(jù)庫的設(shè)計(jì)就說不過去了。對于不同的ORM框架的映射原理不同,在構(gòu)造模型的時(shí)候是需要稍微的調(diào)整的,比如在EntityFramework中,它能支持的映射方案你保證你的模型能順利的映射過去,這里就不扯了后面有一個(gè)詳細(xì)的項(xiàng)目做全面實(shí)踐,到時(shí)候在具體問題具體分析。
***我們看一下分解后的類圖:
1.2圖
這樣一來一塊一塊很清晰,都能直接使用相關(guān)的核心領(lǐng)域模型,也不需要擔(dān)心ORM框架的延遲加載的問題。
【分離用例與功能接口(設(shè)計(jì)模式的使用之地)】
分離用例與功能接口其實(shí)也是初次接觸DDD的朋友都會(huì)犯的職業(yè)病,因?yàn)槲覀兌际煜っ嫦驅(qū)ο笤O(shè)計(jì)。在進(jìn)行UML建模的時(shí)候我們都非常喜歡抽象,會(huì)很清楚的把具有泛化關(guān)系的用繼承來表示,比如【用戶類型】,不同的用戶具有不同的行為權(quán)限,在初步設(shè)計(jì)的時(shí)候我們一般都會(huì)建立關(guān)于用戶的一個(gè)繼承關(guān)系來表達(dá)泛化的業(yè)務(wù)模型。但是在編碼階段會(huì)發(fā)現(xiàn)很明顯的問題就是我們把關(guān)于Repository的行為包含到了發(fā)起用例的用戶聚合當(dāng)中去了,這樣說可能有點(diǎn)抽象。我們還是用例子來分析;
1.3圖
上圖中我將【Admin】和【配送】用例分開了,想表達(dá)是不能將關(guān)于配送的行為放在【Admin】中。在我們對有關(guān)權(quán)限進(jìn)行建模的時(shí)候經(jīng)常會(huì)潛意識(shí)的將各自的行為放在了各自的角色當(dāng)中,如果后期存在多角色共享行為的就將寫在抽象的類中使用虛方法向下傳遞。問題就出在關(guān)于角色行為里,我們知道如果有行為那么就有可能在該行為里面執(zhí)行有關(guān)其他聚合的IRepository操作,這樣一來將會(huì)把領(lǐng)域模型搞的很亂,無法垂直分析。
1.4圖
DDD講究領(lǐng)域驅(qū)動(dòng),在我們看來【Dispatching】、【CheckOrders】都是繼承管理員角色,管理員屬于后臺(tái)管理人員,意味著企業(yè)的員工。對消費(fèi)者來說他們就是管理人員。同樣消費(fèi)者也會(huì)存在相同的情況,消費(fèi)者可能存在很多種類型,有VIP系列的(VIP1\VIP2\VIP3…),有鉆石會(huì)員之類的。如果這樣設(shè)計(jì)的話并不能說是錯(cuò)的,這也完全符合DDD的思想要求,但是實(shí)際情況下卻是不理想的。
這里就用到了我們長期使用的設(shè)計(jì)模式了,我們可以通過設(shè)計(jì)模式中的很多中模式來將用戶與行為分離開來,再將使用的規(guī)則條件抽象出來就完全獨(dú)立了用戶,用戶在使用的時(shí)候不會(huì)存在直接的行為歸屬,但是事實(shí)上他們確實(shí)是有行為。
1.5圖
用專業(yè)的DDD術(shù)語講“規(guī)約模式”,將業(yè)務(wù)規(guī)則抽取出來對象化,甚至到***都可以進(jìn)行規(guī)則的配置化。最讓我們興奮的是,我們苦心學(xué)習(xí)的設(shè)計(jì)模式終于可以在系統(tǒng)設(shè)計(jì)中大面積的使用了,難道不是一件很驚喜的事情嗎!
#p#
【1.4】工具、框架
任何一種架構(gòu)都是需要框架、工具的支撐才能變的***。
當(dāng)我們在某種架構(gòu)下進(jìn)行開發(fā)的時(shí)候,我們必須需要很多工具、框架的支撐才能讓開發(fā)工作變的很便捷,這也和【敏捷開發(fā)】的思想一樣。在傳統(tǒng)的三層架構(gòu)下開發(fā)我們都需要 "對象映射"、"AOP\IOC” 等等類似的輔助框架,目的是為了架構(gòu)前行的可能性。在DDD中我們也需要很多目前還沒有出現(xiàn)的很多工具、框架,在.NET平臺(tái)中目前來看只有EntityFramework框架算是為了DDD做了很多工作,如果我們的領(lǐng)域模型無法與數(shù)據(jù)庫進(jìn)行映射,那么領(lǐng)域模型開發(fā)所要付出的代價(jià)將是很大。
在設(shè)計(jì)階段我們?nèi)狈σ粋€(gè)面向特定領(lǐng)域的建模工具,這種工具與UML不同,UML太技術(shù)化通用化。DDD中經(jīng)常會(huì)提起【領(lǐng)域?qū)<摇恳唤?,他?**有權(quán)威性的領(lǐng)域領(lǐng)頭人,我們所創(chuàng)建出來的UML他們未必能看得懂,通過技術(shù)人員技術(shù)化之后形成UML其實(shí)已經(jīng)變味,【領(lǐng)域?qū)<摇渴嵌嵌臒o法做到肯定的保證。如果能把領(lǐng)域模型語言化,那么這個(gè)將是一大成就?!绢I(lǐng)域?qū)<摇繉︻I(lǐng)域中的任何事物、人物、環(huán)節(jié)都很熟悉,但是他無法表達(dá)清楚自己的想法,如果能有一個(gè)工具輔助他的設(shè)計(jì),該工具能將設(shè)計(jì)后的模型進(jìn)行平滑等價(jià)的技術(shù)化變成代碼模型或者數(shù)據(jù)庫模型,這一條鴻溝如果能跨越那么對行業(yè)來說具有很大影響力。
1.8圖
如果我們能等價(jià)的將上圖中的真實(shí)模型進(jìn)行技術(shù)化,那么真的每個(gè)人都會(huì)喜歡需求分析、分析設(shè)計(jì)。
既然是模型驅(qū)動(dòng)設(shè)計(jì),我們在給用戶分析類似這樣一套系統(tǒng)的時(shí)候,前提是我們已經(jīng)對里面的所有細(xì)節(jié)進(jìn)行了抽象封裝,每一個(gè)過程都是可以拆分的,***能合并在一起形成一個(gè)整體的業(yè)務(wù)模型。當(dāng)然這里只是一種技術(shù)展望,也是我們奮斗和理想的目標(biāo)。
推薦一本***Martin Fowler的書:《領(lǐng)域特定語言》
【1.5】過程
DDD不是一種純技術(shù)實(shí)現(xiàn),而是一整套開發(fā)思想,它貫穿軟件開發(fā)的所有生命周期。從我們開發(fā)接觸領(lǐng)域,對領(lǐng)域知識(shí)進(jìn)行深入的消化,這些都是DDD所強(qiáng)調(diào)的。那么在我們?nèi)粘i_發(fā)過程中,我們該如何處理這些過程,需求不會(huì)再像以前那樣是一份雜亂無章的草稿,而是一個(gè)內(nèi)容豐富的領(lǐng)域模型草圖。這樣的要求對團(tuán)隊(duì)對部門甚至對公司來說都是一個(gè)提升,要想做到完全的DDD過程其實(shí)很難。
公司領(lǐng)導(dǎo)如何看待這樣的開發(fā)方式,我們多數(shù)人都是在一些非專業(yè)研發(fā)類的公司工作,領(lǐng)導(dǎo)希望能盡早的看到東西,這很矛盾,需要好的東西但是不按照好的東西做法來做。如果有幸能有一個(gè)面向DDD、敏捷、XP的研發(fā)團(tuán)隊(duì)工作,那么可以視項(xiàng)目為一件終身的藝術(shù)品。[王清培版權(quán)所有,轉(zhuǎn)載請給出署名]
這兩篇文章主要是一些本人對DDD的感悟,分享給大家。
后面一篇文章將會(huì)詳細(xì)的使用一個(gè)DDD架構(gòu)的小系統(tǒng)作為案例給大家分享,里面將包括從需求的分析建模、設(shè)計(jì)模式的使用、數(shù)據(jù)庫映射、EntityFramework的使用等等,可以作為真實(shí)項(xiàng)目開發(fā)的依據(jù)。
原文鏈接:http://www.cnblogs.com/wangiqngpei557/archive/2013/04/10/3012590.html