1. 什么是領(lǐng)域(Domain)
我們所做的軟件系統(tǒng)的目的都是來(lái)解決一系列問(wèn)題诡宗,例如做一個(gè)電商系統(tǒng)來(lái)在線(xiàn)銷(xiāo)售自己企業(yè)的產(chǎn)品职烧;做一個(gè)灰度發(fā)布平臺(tái)來(lái)提升服務(wù)的質(zhì)量和穩(wěn)定性厂画。任何一個(gè)系統(tǒng)都會(huì)屬于某個(gè)特定的領(lǐng)域认轨,例如:
- 論壇是一個(gè)領(lǐng)域:要做一個(gè)論壇嫁佳,那這個(gè)論壇的核心業(yè)務(wù)是確定的:比如用戶(hù)發(fā)帖、回帖等核心基本功能弧可;
- 電商系統(tǒng)是一個(gè)領(lǐng)域:只要是電商領(lǐng)域的系統(tǒng)蔑匣,那核心業(yè)務(wù)就是:商品瀏覽、購(gòu)物車(chē)棕诵、下單蝙砌、減庫(kù)存狮含、付款交易等核心環(huán)節(jié);
同一個(gè)領(lǐng)域的系統(tǒng)都具有相同的核心業(yè)務(wù)康二,因?yàn)樗麄円鉀Q的問(wèn)題的本質(zhì)是類(lèi)似的贱纠。因此可以推斷:一個(gè)領(lǐng)域本質(zhì)上可以理解為一個(gè) 問(wèn)題域 复哆。只要確定了系統(tǒng)所屬的領(lǐng)域猬错,那么這個(gè)系統(tǒng)的核心業(yè)務(wù)饥漫,即要解決的關(guān)鍵問(wèn)題就基本確定了。通常我們說(shuō)妹孙,要成為一個(gè)領(lǐng)域的專(zhuān)家座硕,必須要在這個(gè)領(lǐng)域深入研究很多年才行,只有這樣才會(huì)遇到非常多的該領(lǐng)域的問(wèn)題涕蜂,積累了豐富的經(jīng)驗(yàn)。
2.界限上下文(Bounded Context)
通常來(lái)說(shuō)映琳,一個(gè)領(lǐng)域有且只有一個(gè)核心問(wèn)題机隙,我們稱(chēng)之為該領(lǐng)域的『核心子域』。在核心子域萨西、通用子域有鹿、支撐子域梳理的同時(shí),會(huì)定義出子域中的『限界上下文』及其關(guān)系谎脯,用它來(lái) 闡述子域之間的關(guān)系 葱跋。界限上下文可以簡(jiǎn)單理解成一個(gè)子系統(tǒng)或組件模塊。
例如:下圖是對(duì)酒店管理的子域和界限上下文的梳理:3. 領(lǐng)域模型(Domain Model)
領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)(Domain-Driven Design)分為兩個(gè)階段:
- 以一種領(lǐng)域?qū)<以此蟆⒃O(shè)計(jì)人員娱俺、開(kāi)發(fā)人員都能理解的通用語(yǔ)言作為相互交流的工具,在交流的過(guò)程中發(fā)現(xiàn)領(lǐng)域概念废麻,然后將這些概念設(shè)計(jì)成一個(gè)領(lǐng)域模型荠卷;
- 由領(lǐng)域模型驅(qū)動(dòng)軟件設(shè)計(jì),用代碼來(lái)實(shí)現(xiàn)該領(lǐng)域模型烛愧;
由此可見(jiàn)油宜,領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)的核心是建立正確的領(lǐng)域模型掂碱。領(lǐng)域模型具有以下特點(diǎn):
- 對(duì)具有某個(gè)邊界的領(lǐng)域的一個(gè)抽象,反映了領(lǐng)域內(nèi)用戶(hù) 業(yè)務(wù)需求的本質(zhì) 慎冤。它屬于『解決問(wèn)題空間』疼燥。領(lǐng)域模型是有邊界的,只反應(yīng)了我們?cè)陬I(lǐng)域內(nèi)所關(guān)注的部分蚁堤,包括 實(shí)體概念(如:貨物醉者,書(shū)本,應(yīng)聘記錄违寿,地址等)湃交,以及 過(guò)程概念(如:資金轉(zhuǎn)賬等);
- 提高軟件的 可維護(hù)性藤巢,業(yè)務(wù)可理解性以及可重用性搞莺。領(lǐng)域模型確保了我們的軟件的業(yè)務(wù)邏輯都在一個(gè)模型中,幫助開(kāi)發(fā)人員相對(duì)平滑地將領(lǐng)域知識(shí)轉(zhuǎn)化為軟件構(gòu)造掂咒;
- 貫穿軟件 分析才沧、設(shè)計(jì)、開(kāi)發(fā) 的整個(gè)過(guò)程绍刮。領(lǐng)域?qū)<椅略病⒃O(shè)計(jì)人員、開(kāi)發(fā)人員面向同一個(gè)模型進(jìn)行交流孩革,彼此共享知識(shí)與信息岁歉,所以可以防止需求走樣,讓軟件開(kāi)發(fā)人員做出來(lái)的軟件真正滿(mǎn)足需求膝蜈;要建立正確的領(lǐng)域模型并不簡(jiǎn)單锅移,需要領(lǐng)域?qū)<摇⒃O(shè)計(jì)饱搏、開(kāi)發(fā)人員積極溝通共同努力非剃,然后才能使大家對(duì)領(lǐng)域的認(rèn)識(shí)不斷深入,從而不斷細(xì)化和完善領(lǐng)域模型推沸;
- 為了讓領(lǐng)域模型看的見(jiàn)备绽,使用的常用表達(dá)領(lǐng)域模型的方式:圖、代碼或文字鬓催;
- 重要性:領(lǐng)域模型是整個(gè)軟件的核心肺素,是軟件中最有價(jià)值和最具競(jìng)爭(zhēng)力的部分;設(shè)計(jì)足夠精良且符合業(yè)務(wù)需求的領(lǐng)域模型能夠更快速的響應(yīng)需求變化宇驾;
4. 領(lǐng)域通用語(yǔ)言
由軟件專(zhuān)家和領(lǐng)域?qū)<液献鏖_(kāi)發(fā)一個(gè)領(lǐng)域的模型是有必要的压怠。開(kāi)發(fā)過(guò)程中, 開(kāi)發(fā)人員以類(lèi)飞苇、算法菌瘫、設(shè)計(jì)模式蜗顽、架構(gòu)等進(jìn)行思考與交流。但領(lǐng)域?qū)<覍?duì)此一無(wú)所知雨让,他們對(duì)技術(shù)上的術(shù)語(yǔ)沒(méi)有太多概念雇盖,只了解特有的領(lǐng)域?qū)I(yè)技能,例如:在空中交通監(jiān)控樣例中栖忠,領(lǐng)域?qū)<抑里w機(jī)崔挖、路線(xiàn)、海拔庵寞、經(jīng)度狸相、緯度,他們有自己的術(shù)語(yǔ)來(lái)討論這些事情捐川。軟件專(zhuān)家和領(lǐng)域?qū)<医涣鬟^(guò)程中脓鹃,需要做翻譯才能讓對(duì)方理解這些概念。
領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)的一個(gè)核心原則是使用一種基于模型的語(yǔ)言古沥。使用模型作為語(yǔ)言的核心骨架瘸右,要求團(tuán)隊(duì)在進(jìn)行所有的交流是都使用一致的語(yǔ)言,在代碼中也是這樣岩齿,這種語(yǔ)言被稱(chēng)為『通用語(yǔ)言』太颤。
5.建模思考的問(wèn)題:用戶(hù)需求
『用戶(hù)需求』不能等同于『用戶(hù)』,捕捉『用戶(hù)心中的模型』也不能等同于『以用戶(hù)為核心設(shè)計(jì)領(lǐng)域模型』盹沈。設(shè)計(jì)領(lǐng)域模型時(shí)不能以用戶(hù)為出發(fā)點(diǎn)去思考問(wèn)題龄章,不能老想著用戶(hù)會(huì)對(duì)系統(tǒng)做什么;而應(yīng)該從一個(gè)客觀(guān)的角度乞封,根據(jù)用戶(hù)需求挖掘出領(lǐng)域內(nèi)的相關(guān)事物瓦堵,思考這些事物的本質(zhì)關(guān)聯(lián)及其變化規(guī)律作為出發(fā)點(diǎn)去思考問(wèn)題。
領(lǐng)域模型是 排除了人之外的客觀(guān)世界模型 歌亲,包含了人所扮演的參與者角色。但是一般情況下不要讓參與者角色在領(lǐng)域模型中占據(jù)主要位置澜驮,否則各個(gè)系統(tǒng)的領(lǐng)域模型將變得沒(méi)有差別陷揪,因?yàn)檐浖到y(tǒng)就是一個(gè)人機(jī)交互的系統(tǒng),都是以人為主的活動(dòng)記錄或跟蹤杂穷。例如:
- 論壇中如果以人為主導(dǎo)悍缠,那么領(lǐng)域模型就是:人發(fā)帖,人回帖耐量,人結(jié)貼飞蚓,等等;
- 貨物托運(yùn)系統(tǒng)中如果以人為主導(dǎo)廊蜒,就變成了:托運(yùn)人托運(yùn)貨物趴拧,收貨人收貨物溅漾,付款人付款,等等著榴;
以一個(gè)貨物運(yùn)輸系統(tǒng)為例子簡(jiǎn)單說(shuō)明一下添履。在用戶(hù)需求相對(duì)明朗之后,這樣描述領(lǐng)域模型:
- 一個(gè)Cargo(貨物)涉及多個(gè)Customer(客戶(hù)脑又,如托運(yùn)人暮胧、收貨人、付款人)问麸,每個(gè)Customer承擔(dān)不同的角色往衷;
- Cargo的運(yùn)送目標(biāo)已指定,即Cargo有一個(gè)運(yùn)送目標(biāo)严卖;
- 由一系列滿(mǎn)足Specification(規(guī)格)的Carrier Movement(運(yùn)輸動(dòng)作)來(lái)完成運(yùn)輸目標(biāo)席舍;
以上描述沒(méi)有從用戶(hù)的角度去描述領(lǐng)域模型,而是以領(lǐng)域內(nèi)的相關(guān)事物為出發(fā)點(diǎn)妄田,考慮這些事物的本質(zhì)關(guān)聯(lián)及其變化規(guī)律的:
- 以貨物為中心俺亮,把客戶(hù)看成是貨物在某個(gè)場(chǎng)景中可能會(huì)涉及到的關(guān)聯(lián)角色,如貨物會(huì)涉及到托運(yùn)人疟呐、收貨人脚曾、付款人;
- 貨物有一個(gè)確定的目標(biāo)启具,貨物會(huì)經(jīng)過(guò)一系列的運(yùn)輸動(dòng)作到達(dá)目的地本讥。
以用戶(hù)為中心來(lái)思考領(lǐng)域模型的思維只是停留在需求的表面,而沒(méi)有挖掘出真正的需求的本質(zhì)鲁冯。領(lǐng)域建模時(shí)需要努力挖掘用戶(hù)需求的本質(zhì)拷沸,這樣才能真正實(shí)現(xiàn)用戶(hù)需求。
6. 經(jīng)典分層架構(gòu)
用戶(hù)界面/展示層:1)請(qǐng)求應(yīng)用層獲取用戶(hù)所需的展示數(shù)據(jù)薯演;2)發(fā)送命令給應(yīng)用層執(zhí)行用戶(hù)的命令
應(yīng)用層:薄薄的一層撞芍,定義軟件要完成的任務(wù)。對(duì)外為展示層提供各種應(yīng)用功能跨扮,對(duì)內(nèi)調(diào)用領(lǐng)域?qū)樱I(lǐng)域?qū)ο蠡蝾I(lǐng)域服務(wù))完成各種業(yè)務(wù)邏輯序无。應(yīng)用層不包含業(yè)務(wù)邏輯
領(lǐng)域?qū)樱罕磉_(dá)業(yè)務(wù)概念、業(yè)務(wù)狀態(tài)信息及業(yè)務(wù)規(guī)則衡创,是業(yè)務(wù)軟件的核心
基礎(chǔ)設(shè)施層:為其他層提供通用的技術(shù)能力帝嗡,提供了層間通信;為領(lǐng)域?qū)犹峁┏志没瘷C(jī)制璃氢。
7. 使用的模式
7.1. 總覽圖
7.2. 關(guān)聯(lián)的設(shè)計(jì)
關(guān)聯(lián)在領(lǐng)域建模的過(guò)程中非常重要哟玷,關(guān)聯(lián)的設(shè)計(jì)可以遵循如下的一些原則:
- 關(guān)聯(lián)盡量少。對(duì)象之間復(fù)雜的關(guān)聯(lián)容易形成對(duì)象的關(guān)系網(wǎng)一也,對(duì)于理解和維護(hù)單個(gè)對(duì)象很不利巢寡,同時(shí)也很難劃分對(duì)象與對(duì)象之間的邊界喉脖;另外,減少關(guān)聯(lián)有助于簡(jiǎn)化對(duì)象之間的遍歷讼渊;
- 關(guān)聯(lián)盡量保持 單向 的關(guān)聯(lián)动看;
- 在建立關(guān)聯(lián)時(shí),需要挖掘是否存在關(guān)聯(lián)的 限制條件 爪幻。如果存在菱皆,那么最好把限制條件加到關(guān)聯(lián)上,往往這樣的限制條件能將關(guān)聯(lián)化繁為簡(jiǎn)挨稿,即將多對(duì)多簡(jiǎn)化為1對(duì)多仇轻,或?qū)?對(duì)多簡(jiǎn)化為1對(duì)1;
7.3. 實(shí)體(Entity)
實(shí)體就是領(lǐng)域中需要 唯一標(biāo)識(shí) 的領(lǐng)域概念奶甘。因?yàn)槲覀冇袝r(shí)需要區(qū)分是哪個(gè)實(shí)體:有兩個(gè)實(shí)體篷店,如果唯一標(biāo)識(shí)不一樣,那么即便實(shí)體的其他所有屬性都一樣臭家,也認(rèn)為他們是兩個(gè)不同的實(shí)體疲陕。
不應(yīng)該給實(shí)體定義太多的屬性或行為,而應(yīng)該尋找關(guān)聯(lián)钉赁,將屬性或行為轉(zhuǎn)移到其他關(guān)聯(lián)的實(shí)體或值對(duì)象上蹄殃。比如:Customer 實(shí)體,有一些地址信息你踩,由于地址信息是一個(gè)完整的有業(yè)務(wù)含義的概念诅岩,所以我們可以定義一個(gè) Address 對(duì)象,然后把 Customer 的地址相關(guān)的信息轉(zhuǎn)移到 Address 對(duì)象上带膜。如果沒(méi)有 Address 對(duì)象吩谦,而把這些地址信息直接放在 Customer 對(duì)象上,然后對(duì)于一些其他的類(lèi)似Address的信息也都直接放在Customer 上膝藕,會(huì)導(dǎo)致 Customer 對(duì)象很混亂式廷,結(jié)構(gòu)不清晰,最終導(dǎo)致它難以維護(hù)和理解芭挽。
7.4. 值對(duì)象(Value Object)
并不是每一個(gè)事物都必須有一個(gè)唯一標(biāo)識(shí)滑废。就以上面的地址對(duì)象 Address 為例,如果兩個(gè) Customer 的地址信息是一樣的览绿,我們就會(huì)認(rèn)為這兩個(gè) Customer 的地址是同一個(gè)。用程序的方式來(lái)表達(dá)就是:如果兩個(gè)對(duì)象所有屬性的值都相同穗慕,我們會(huì)認(rèn)為它們是同一個(gè)對(duì)象饿敲,那么就可以把這種對(duì)象設(shè)計(jì)為值對(duì)象。
值對(duì)象的特征:
- 值對(duì)象 沒(méi)有唯一標(biāo)識(shí) 逛绵,這是它和實(shí)體的最大不同怀各。值對(duì)象在判斷是否是同一個(gè)對(duì)象時(shí)是通過(guò)它們的所有屬性是否相同倔韭,如果相同則認(rèn)為是同一個(gè)值對(duì)象。在區(qū)分是否是同一個(gè)實(shí)體時(shí)瓢对,只看實(shí)體的唯一標(biāo)識(shí)是否相同寿酌,而不管實(shí)體的屬性是否相同。
- 值對(duì)象是 不可變 的硕蛹,即所有屬性都是只讀的醇疼,所以可以被安全的共享。
應(yīng)該給值對(duì)象設(shè)計(jì)的盡量簡(jiǎn)單法焰,不要讓它引用很多其他的對(duì)象秧荆。值對(duì)象只是一個(gè)值,類(lèi)似(int a = 3)中的『3』埃仪,只不過(guò)是用對(duì)象來(lái)表示乙濒。值對(duì)象雖然是只讀的,是一個(gè)完整的不可分割的整體卵蛉,但是可以被整個(gè)替換掉:類(lèi)似(a = 4)把a(bǔ)的值由『3』替換為為『4』颁股,當(dāng)修改 Customer 的 Address 對(duì)象引用時(shí),不是通過(guò) Customer.Address.Street 這樣的方式來(lái)修改屬性傻丝,可以這樣做:Customer.Address = new Address(…)
7.5. 領(lǐng)域服務(wù)(Domain Service)
領(lǐng)域中的一些概念不太適合建模為對(duì)象(實(shí)體對(duì)象或值對(duì)象)甘有,因?yàn)樗鼈儽举|(zhì)上就是一些操作、動(dòng)作桑滩,而不是事物梧疲。這些操作往往需要 協(xié)調(diào)多個(gè)領(lǐng)域?qū)ο?/strong>。如果強(qiáng)行將這些操作職責(zé)分配給任何一個(gè)對(duì)象运准,則被分配的對(duì)象就是承擔(dān)一些不該承擔(dān)的職責(zé)幌氮,從而會(huì)導(dǎo)致對(duì)象的職責(zé)不明確很混亂。DDD認(rèn)為領(lǐng)域服務(wù)模式是一個(gè)很自然的范式用來(lái)對(duì)應(yīng)這種跨多個(gè)對(duì)象的操作胁澳。一般的領(lǐng)域?qū)ο蠖际怯袪顟B(tài)和行為的该互,而領(lǐng)域服務(wù)沒(méi)有狀態(tài)只有行為。
領(lǐng)域服務(wù)還有一個(gè)很重要的功能就是可以避免領(lǐng)域邏輯泄露到應(yīng)用層韭畸。因?yàn)槿绻麤](méi)有領(lǐng)域服務(wù)宇智,那么應(yīng)用層會(huì)直接調(diào)用領(lǐng)域?qū)ο笸瓿杀驹撌菍儆陬I(lǐng)域服務(wù)該做的操作,需要了解每個(gè)領(lǐng)域?qū)ο蟮臉I(yè)務(wù)功能胰丁,以及它可能會(huì)與哪些其他領(lǐng)域?qū)ο蠼换サ纫幌盗蓄I(lǐng)域知識(shí)随橘。這樣一來(lái),領(lǐng)域?qū)涌赡軙?huì)把一部分領(lǐng)域知識(shí)泄露到應(yīng)用層锦庸。對(duì)于應(yīng)用層來(lái)說(shuō)机蔗,通過(guò)調(diào)用領(lǐng)域服務(wù)提供的簡(jiǎn)單易懂且意義明確的接口肯定也要比直接操縱領(lǐng)域?qū)ο笕菀椎亩唷?/p>
說(shuō)到領(lǐng)域服務(wù),還需要提一下軟件中一般有三種服務(wù):應(yīng)用層服務(wù)、領(lǐng)域服務(wù)萝嘁、基礎(chǔ)服務(wù)梆掸。從以下的例子中可以清晰的看出每種服務(wù)的職責(zé):
應(yīng)用層服務(wù)
- 獲取輸入(如一個(gè)XML請(qǐng)求)
- 發(fā)送消息給領(lǐng)域?qū)臃?wù),要求其實(shí)現(xiàn)轉(zhuǎn)帳的業(yè)務(wù)邏輯
- 領(lǐng)域?qū)臃?wù)處理成功牙言,則調(diào)用基礎(chǔ)層服務(wù)發(fā)送Email通知
領(lǐng)域?qū)臃?wù)
- 獲取源帳號(hào)和目標(biāo)帳號(hào)酸钦,分別通知源帳號(hào)和目標(biāo)帳號(hào)進(jìn)行扣除金額和增加金額的操作
- 提供返回結(jié)果給應(yīng)用層
基礎(chǔ)層服務(wù)
- 按照應(yīng)用層的請(qǐng)求,發(fā)送Email通知
7.6. 聚合及聚合根(Aggregate咱枉,Aggregate Root)
聚合定義了一組具有 內(nèi)聚關(guān)系 的相關(guān)對(duì)象的集合卑硫,以及對(duì)象之間清晰的所屬關(guān)系和邊界,避免了錯(cuò)綜復(fù)雜的難以維護(hù)的對(duì)象關(guān)系網(wǎng)的形成庞钢。我們把聚合看作是一個(gè)修改數(shù)據(jù)的單元拔恰。
聚合有以下特點(diǎn):
- 每個(gè)聚合有一個(gè)根和一個(gè)邊界:根是聚合內(nèi)的某個(gè)實(shí)體;邊界定義了一個(gè)聚合內(nèi)部有哪些實(shí)體或值對(duì)象基括;
- 聚合根是外部可以保持對(duì)聚合引用的唯一元素颜懊,負(fù)責(zé)與外部其他對(duì)象打交道并維護(hù)自己內(nèi)部的業(yè)務(wù)規(guī)則。聚合內(nèi)部的對(duì)象之間可以相互引用风皿,但是聚合外部如果要訪(fǎng)問(wèn)聚合內(nèi)部的對(duì)象時(shí)河爹,必須通過(guò)聚合根開(kāi)始導(dǎo)航,絕對(duì)不能繞過(guò)聚合根直接訪(fǎng)問(wèn)聚合內(nèi)的對(duì)象桐款;
- 聚合內(nèi)除根以外的其他實(shí)體的唯一標(biāo)識(shí)都是本地標(biāo)識(shí)咸这,也就是只要在聚合內(nèi)部保持唯一即可,因?yàn)樗鼈兛偸菑膶儆谶@個(gè)聚合的魔眨;
- 聚合內(nèi)部的對(duì)象可以保持對(duì)其他聚合根的引用媳维;
- 刪除一個(gè)聚合根時(shí)必須同時(shí)刪除該聚合內(nèi)的所有相關(guān)對(duì)象,因?yàn)樗麄兌纪瑢儆谝粋€(gè)聚合遏暴,是一個(gè)完整的概念侄刽;
- 基于聚合的以上概念,我們可以推論出從數(shù)據(jù)庫(kù)查詢(xún)時(shí)的單元也是以聚合為一個(gè)單元朋凉,不能直接查詢(xún)聚合內(nèi)部的某個(gè)非根的對(duì)象州丹;
如何識(shí)別聚合:
可以從業(yè)務(wù)的角度分析哪些對(duì)象它們的關(guān)系是內(nèi)聚的,可看成一個(gè)整體來(lái)考慮的杂彭,然后這些對(duì)象可以放在一個(gè)聚合內(nèi)墓毒。關(guān)系內(nèi)聚是指這些對(duì)象之間必須保持一個(gè)固定規(guī)則,固定規(guī)則是指在數(shù)據(jù)變化時(shí)必須保持不變的一致性規(guī)則亲怠。當(dāng)修改一個(gè)聚合時(shí)所计,必須在 事務(wù)級(jí)別
確保整個(gè)聚合內(nèi)的所有對(duì)象滿(mǎn)足這個(gè)固定規(guī)則。聚合盡量不要太大团秽,否則可能帶來(lái)一定的性能問(wèn)題主胧。通常在大部分領(lǐng)域模型中钾腺,有70%的聚合通常只有一個(gè)實(shí)體,即聚合根讥裤,該實(shí)體內(nèi)部沒(méi)有包含其他實(shí)體,只包含一些值對(duì)象姻报;另外30%的聚合中己英,基本上也只包含兩到三個(gè)實(shí)體。
如何識(shí)別聚合根:
如果一個(gè)聚合只有一個(gè)實(shí)體吴旋,那么這個(gè)實(shí)體就是聚合根损肛;如果有多個(gè)實(shí)體,那么我們可以思考聚合內(nèi)哪個(gè)對(duì)象有獨(dú)立存在的意義并且可以和外部直接進(jìn)行交互荣瑟。
7.7. 工廠(chǎng)(Factory)
DDD中的工廠(chǎng)也是一種體現(xiàn) 封裝思想 的模式治拿。DDD中引入工廠(chǎng)模式的原因是:有時(shí)創(chuàng)建一個(gè)領(lǐng)域?qū)ο笫且患容^復(fù)雜的事情,不僅僅是簡(jiǎn)單的new操作笆焰。工廠(chǎng)是用來(lái)封裝創(chuàng)建一個(gè)復(fù)雜對(duì)象尤其是聚合時(shí)所需的知識(shí)劫谅,將創(chuàng)建對(duì)象的細(xì)節(jié)(如何實(shí)例化對(duì)象,然后做哪些初始化操作)隱藏起來(lái)嚷掠。
客戶(hù)傳遞給工廠(chǎng)一些簡(jiǎn)單的參數(shù)捏检,如果參數(shù)符合業(yè)務(wù)規(guī)則,則工廠(chǎng)可以在內(nèi)部創(chuàng)建出一個(gè)相應(yīng)的領(lǐng)域?qū)ο蠓祷亟o客戶(hù)不皆;但是如果參數(shù)無(wú)效贯城,應(yīng)該拋出異常,以確保不會(huì)創(chuàng)建出一個(gè)錯(cuò)誤的對(duì)象霹娄。當(dāng)然也并不總是需要通過(guò)工廠(chǎng)來(lái)創(chuàng)建對(duì)象能犯,事實(shí)上大部分情況下領(lǐng)域?qū)ο蟮膭?chuàng)建都不會(huì)太復(fù)雜,只需要簡(jiǎn)單的使用構(gòu)造函數(shù)就可以了犬耻。隱藏創(chuàng)建對(duì)象的好處:可以不讓領(lǐng)域?qū)拥臉I(yè)務(wù)邏輯泄露到應(yīng)用層踩晶,同時(shí)也減輕了應(yīng)用層的負(fù)擔(dān),它只需要簡(jiǎn)單的調(diào)用領(lǐng)域工廠(chǎng)創(chuàng)建出期望的對(duì)象即可香追。
7.8. 倉(cāng)儲(chǔ)(Repository)
倉(cāng)儲(chǔ)被設(shè)計(jì)出來(lái)的原因:領(lǐng)域模型中的對(duì)象自從創(chuàng)建后不會(huì)一直留在內(nèi)存活動(dòng)合瓢,當(dāng)它不活動(dòng)時(shí)會(huì)被持久化到DB中,當(dāng)需要的時(shí)候會(huì)重建該對(duì)象透典。所以晴楔,重建對(duì)象是一個(gè)和DB打交道的過(guò)程,需要提供一種機(jī)制峭咒,提供類(lèi)似集合的接口來(lái)幫助我們 管理對(duì)象税弃。
倉(cāng)儲(chǔ)里存放的對(duì)象一定是聚合,因?yàn)橹疤岬降念I(lǐng)域模型是以聚合的概念來(lái)劃分邊界的凑队。我們 只對(duì)聚合設(shè)計(jì)倉(cāng)儲(chǔ) 则果,把整個(gè)聚合看成一個(gè)整體幔翰,要么一起取出來(lái),要么一起被刪除西壮,不會(huì)單獨(dú)對(duì)某個(gè)聚合內(nèi)的子對(duì)象進(jìn)行單獨(dú)查詢(xún)和更新遗增。倉(cāng)儲(chǔ)還有一個(gè)重要的特征就是分為倉(cāng)儲(chǔ)定義部分和倉(cāng)儲(chǔ)實(shí)現(xiàn)部分,在領(lǐng)域模型中定義倉(cāng)儲(chǔ)的接口款青,而在基礎(chǔ)設(shè)施層實(shí)現(xiàn)具體的倉(cāng)儲(chǔ)做修。
8.設(shè)計(jì)領(lǐng)域模型時(shí)一般步驟
- 根據(jù)需求建立初步的領(lǐng)域模型,識(shí)別明顯的領(lǐng)域概念和之間的關(guān)聯(lián)(1:1, 1:n的關(guān)系)抡草,用文字精確沒(méi)有歧義的描述出每個(gè)領(lǐng)域概念的含義饰及;
- 分析主要的軟件功能,識(shí)別主要的應(yīng)用層的類(lèi)康震,這樣有助于及早發(fā)現(xiàn)哪些是應(yīng)用層的職責(zé)燎含,哪些是領(lǐng)域?qū)拥穆氊?zé);
- 進(jìn)一步分析領(lǐng)域模型腿短,識(shí)別出實(shí)體屏箍、值對(duì)象、領(lǐng)域服務(wù)橘忱;
- 分析關(guān)聯(lián)铣除,通過(guò)對(duì)業(yè)務(wù)的深入分析和軟件設(shè)計(jì)原則及性能方面的權(quán)衡,明確關(guān)聯(lián)的方向鹦付,去掉一些不需要的關(guān)聯(lián)尚粘;
- 找出聚合邊界及聚合根,在分析過(guò)程中會(huì)出現(xiàn)難以清洗判斷的選擇問(wèn)題敲长,這就依賴(lài)平時(shí)分析經(jīng)驗(yàn)的積累了郎嫁;
- 為聚合根配置倉(cāng)儲(chǔ),一般情況下為一個(gè)聚合分配一個(gè)倉(cāng)儲(chǔ)祈噪,此時(shí)設(shè)計(jì)好倉(cāng)儲(chǔ)的接口即可泽铛;
- 遍歷所有場(chǎng)景,確定設(shè)計(jì)的領(lǐng)域模型能有效解決業(yè)務(wù)需求辑鲤;
- 考慮如何創(chuàng)建實(shí)體和值對(duì)象盔腔,是通過(guò)工廠(chǎng)還是構(gòu)造函數(shù);
- 重構(gòu)模型月褥,尋找模型中有疑問(wèn)或蹩腳的地方弛随,比如思考:聚合的設(shè)計(jì)是否正確,模型的性能等等宁赤;
領(lǐng)域建模是一個(gè)不斷重構(gòu)舀透,持續(xù)完善的過(guò)程,大家會(huì)在討論中將變化的部分反映到模型中决左,從而模型不斷細(xì)化并朝正確的方向走愕够。
9. 參考
- http://www.cnblogs.com/netfocus/archive/2011/10/10/2204949.html
- 《實(shí)現(xiàn)領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)》
本文是閱讀學(xué)習(xí) 湯雪華的博客 后所做的一些整理走贪,希望能對(duì)大家有所幫助~