領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)簡(jiǎn)介

當(dāng)今的企業(yè)應(yīng)用程序無疑是復(fù)雜的紊馏,并且依靠某些專門技術(shù)(持久性牺弄,AJAX姻几,Web服務(wù)等)來完成其工作。作為開發(fā)人員势告,我們傾向于專注于這些技術(shù)細(xì)節(jié)是可以理解的蛇捌。但是事實(shí)是,不能解決業(yè)務(wù)需求的系統(tǒng)對(duì)任何人都沒有用咱台,無論它的外觀多么漂亮或其基礎(chǔ)架構(gòu)的架構(gòu)如何络拌。

領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)(“Domain-Driven Design領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)”簡(jiǎn)稱DDD)的哲學(xué)-由埃里克·埃文斯(Eric Evans)在他的同名書中首次描述-旨在將我們的注意力放在應(yīng)用程序的核心,專注于業(yè)務(wù)領(lǐng)域固有的復(fù)雜性本身回溺。我們還將核心域(對(duì)業(yè)務(wù)而言是唯一的)與支持子域(本質(zhì)上通常是通用的春贸,例如金錢或時(shí)間)區(qū)分開來,并將更多的設(shè)計(jì)工作適當(dāng)?shù)胤旁诤诵纳稀?/p>

過去系統(tǒng)分析和系統(tǒng)設(shè)計(jì)都是分離的遗遵,正如我們國(guó)家“系統(tǒng)分析師” 和“系統(tǒng)設(shè)計(jì)師” 兩種職稱考試一樣萍恕,這樣割裂的結(jié)果導(dǎo)致,需求分析的結(jié)果無法直接進(jìn)行設(shè)計(jì)編程瓮恭,而能夠進(jìn)行編程運(yùn)行的代碼卻扭曲需求雄坪,導(dǎo)致客戶運(yùn)行軟件后才發(fā)現(xiàn)很多功能不是自己想要的,而且軟件不能快速跟隨需求變化屯蹦。DDD則打破了這種隔閡维哈,提出了領(lǐng)域模型概念,統(tǒng)一了分析和設(shè)計(jì)編程登澜,使得軟件能夠更靈活快速跟隨需求變化阔挠。DDD包括一組用于從域模型構(gòu)建企業(yè)應(yīng)用程序的模式。

代碼和模型...

借助DDD脑蠕,我們正在尋求創(chuàng)建問題域的模型购撼。持久性,用戶界面和消息傳遞內(nèi)容可能會(huì)在以后出現(xiàn)谴仙,這是需要了解的領(lǐng)域迂求,因?yàn)檫@是所構(gòu)建系統(tǒng)中將您公司的業(yè)務(wù)與競(jìng)爭(zhēng)對(duì)手區(qū)分開來的部分。 (如果事實(shí)并非如此晃跺,則可以考慮購(gòu)買包裝產(chǎn)品)揩局。

通過模型,我們不是指一個(gè)圖或一組圖掀虎。當(dāng)然凌盯,圖是有用的付枫,但它們不是模型,只是模型的不同視圖(參見圖)驰怎。

? 模型與模型視圖

所以模型是我們選擇在軟件中實(shí)現(xiàn)的概念集阐滩,以代碼和用于構(gòu)建交付系統(tǒng)的任何其他軟件工件表示。換句話說县忌,代碼本身就是模型掂榔。文本編輯器提供了使用此模型的一種方法,盡管現(xiàn)代工具也提供了許多其他可視化效果(UML類圖芹枷,實(shí)體關(guān)系圖衅疙,Spring beandocs [2],Struts / JSF流程等)鸳慈。

這是DDD模式的第一個(gè):模型驅(qū)動(dòng)的設(shè)計(jì)饱溢。 這意味著能夠?qū)⒛P椭械母拍睿ɡ硐肭闆r下完全按字面意義)映射到設(shè)計(jì)/代碼的概念。 模型的改變意味著代碼的改變走芋。 更改代碼意味著模型已更改绩郎。 DDD并不要求您使用面向?qū)ο髮?duì)域進(jìn)行建模-例如,我們可以使用規(guī)則引擎來構(gòu)建模型-但鑒于主要的企業(yè)編程語言是基于OO的翁逞,因此大多數(shù)模型本質(zhì)上都是OO肋杖。 畢竟,OO是基于建模范例的挖函。 模型的概念將表示為類和接口状植,職責(zé)將表示為類成員。

溝通語言

現(xiàn)在讓我們看一下域驅(qū)動(dòng)設(shè)計(jì)的另一個(gè)基本原理怨喘〗蚧回顧一下:我們想構(gòu)建一個(gè)域模型來捕獲正在構(gòu)建的系統(tǒng)的問題域,并且我們將在代碼/軟件工件中表達(dá)這種理解必怜。為了幫助我們做到這一點(diǎn)肉拓,DDD提倡領(lǐng)域?qū)<液烷_發(fā)人員使用模型中的概念有意識(shí)地進(jìn)行交流。因此梳庆,域?qū)<也粫?huì)根據(jù)屏幕或菜單項(xiàng)上的字段來描述新的用戶故事暖途,而是談?wù)撚驅(qū)ο笏璧幕A(chǔ)屬性或行為。同樣膏执,開發(fā)人員也不會(huì)談?wù)摂?shù)據(jù)庫(kù)表中類或列的新實(shí)例變量驻售。

嚴(yán)格執(zhí)行此操作,我們將開發(fā)一種無處不在的語言更米。如果無法輕松表達(dá)一個(gè)想法芋浮,則表示領(lǐng)域模型中缺少一個(gè)概念,團(tuán)隊(duì)將共同努力找出該概念是什么壳快。一旦建立了該概念纸巷,屏幕就會(huì)出現(xiàn)一個(gè)領(lǐng)域或數(shù)據(jù)庫(kù)表的列上的新字段便會(huì)隨之出現(xiàn)。

像大多數(shù)DDD一樣眶痰,這種開發(fā)無處不在的語言的想法并不是一個(gè)真正的新想法:XPers稱其為“名稱系統(tǒng)”瘤旨,并且DBA多年來一直將數(shù)據(jù)字典放在一起。但是無處不在的語言是一個(gè)令人回味的術(shù)語竖伯,并且可以出售給商務(wù)和技術(shù)人員〈嬲埽現(xiàn)在,“整個(gè)團(tuán)隊(duì)”敏捷實(shí)踐已成為主流七婴,這也變得很有道理祟偷。

模型和上下文...

每當(dāng)我們討論模型時(shí),它總是在一定范圍內(nèi)打厘。通承蕹Γ可以從使用該系統(tǒng)的最終用戶集合中推斷出此上下文。因此户盯,我們有一個(gè)部署到交易員的前臺(tái)交易系統(tǒng)嵌施,或一個(gè)超市收銀員使用的銷售點(diǎn)系統(tǒng)。這些用戶以特定的方式與模型的概念相關(guān)莽鸭,并且模型的術(shù)語對(duì)這些用戶有意義吗伤,但對(duì)于上下文之外的任何其他人則不一定。 DDD將此稱為有界上下文(BC)硫眨。每個(gè)域模型僅存在于一個(gè)有界上下文中足淆,而有界上下文恰好包含一個(gè)域模型。

我必須承認(rèn)礁阁,當(dāng)我第一次了解有界上下文時(shí)巧号,我看不出要點(diǎn):如果BC與域模型同構(gòu),為什么要引入一個(gè)新術(shù)語氮兵?如果只有最終用戶與BC進(jìn)行交互裂逐,那么這個(gè)術(shù)語也許就不需要了。但是泣栈,不同的系統(tǒng)(BC)也彼此交互卜高,發(fā)送文件,傳遞消息南片,調(diào)用API等掺涛。如果我們知道有兩個(gè)BC相互交互,則我們必須注意在一個(gè)概念之間進(jìn)行轉(zhuǎn)換:域和其他域疼进。

在模型周圍放置明確的邊界還意味著我們可以開始討論這些BC之間的關(guān)系薪缆。實(shí)際上,DDD標(biāo)識(shí)了BC之間的一整套關(guān)系伞广,以便我們可以合理化在需要將不同的BC鏈接在一起時(shí)應(yīng)該采取的措施:

  • 已發(fā)布的語言:交互的BC商定一種共同的語言(例如拣帽,企業(yè)服務(wù)總線上的一堆XML模式)疼电,通過它們它們可以彼此交互。
  • 開放主機(jī)服務(wù):BC指定任何其他BC可以使用其服務(wù)的協(xié)議(例如RESTful Web服務(wù))减拭;
  • 共享內(nèi)核:兩個(gè)BC使用通用的代碼內(nèi)核(例如蔽豺,庫(kù))作為通用的通用語言,但否則以其自己的特定方式來完成其他工作拧粪;
  • 客戶/供應(yīng)商:一個(gè)BC使用另一個(gè)服務(wù)的服務(wù)修陡,并且是另一個(gè)BC的利益相關(guān)者(客戶)。因此可霎,它可以影響該BC提供的服務(wù)魄鸦;
  • 遵循者:一個(gè)BC使用另一個(gè)服務(wù),但不是該另一個(gè)BC的利益相關(guān)者癣朗。因此拾因,它使用“原樣”(符合)該BC提供的協(xié)議或API;
  • 反腐敗層:一個(gè)BC使用另一方的服務(wù)斯棒,而不是利益相關(guān)者盾致,但其目的是通過引入一組適配器將一個(gè)BC依賴的BC的變化所產(chǎn)生的影響降至最低,即反腐敗層荣暮。使用反腐敗層庭惜,可以降低依賴風(fēng)險(xiǎn),特別是在與舊系統(tǒng)集成時(shí)穗酥,至少實(shí)現(xiàn)反腐敗層比重新實(shí)現(xiàn)該舊系統(tǒng)性價(jià)比要高很多护赊。

DDD建議我們繪制一個(gè)上下文圖,以識(shí)別我們的BC和我們依賴或依賴的BC砾跃,并確定這些依賴的性質(zhì)骏啰。

所有有關(guān)上下文映射和BC的討論有時(shí)都稱為戰(zhàn)略DDD,這是有充分理由的抽高。畢竟判耕,考慮一下BC之間的關(guān)系是很政治的:我的系統(tǒng)將依賴于哪個(gè)上游系統(tǒng),我是否容易與它們集成翘骂,我對(duì)它們有影響力壁熄,我信任它們嗎?下游也是如此:哪些系統(tǒng)將使用我的服務(wù)碳竟,我如何將我的功能作為服務(wù)公開草丧,它們對(duì)我有影響?一旦產(chǎn)生誤解莹桅,應(yīng)用程序很容易失敗昌执。

圖層和六邊形

現(xiàn)在,我們開始向內(nèi)考慮我們自己的BC(系統(tǒng))的體系結(jié)構(gòu)。從根本上講懂拾,DDD只真正關(guān)心域?qū)印?/p>

當(dāng)然煤禽,我們多年來一直在構(gòu)建多層系統(tǒng),但這并不意味著我們一定很擅長(zhǎng)委粉。確實(shí)呜师,過去有一些主導(dǎo)技術(shù)-比如EJB ,所有業(yè)務(wù)邏輯似乎都滲透到應(yīng)用程序?qū)由踔帘硎緦又屑纸冢粝乱唤M數(shù)據(jù)實(shí)體類作為數(shù)據(jù)持有者,也就是所謂的貧血模型衷畦。這不是DDD的意思栗涂。

分層架構(gòu)是一種歷史悠久的架構(gòu),通過分層架構(gòu)祈争,可以將系統(tǒng)按不同職責(zé)組織成有序?qū)哟谓锍蹋捎谶@種劃分往往比較容易界定,也算是最常見和最受歡迎的一種架構(gòu)菩混,有一個(gè)說法是:“如果你不知道要用什么架構(gòu)忿墅,那就用它。

當(dāng)我們說一個(gè)系統(tǒng)是分層架構(gòu)的時(shí)候沮峡,你可以把這個(gè)軟件想象成一個(gè)有很多層的蛋糕的樣子疚脐,其中每一層放在它的下一層上。較高層使用諸多較低層定義和提供的服務(wù)邢疙,但較低層并沒有察覺較高層的存在棍弄。另外,每一層都會(huì)對(duì)其上層隱藏更低的層疟游。

分層體系結(jié)構(gòu)的一個(gè)缺點(diǎn)是呼畸,它建議線性依賴關(guān)系的堆疊,從表示層一直到基礎(chǔ)結(jié)構(gòu)層颁虐。但是蛮原,我們可能希望在表示層和基礎(chǔ)結(jié)構(gòu)層中支持不同的實(shí)現(xiàn)。

因此另绩,不是將我們的應(yīng)用程序視為一組圖層儒陨,而是將其視為六邊形,如圖所示板熊。六邊形的內(nèi)部代表了application和domain層框全。外部代表應(yīng)用的驅(qū)動(dòng)邏輯、基礎(chǔ)設(shè)施或其他應(yīng)用干签。內(nèi)部通過端口和外部系統(tǒng)通信津辩,端口代表了一定協(xié)議,以API呈現(xiàn)。

圖:六角結(jié)構(gòu)

按照領(lǐng)域分層的模型喘沿,在應(yīng)用層和領(lǐng)域?qū)觾?nèi)置后闸度,一個(gè)典型的六邊形架構(gòu)應(yīng)用有兩個(gè)口子,一個(gè)入口對(duì)應(yīng)用戶接口層蚜印,用于應(yīng)用控制莺禁,一個(gè)出口對(duì)應(yīng)數(shù)據(jù)訪問層,用于數(shù)據(jù)獲取和持久化窄赋。每個(gè)口子都可以對(duì)應(yīng)幾個(gè)適配器哟冬,該應(yīng)用可以被自動(dòng)化測(cè)試,系統(tǒng)層面的回歸測(cè)試忆绰,用戶交互操作浩峡,遠(yuǎn)程HTTP調(diào)用,REST調(diào)用或者其他错敢。在數(shù)據(jù)方面翰灾,通過配置使用外部的數(shù)據(jù)庫(kù),可以是Oracle數(shù)據(jù)庫(kù)稚茅,mock的數(shù)據(jù)庫(kù)纸淮,測(cè)試數(shù)據(jù)庫(kù)或生產(chǎn)數(shù)據(jù)庫(kù),從而實(shí)現(xiàn)應(yīng)用和外部數(shù)據(jù)庫(kù)的解耦亚享。
另外值得一提的是咽块,在六邊形架構(gòu)中,自動(dòng)化測(cè)試和用戶具有同等的地位虹蒋,在實(shí)現(xiàn)用戶界面的同時(shí)就需要考慮自動(dòng)化測(cè)試糜芳。它們對(duì)應(yīng)相同的端口。六邊形架構(gòu)不僅讓自動(dòng)化測(cè)試這件事情成為設(shè)計(jì)第一要素魄衅,同時(shí)自動(dòng)化測(cè)試也保證應(yīng)用邏輯不會(huì)泄露到用戶界面峭竣,在技術(shù)上保證了層次的分界。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末晃虫,一起剝皮案震驚了整個(gè)濱河市皆撩,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌哲银,老刑警劉巖扛吞,帶你破解...
    沈念sama閱讀 222,183評(píng)論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異荆责,居然都是意外死亡滥比,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,850評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門做院,熙熙樓的掌柜王于貴愁眉苦臉地迎上來盲泛,“玉大人濒持,你說我怎么就攤上這事∷鹿觯” “怎么了柑营?”我有些...
    開封第一講書人閱讀 168,766評(píng)論 0 361
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)村视。 經(jīng)常有香客問我官套,道長(zhǎng),這世上最難降的妖魔是什么蚁孔? 我笑而不...
    開封第一講書人閱讀 59,854評(píng)論 1 299
  • 正文 為了忘掉前任奶赔,我火速辦了婚禮,結(jié)果婚禮上勒虾,老公的妹妹穿的比我還像新娘纺阔。我一直安慰自己,他們只是感情好修然,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,871評(píng)論 6 398
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著质况,像睡著了一般愕宋。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上结榄,一...
    開封第一講書人閱讀 52,457評(píng)論 1 311
  • 那天中贝,我揣著相機(jī)與錄音,去河邊找鬼臼朗。 笑死邻寿,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的视哑。 我是一名探鬼主播绣否,決...
    沈念sama閱讀 40,999評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼挡毅!你這毒婦竟也來了蒜撮?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,914評(píng)論 0 277
  • 序言:老撾萬榮一對(duì)情侶失蹤跪呈,失蹤者是張志新(化名)和其女友劉穎段磨,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體耗绿,經(jīng)...
    沈念sama閱讀 46,465評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡苹支,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,543評(píng)論 3 342
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了误阻。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片债蜜。...
    茶點(diǎn)故事閱讀 40,675評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡晴埂,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出策幼,到底是詐尸還是另有隱情邑时,我是刑警寧澤,帶...
    沈念sama閱讀 36,354評(píng)論 5 351
  • 正文 年R本政府宣布特姐,位于F島的核電站晶丘,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏唐含。R本人自食惡果不足惜浅浮,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,029評(píng)論 3 335
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望捷枯。 院中可真熱鬧滚秩,春花似錦、人聲如沸淮捆。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,514評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)攀痊。三九已至桐腌,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間苟径,已是汗流浹背案站。 一陣腳步聲響...
    開封第一講書人閱讀 33,616評(píng)論 1 274
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留棘街,地道東北人蟆盐。 一個(gè)月前我還...
    沈念sama閱讀 49,091評(píng)論 3 378
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像遭殉,于是被迫代替她去往敵國(guó)和親石挂。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,685評(píng)論 2 360

推薦閱讀更多精彩內(nèi)容