官术网_书友最值得收藏!

如何DDD

讓我們暫時撇開關(guān)于實現(xiàn)細(xì)節(jié)的討論,現(xiàn)在來看看DDD最具威力的特性之一:通用語言。通用語言和限界上下文(Bounded Context,2)同時構(gòu)成了DDD的兩大支柱,并且它們是相輔相成的。

上下文術(shù)語

就現(xiàn)在來說,可以將限界上下文看成是整個應(yīng)用程序之內(nèi)的一個概念性邊界。這個邊界之內(nèi)的每種領(lǐng)域術(shù)語、詞組或句子——也即通用語言,都有確定的上下文含義。在邊界之外,這些術(shù)語可能表示不同的意思。我們將在第2章中對限界上下文做深入探討。

通用語言

通用語言是團(tuán)隊共享的語言。領(lǐng)域?qū)<液烷_發(fā)者使用相同的通用語言進(jìn)行交流。事實上,團(tuán)隊中每個人都使用相同的通用語言。不管你在團(tuán)隊中的角色如何,只要你是團(tuán)隊的一員,你都將使用通用語言。

那么,你認(rèn)為你已經(jīng)知道了什么是通用語言了?

很明顯,通用語言是一種業(yè)務(wù)語言。

抱歉,不是。

通用語言必須采用工業(yè)標(biāo)準(zhǔn)術(shù)語。

不完全是。.

通用語言是領(lǐng)域?qū)<覍S玫摹?/p>

對不起,不是。

通用語言是團(tuán)隊自己創(chuàng)建的公用語言,團(tuán)隊中同時包含領(lǐng)域?qū)<液蛙浖_發(fā)人員。

對了。

自然地,領(lǐng)域?qū)<覍νㄓ谜Z言有很大的影響,因為他們最了解業(yè)務(wù),并且深受工業(yè)標(biāo)準(zhǔn)的影響。但是,通用語言更多地是關(guān)于業(yè)務(wù)本身如何思考和運(yùn)作的。此外,很多時候,不同領(lǐng)域?qū)<視诟拍詈托g(shù)語上產(chǎn)生分歧,他們甚至也會犯錯,因為他們也無法了解每種業(yè)務(wù)用例。因此,當(dāng)領(lǐng)域?qū)<液烷_發(fā)者一起創(chuàng)建領(lǐng)域模型的時候,他們有時會達(dá)成一致,有時會做一些妥協(xié),但最終目的都是為了創(chuàng)造最適合項目的通用語言。團(tuán)隊成員們妥協(xié)的絕對不應(yīng)是通用語言的質(zhì)量,而是概念、術(shù)語和含義。然而,最初的一致并不表示始終一致,就像其他語言一樣,通用語言也會隨著時間推移而不斷演化改變。

要使開發(fā)者和領(lǐng)域?qū)<乙粯恿私鈽I(yè)務(wù)沒有什么竅門。通用語言也不是強(qiáng)加在開發(fā)者身上的晦澀業(yè)務(wù)術(shù)語。通用語言是由整個團(tuán)隊共同創(chuàng)建的一門語言,其中包括領(lǐng)域?qū)<摇㈤_發(fā)者、業(yè)務(wù)分析員等。在開始的時候,通用語言可能只包含由領(lǐng)域?qū)<沂褂玫男g(shù)語,但是隨著時間推移,通用語言將不斷壯大成長。

在表1.4中,對于“注射流感疫苗”這個業(yè)務(wù)用例,我們不僅要完成建模,還應(yīng)該讓團(tuán)隊使用相同的通用語言。當(dāng)團(tuán)隊討論到業(yè)務(wù)模型時,他們會說:“護(hù)士給病人注射標(biāo)準(zhǔn)劑量的流感疫苗。”

表1.4 分析“注射流感疫苗”的最佳模型

由于通用語言最初只來自于領(lǐng)域?qū)<遥制缡请y免的。然而,這正是創(chuàng)建最佳通用語言的自然過程。在這個過程中,團(tuán)隊成員通過討論、參考資料、引用標(biāo)準(zhǔn)、查閱詞典等對通用語言進(jìn)行改進(jìn)。有時我們發(fā)現(xiàn),有些我們曾經(jīng)認(rèn)為能很好表達(dá)業(yè)務(wù)的詞匯不再適用了,而另外的一些詞匯具有更好的效果。

那么,你該如何掌握通用語言呢?這里有一些試驗性的方法:

? 同時繪制物理模型圖和概念模型圖,并標(biāo)以名字和行為。雖然這些圖并不是正式的設(shè)計圖,但它們卻包含了軟件建模的某些方面。即使你的團(tuán)隊在使用統(tǒng)一建模語言(Unified Modeling Language,UML )來完成正式建模,也不要得意忘形,因為這樣可能反而不利于團(tuán)隊的討論,最終將阻礙通用語言的產(chǎn)生。

? 創(chuàng)建一個包含簡單定義的術(shù)語表。將你能想到的術(shù)語都羅列出來,包括好的和不好的,并注明好與不好的原因。在你給術(shù)語下定義時,你在不經(jīng)意間就會創(chuàng)造出一些可重用的詞匯,因為此時你使用的是領(lǐng)域中的通用語言。

? 如果你不喜歡術(shù)語表,可以采用其他類型的文檔,但記得將那些“不正式”的模型圖也包含進(jìn)去。同樣,這里最終的目的也是發(fā)現(xiàn)通用語言中的術(shù)語和詞組。

? 由于團(tuán)隊中有些人工作在術(shù)語表上,還有些人工作在文檔上,此時你需要找到團(tuán)隊的其他人員來檢查你的成果。分歧肯定是有的,你應(yīng)該對此有所準(zhǔn)備。

以上是建立通用語言的一些理想化步驟,這樣建立起來模型肯定不能直接用來指導(dǎo)開發(fā),而只是建立通用語言的起步而已。此后,改進(jìn)之后的通用語言將反映到系統(tǒng)的源代碼中,比如Java、C#或者Scala等。以上的模型圖和文檔并未表明通用語言會隨著時間而擴(kuò)大。在通用語言開發(fā)早期,這些材料可能會對我們產(chǎn)生鼓舞,但是時間一久,它們也將變得過時。這也是為什么只有團(tuán)隊的交流和代碼才能持續(xù)到最后的原因,也只有這兩者才能實時地反映通用語言。

由于團(tuán)隊交流和代碼才是對通用語言的持續(xù)表達(dá),你應(yīng)該試著拋棄那些模型圖、術(shù)語表和文檔。雖然這并不是DDD所要求的,但是這樣做的確很實用,因為我們很難將項目文檔和軟件系統(tǒng)保持同步。

有了以上認(rèn)識,我們便可以重新設(shè)計saveCustomer()方法了。我們將修改Customer,使其能夠反映出它應(yīng)該支持的業(yè)務(wù)操作:

img

當(dāng)然,以上的Customer并不是一個完美的模型,然而在實施DDD時,對設(shè)計的反思正是我們所期望的。作為一個團(tuán)隊,我們可以自由地討論什么樣的模型才是最好的,在對通用語言達(dá)成了一致之后,才開始著手開發(fā)。然而,即便我們可以對通用語言進(jìn)行一遍又一遍地提煉,此時上面的例子已經(jīng)能夠反映出一個Customer應(yīng)該支持的業(yè)務(wù)操作了。

另外,我們還應(yīng)該知道,對領(lǐng)域模型的修改也將導(dǎo)致對應(yīng)用層的修改。每一個應(yīng)用層的方法都對應(yīng)著一個單一的用例流:

img

這和最開始的saveCustomer()例子是不同的,在那個例子中,我們使用了同一個方法來處理多個用例流。在這個新的例子中,我們只用一個應(yīng)用層方法來修改Customer的姓名,除此之外,該方法別無其他業(yè)務(wù)功能。因此,在使用DDD時,我們應(yīng)該對照著模型的修改相應(yīng)地修改應(yīng)用層。同時,這也意味著用戶界面所反映的用戶操作也變得更加狹窄。但是無論如何,這個特定的應(yīng)用層方法不再要求我們在用戶姓名參數(shù)之后跟上10個null了。

對這個新例子你還算滿意吧?通過閱讀代碼你便能理解它的業(yè)務(wù)意圖。你還可以通過測試來保證它的功能,即只修改Customer的姓名。

因此,我們使用通用語言來捕捉特定核心業(yè)務(wù)領(lǐng)域中的概念和術(shù)語,它是一種團(tuán)隊模式。軟件模型包含名詞、形容詞、動詞和一些富有含義的語句等,團(tuán)隊成員便通過這些語言進(jìn)行交流。軟件實現(xiàn)和測試中也使用和團(tuán)隊語言一樣的通用語言。

是通用,不是萬能

我想,關(guān)于通用語言,有必要再做一點澄清。在理解通用語言時,我們必須牢牢記住以下幾點:

? 這里的“通用”意思是“普遍的”,或者“到處都存在的”。通用語言在團(tuán)隊范圍內(nèi)使用,并且只表達(dá)一個單一的領(lǐng)域模型。

? “通用語言”并不表示全企業(yè)、全公司或者全球性的萬能的領(lǐng)域語言。

? 限界上下文和通用語言間存在一對一的關(guān)系。

? 限界上下文是一個相對較小的概念,通常比我們起初想象的要小。限界上下文剛好能夠容納下一個獨(dú)立的業(yè)務(wù)領(lǐng)域所使用的通用語言。

? 只有當(dāng)團(tuán)隊工作在一個獨(dú)立的限界上下文中時,通用語言才是“通用”的。

? 雖然我們只工作在一個限界上下文中,但是通常我們還需要和其他限界上下文打交道,這時可以通過上下文映射圖(3)對這些限界上下文進(jìn)行集成。每個限界上下文都有自己的通用語言,而有時語言間的術(shù)語可能有重疊的地方。

? 如果你試圖將某個通用語言運(yùn)用在整個企業(yè)范圍之內(nèi),或者更大的、夸企業(yè)的范圍內(nèi),你將失敗。

當(dāng)你開始一個項目,而該項目已經(jīng)在使用DDD了,此時你需要將你正在開發(fā)的獨(dú)立限界上下文識別出來,這樣便在你的領(lǐng)域模型周圍加上了一個顯式的邊界。此時,你應(yīng)該在這個限界上下文中使用其專屬的通用語言。對于那些不包含在通用語言中的概念,你應(yīng)該拒絕使用。

主站蜘蛛池模板: 博乐市| 青川县| 嘉义县| 泸定县| 怀柔区| 辽中县| 盘山县| 西峡县| 青海省| 屏山县| 巴林左旗| 安泽县| 娄烦县| 定南县| 万年县| 桃江县| 荆门市| 云龙县| 建始县| 冀州市| 伽师县| 佛冈县| 郎溪县| 加查县| 随州市| 和林格尔县| 迁安市| 定陶县| 九台市| 松桃| 临安市| 清镇市| 台江县| 孟津县| 和田县| 鲜城| 吉水县| 玛沁县| 左云县| 临城县| 西乌珠穆沁旗|