自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

京東研發(fā)團(tuán)隊(duì)領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)(DDD)實(shí)踐

開發(fā) 架構(gòu)
DDD 是一個(gè)非常龐大的建模和設(shè)計(jì)體系,這篇文章只在理論和概念上闡述 DDD 的價(jià)值、方法和架構(gòu),歡迎任何的問題指正和補(bǔ)充。

過去幾年,通天塔一直處于快速的業(yè)務(wù)能力建設(shè)和架構(gòu)完善的階段,以應(yīng)對(duì)不斷增長(zhǎng)的業(yè)務(wù)需求和容量、高可用等技術(shù)需求,現(xiàn)在通天塔平臺(tái)已經(jīng)能滿足集團(tuán)主站的大部分活動(dòng)、頻道搭建和運(yùn)營(yíng)能力,主流程的新需求越來(lái)越少,個(gè)性化需求和非標(biāo)準(zhǔn)化流程的數(shù)據(jù)源和服務(wù)接入的需求越來(lái)越多,有些甚至是京東零售體系外的,同時(shí)通天塔技術(shù)和產(chǎn)品也在積極主動(dòng)尋求變化和創(chuàng)新,這些因素結(jié)合在一起驅(qū)動(dòng)通天塔孵化出了一個(gè)以技術(shù)為導(dǎo)向的項(xiàng)目:通天塔積木,旨在構(gòu)建一個(gè)基于完全開放的前端 SDK 和后端數(shù)據(jù)源&服務(wù)、高度靈活和強(qiáng)大的積木畫布、能夠快速移植和部署到任何第三方 IT 環(huán)境的活動(dòng)搭建解決方案,這套方案的初衷和設(shè)計(jì)理念也契合了京東國(guó)際化賦能和 PaaS 化的戰(zhàn)略。

[[427770]]

目前通天塔積木已經(jīng)取得階段性成果,已開始賦能京東國(guó)內(nèi)和國(guó)際站,但如何應(yīng)對(duì)異常復(fù)雜的積木業(yè)務(wù)邏輯和不可預(yù)知的業(yè)務(wù)變化,構(gòu)建業(yè)務(wù)和底層技術(shù)基礎(chǔ)實(shí)施的完全解耦的系統(tǒng),一直是我們面對(duì)的巨大挑戰(zhàn)。也是時(shí)候從更高視角來(lái)看清問題和源頭,思考一種能應(yīng)對(duì)和控制業(yè)務(wù)復(fù)雜度、具備強(qiáng)擴(kuò)展性和彈性的解決方案??v觀我們的目標(biāo),DDD 這個(gè)詞不知不覺映入了我的眼簾。

2004 年著名建模專家 Eric Evans 發(fā)表了他最具影響力的書籍《Domain-Driven Design –Tackling Complexity in the Heart of Software》(領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)—軟件核心復(fù)雜性應(yīng)對(duì)之道),書中反復(fù)強(qiáng)調(diào)領(lǐng)域通用語(yǔ)言(Ubiquitous Language)的重要性,全面闡述了 DDD 戰(zhàn)略設(shè)計(jì)到戰(zhàn)術(shù)設(shè)計(jì)的方法論和實(shí)踐。讓軟件研發(fā)所有參與者圍繞著一個(gè)統(tǒng)一和一致的領(lǐng)域模型建模和設(shè)計(jì),分析模型和設(shè)計(jì)模型不再割裂,并引出了以領(lǐng)域?yàn)楹诵牡姆謱蛹軜?gòu),有效地分離業(yè)務(wù)和技術(shù)復(fù)雜度,使得領(lǐng)域?qū)拥拇a和領(lǐng)域模型保持高度一致。在戰(zhàn)術(shù)上提供了諸多元模式幫助構(gòu)建職責(zé)清晰、內(nèi)聚和高維護(hù)性和可擴(kuò)展性的代碼。

領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)不是新鮮的概念,至今已有十六年時(shí)間,一直來(lái)不曾大行其道,直到 IT 行業(yè)內(nèi)掀起微服務(wù)的狂潮,技術(shù)界才重新審視和意識(shí)到領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)的價(jià)值。不能說(shuō)微服務(wù)拯救了領(lǐng)域驅(qū)動(dòng)設(shè)計(jì),但確實(shí)是微服務(wù),讓領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)又重新煥發(fā)了青春。DDD 是一個(gè)非常龐大的建模和設(shè)計(jì)體系,這篇文章只在理論和概念上闡述 DDD 的價(jià)值、方法和架構(gòu),歡迎任何的問題指正和補(bǔ)充。

DDD 價(jià)值

應(yīng)對(duì)復(fù)雜業(yè)務(wù)

引起軟件系統(tǒng)復(fù)雜度的主要因素是需求,軟件系統(tǒng)需求又可以分兩個(gè)方面:業(yè)務(wù)需求和技術(shù)需求。我們分析系統(tǒng)的復(fù)雜度時(shí)就可以從業(yè)務(wù)復(fù)雜度和技術(shù)復(fù)雜度這兩個(gè)維度出發(fā)。

業(yè)務(wù)復(fù)雜度跟系統(tǒng)的業(yè)務(wù)需求規(guī)模和需求之間的關(guān)系層級(jí)有直接關(guān)系,需求的數(shù)量和關(guān)系的層級(jí)決定代碼的規(guī)模和邏輯循環(huán)或遞歸的層級(jí),系統(tǒng)的需求數(shù)量越大,需求之間的關(guān)系越復(fù)雜,系統(tǒng)的業(yè)務(wù)復(fù)雜度就越大。John Ousterhout 的著作《A Philosophy of Software Design》從認(rèn)知的負(fù)擔(dān)和開發(fā)工作量的角度來(lái)定義軟件系統(tǒng)的復(fù)雜度,并給出了一個(gè)復(fù)雜度公式:

子模塊的復(fù)雜度(cp)乘以該模塊對(duì)應(yīng)的開發(fā)時(shí)間權(quán)重值(tp),累加后得到系統(tǒng)的整體復(fù)雜度(C)??梢钥吹较到y(tǒng)整體的復(fù)雜度并不簡(jiǎn)單等于所有子模塊復(fù)雜度的累加,還要考慮該模塊的開發(fā)維護(hù)所花費(fèi)的時(shí)間在整體時(shí)間中的權(quán)重占比(tp),這個(gè)權(quán)重比就跟模塊劃分是否內(nèi)聚、設(shè)計(jì)是否優(yōu)雅有直接關(guān)系。

技術(shù)復(fù)雜度則來(lái)自于對(duì)軟件系統(tǒng)運(yùn)行的質(zhì)量需求,包括安全、高性能、高并發(fā)、高可用和高擴(kuò)展性。系統(tǒng)安全性要求對(duì)訪問進(jìn)行控制,無(wú)論是加密還是認(rèn)證和授權(quán),都需要為整個(gè)系統(tǒng)架構(gòu)添加額外的間接層。不僅對(duì)訪問的低延遲產(chǎn)生影響,還極大提升了系統(tǒng)代碼復(fù)雜度;為了讓后端系統(tǒng)能具備高擴(kuò)展性和彈性,要求所有系統(tǒng)的設(shè)計(jì)必須是無(wú)狀態(tài)的;為了提升用戶端訪問體驗(yàn),后端需要增添離線任務(wù)對(duì)數(shù)據(jù)加工、異構(gòu)、預(yù)熱、預(yù)緩存,以實(shí)現(xiàn)用空間換時(shí)間,降低實(shí)時(shí)接口的邏輯復(fù)雜度來(lái)降低請(qǐng)求的延遲。然而最讓開發(fā)者更抓狂的是這些技術(shù)需求彼此又是相互影響甚至相互矛盾,在一些復(fù)雜流程并要求高響應(yīng)的業(yè)務(wù)場(chǎng)景,如下單、秒殺等,會(huì)將一個(gè)同步的訪問請(qǐng)求拆分為多級(jí)步驟的異步請(qǐng)求,再通過引入消息中間件對(duì)這些請(qǐng)求進(jìn)行整合和分散處理,這種分離一方面增加了系統(tǒng)架構(gòu)的復(fù)雜性,另一方面也因?yàn)橐肓烁嗟馁Y源,使得系統(tǒng)的高可用面臨挑戰(zhàn),并增加了維護(hù)數(shù)據(jù)一致性的難度。而且技術(shù)復(fù)雜度與業(yè)務(wù)復(fù)雜度并非孤立,二者復(fù)雜度因子混合在一起產(chǎn)生的負(fù)作用更讓系統(tǒng)的復(fù)雜度變得不可預(yù)期,難以掌控,就好比氫氣和氯氣混合在一起遇到光亮發(fā)生爆炸一樣。

DDD 的核心思想就是要避免業(yè)務(wù)邏輯的復(fù)雜度與技術(shù)實(shí)現(xiàn)的復(fù)雜度混淆在一起,確定業(yè)務(wù)邏輯與技術(shù)實(shí)現(xiàn)的邊界,從而隔離各自的復(fù)雜度,業(yè)務(wù)邏輯并不關(guān)心技術(shù)是如何實(shí)現(xiàn)的。無(wú)論采用何種技術(shù),只要業(yè)務(wù)需求不變,業(yè)務(wù)規(guī)則就不會(huì)變化。理想狀態(tài)下,應(yīng)該保證業(yè)務(wù)邏輯與技術(shù)實(shí)現(xiàn)是正交的。

DDD 通過分層架構(gòu)與六邊形架構(gòu)確保業(yè)務(wù)邏輯與技術(shù)實(shí)現(xiàn)的隔離。

DDD 戰(zhàn)略設(shè)計(jì)指導(dǎo)我們面對(duì)客戶的業(yè)務(wù)需求,由領(lǐng)域?qū)<遗c開發(fā)團(tuán)隊(duì)展開充分的交流,經(jīng)過需求分析與知識(shí)提煉,獲得清晰的問題域,在引入限界上下文和上下文映射對(duì)問題域進(jìn)行合理的分解,識(shí)別出核心領(lǐng)域與子領(lǐng)域,并確定領(lǐng)域的邊界以及它們之間的關(guān)系,從而把一個(gè)大的復(fù)雜系統(tǒng)問題拆分成多個(gè)細(xì)粒度、獨(dú)立和內(nèi)聚的業(yè)務(wù)子問題,從而很好地分解和控制業(yè)務(wù)復(fù)雜度,各個(gè)小組聚焦各自的子領(lǐng)域中。

在架構(gòu)方面,通過分層架構(gòu)來(lái)隔離關(guān)注點(diǎn),將領(lǐng)域?qū)崿F(xiàn)獨(dú)立出來(lái),利于領(lǐng)域模型的單一性與穩(wěn)定性;

引入六邊形架構(gòu)清晰地界定領(lǐng)域與技術(shù)基礎(chǔ)設(shè)施的邊界;CQRS 模式則分離了查詢場(chǎng)景和命令場(chǎng)景,針對(duì)不同場(chǎng)景選擇使用同步或異步操作,提高架構(gòu)的低延遲性與高并發(fā)能力。

分層架構(gòu)

“分層架構(gòu)”遵循了“關(guān)注點(diǎn)分離”原則,將屬于業(yè)務(wù)邏輯的關(guān)注點(diǎn)放到領(lǐng)域?qū)?Domain Layer)中,而將支撐業(yè)務(wù)邏輯的技術(shù)實(shí)現(xiàn)放到基礎(chǔ)設(shè)施層(Infrastructure Layer)中。同時(shí),領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)又頗具創(chuàng)見的引入了應(yīng)用層(Application Layer)。應(yīng)用層扮演了雙重角色。一方面它作為業(yè)務(wù)邏輯的外觀(Facade),暴露了能夠體現(xiàn)業(yè)務(wù)用例的應(yīng)用服務(wù)接口;另一方面它又是業(yè)務(wù)邏輯與技術(shù)實(shí)現(xiàn)的粘合劑,實(shí)現(xiàn)二者之間的協(xié)作。下圖展現(xiàn)的就是一個(gè)典型的領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)分層架構(gòu)。藍(lán)色區(qū)域的內(nèi)容與業(yè)務(wù)邏輯有關(guān),灰色區(qū)域的內(nèi)容與技術(shù)實(shí)現(xiàn)有關(guān),二者涇渭分明,然后匯合在應(yīng)用層。應(yīng)用層確定了業(yè)務(wù)邏輯與技術(shù)實(shí)現(xiàn)的邊界,通過直接依賴或者依賴注入(DI,Dependency Injection)的方式將二者結(jié)合起來(lái)。

六邊形架構(gòu)

由 Cockburn 提出的六邊形架構(gòu)則以“內(nèi)外分離”的方式,更加清晰地勾勒出業(yè)務(wù)邏輯與技術(shù)實(shí)現(xiàn)的邊界,且將業(yè)務(wù)邏輯放在了架構(gòu)的核心位置。這種架構(gòu)模式改變了我們觀察系統(tǒng)架構(gòu)的視角。體現(xiàn)業(yè)務(wù)邏輯的應(yīng)用層與領(lǐng)域?qū)犹幱诹呅渭軜?gòu)的內(nèi)核,并通過內(nèi)部的六邊形邊界與基礎(chǔ)設(shè)施的模塊隔離開。當(dāng)我們?cè)谶M(jìn)行軟件開發(fā)時(shí),只要恪守架構(gòu)上的六邊形邊界,就不會(huì)讓技術(shù)實(shí)現(xiàn)的復(fù)雜度污染到業(yè)務(wù)邏輯,保證了領(lǐng)域的整潔。邊界還隔離了變化產(chǎn)生的影響。如果我們?cè)陬I(lǐng)域?qū)踊驊?yīng)用層抽象了技術(shù)實(shí)現(xiàn)的接口,再通過依賴注入將控制的方向倒轉(zhuǎn),業(yè)務(wù)內(nèi)核就會(huì)變得更加的穩(wěn)定,不會(huì)因?yàn)榧夹g(shù)選型或其他決策的變化而導(dǎo)致領(lǐng)域代碼的修改。

快速響應(yīng)業(yè)務(wù)變化

不確定性和變化是這個(gè)時(shí)代的主旋律,業(yè)務(wù)需要快速上線,并根據(jù)用戶的反饋不停地調(diào)整和升級(jí),有生命力的業(yè)務(wù)主動(dòng)尋求變化,不變則亡是很多行業(yè)目前的共識(shí),企業(yè)應(yīng)對(duì)變化的響應(yīng)力成了成敗的關(guān)鍵。同時(shí)一個(gè)長(zhǎng)期困擾軟件研發(fā)的問題是,需求總是在變化,無(wú)論預(yù)先設(shè)計(jì)如何“精確”,總是發(fā)現(xiàn)下一個(gè)坑就在不遠(yuǎn)處。相信很多技術(shù)人員都有這樣的經(jīng)歷,架構(gòu)和響應(yīng)能力越來(lái)越糟糕,也就是我們常說(shuō)的架構(gòu)腐化了,最后大家不得不接受重寫。軟件架構(gòu)設(shè)計(jì)的另一個(gè)關(guān)鍵方面是讓系統(tǒng)能夠更快地響應(yīng)外界業(yè)務(wù)的變化,并且使得系統(tǒng)能夠持續(xù)演進(jìn)。在遇到變化時(shí)不需要從頭開始,保證實(shí)現(xiàn)成本得到有效控制。

DDD 的核心是從業(yè)務(wù)出發(fā)、面向業(yè)務(wù)變化構(gòu)建軟件架構(gòu),實(shí)質(zhì)是保證面對(duì)業(yè)務(wù)變化時(shí)我們能夠有足夠快的響應(yīng)能力。面向業(yè)務(wù)變化而架構(gòu)就要求首先理解業(yè)務(wù)的核心問題,即有針對(duì)性地進(jìn)行關(guān)注點(diǎn)分離來(lái)找到相對(duì)內(nèi)聚的業(yè)務(wù)活動(dòng)形成子問題域。讓每個(gè)字問題的劃分盡可能靠近變化的原點(diǎn),子問題域內(nèi)部是相對(duì)穩(wěn)定的,未來(lái)的變化頻率不會(huì)很高,是符合深模塊特性的,而子問題邊界是很容易變化的。DDD 最后在實(shí)現(xiàn)層面利用成熟的技術(shù)模式屏蔽掉技術(shù)細(xì)節(jié)的復(fù)雜度。

與微服務(wù)相得益彰

Martin Fowler 和 James Lewis 提出微服務(wù)時(shí),提出了微服務(wù)的 9 大架構(gòu)特質(zhì),指導(dǎo)組織圍繞業(yè)務(wù)組建團(tuán)隊(duì),把業(yè)務(wù)拆分為一個(gè)個(gè)業(yè)務(wù)上高度內(nèi)聚、技術(shù)上松散耦合、運(yùn)行在獨(dú)立進(jìn)程中的小型服務(wù),微服務(wù)架構(gòu)賦予了每個(gè)服務(wù)業(yè)務(wù)上的敏捷性和技術(shù)上的自主性,因此可以針對(duì)每個(gè)服務(wù)進(jìn)行獨(dú)立地迭代、更新、部署和彈性擴(kuò)展,從而縮短需求交付周期并加速創(chuàng)新。

在面對(duì)復(fù)雜業(yè)務(wù)和快速變化需求時(shí),DDD 從業(yè)務(wù)視角進(jìn)行關(guān)注點(diǎn)分離和應(yīng)對(duì)復(fù)雜度,讓業(yè)務(wù)具備更高的響應(yīng)力。DDD 戰(zhàn)略設(shè)計(jì)階段,引入限界上下文(Bounded Context)和上下文映射(Context Map)對(duì)問題域進(jìn)行合理的分解,確定領(lǐng)域的邊界以及它們之間的關(guān)系,維持模型的完整性。

限界上下文不僅限于對(duì)領(lǐng)域模型的控制,而在于分離關(guān)注點(diǎn)之后,使得整個(gè)上下文可以成為獨(dú)立部署的設(shè)計(jì)單元,這就是“微服務(wù)”的概念,上下文映射的諸多模式則對(duì)應(yīng)了微服務(wù)之間的協(xié)作。因此在戰(zhàn)略設(shè)計(jì)階段,微服務(wù)擴(kuò)展了領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)的內(nèi)容,反過來(lái)領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)又能夠保證良好的微服務(wù)設(shè)計(jì)。

邊界給了實(shí)現(xiàn)限界上下文內(nèi)部的最大自由度。這也是戰(zhàn)略設(shè)計(jì)在分治上起到的效用,我們可以在不同的限界上下文選擇不同的架構(gòu)模式和技術(shù)實(shí)現(xiàn),這也正好映照了微服務(wù)的特點(diǎn):在技術(shù)架構(gòu)上,系統(tǒng)模塊之間充分解耦,可以自由地選擇合適的技術(shù)架構(gòu),去中心化地治理技術(shù)和數(shù)據(jù)。

ThoughtWorks 公司技術(shù)專家編寫的《微服務(wù)設(shè)計(jì)》書中,專門有一章節(jié)“限界上下文”,充分說(shuō)明微服務(wù)的落地需要 DDD 來(lái)輔助的,起碼在建模階段是需要借助 DDD 強(qiáng)大的戰(zhàn)略模式來(lái)支撐的。微服務(wù)不是簡(jiǎn)單的指將服務(wù)盡可能的拆小,然后一個(gè) RPC 框架搞定了,這太粗糙了,無(wú)法落地。

輔助中臺(tái)戰(zhàn)略落地

領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)讓參與者基于統(tǒng)一語(yǔ)言溝通和協(xié)作,圍繞一個(gè)統(tǒng)一和一致的領(lǐng)域模型工作,傳統(tǒng)的分析模型和設(shè)計(jì)模型不再割裂;顯式地把業(yè)務(wù)領(lǐng)域和設(shè)計(jì)放到了軟件開發(fā)的核心,軟件人員和業(yè)務(wù)人員合作來(lái)構(gòu)建領(lǐng)域模型,使得軟件的交付質(zhì)量更高且維護(hù)成本更低;利用限界上下文來(lái)分解問題域,識(shí)別核心領(lǐng)域,有效分解和控制了業(yè)務(wù)的復(fù)雜度;

利用 DDD 提倡的分層、六邊形等架構(gòu),分離了業(yè)務(wù)復(fù)雜度和技術(shù)復(fù)雜度,使得系統(tǒng)具備更強(qiáng)的擴(kuò)展性和彈性;戰(zhàn)術(shù)層面提供了元模型(聚合,實(shí)體,值對(duì)象,服務(wù),工廠,倉(cāng)儲(chǔ))幫助構(gòu)建清晰、穩(wěn)定,能快速響應(yīng)變化和新需求能力的應(yīng)用;

DDD 構(gòu)建的應(yīng)用能快速方便地切到微服務(wù);領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)給企業(yè)應(yīng)用帶來(lái)的穩(wěn)定性、靈活性、擴(kuò)展性和應(yīng)對(duì)變化的響應(yīng)力對(duì)于建立靈活前臺(tái)、穩(wěn)固中臺(tái)能帶來(lái)巨大的幫助作用。

DDD 過程

領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)是一套面對(duì)復(fù)雜業(yè)務(wù)進(jìn)行建模和設(shè)計(jì)的方法論和實(shí)踐,建立了以領(lǐng)域?yàn)楹诵尿?qū)動(dòng)力的設(shè)計(jì)體系。領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)分為 2 個(gè)主要過程:戰(zhàn)略設(shè)計(jì)、戰(zhàn)術(shù)設(shè)計(jì)。

在戰(zhàn)略設(shè)計(jì)階段,面對(duì)紛繁復(fù)雜的業(yè)務(wù)需求,領(lǐng)域?qū)<液脱邪l(fā)團(tuán)隊(duì)進(jìn)行緊密合作、充分溝通,進(jìn)行事件風(fēng)暴或場(chǎng)景驅(qū)動(dòng)設(shè)計(jì),分析需求并提煉知識(shí),得到比較清晰的問題域,輸出由領(lǐng)域?qū)<液脱邪l(fā)團(tuán)隊(duì)達(dá)成共識(shí)的統(tǒng)一語(yǔ)言(UL,Ubiquitous Language),基于統(tǒng)一語(yǔ)言對(duì)問題域進(jìn)行分析和建模,識(shí)別業(yè)務(wù)邊界,確定限界上下文,根據(jù)限界上下文劃分獨(dú)立的領(lǐng)域,建立限界上下文彼此之間的關(guān)系,接著引入系統(tǒng)上下文(System Context)確定系統(tǒng)的邊界,并確定它的外部環(huán)境,包括與其集成的第三方系統(tǒng)與基礎(chǔ)設(shè)施。利用 DDD 分層架構(gòu)或六邊形架構(gòu)界定業(yè)務(wù)領(lǐng)域和技術(shù)實(shí)現(xiàn)的邊界,讓穩(wěn)定的核心領(lǐng)域模型處于架構(gòu)的最內(nèi)部,避免技術(shù)實(shí)現(xiàn)和架構(gòu)變動(dòng)帶來(lái)的影響。

接著進(jìn)入戰(zhàn)術(shù)設(shè)計(jì)階段,一個(gè)大的業(yè)務(wù)問題被分解為多個(gè)限界上下文(問題域),團(tuán)隊(duì)視野和專注就可以聚焦到每一個(gè)內(nèi)聚的限界上下文,進(jìn)行戰(zhàn)術(shù)設(shè)計(jì)。戰(zhàn)術(shù)設(shè)計(jì)的重點(diǎn)是利用領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)的元模型對(duì)領(lǐng)域的復(fù)雜性進(jìn)行分解和建模。

領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)強(qiáng)調(diào)和突出了領(lǐng)域模型的重要性,通過整個(gè)領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)過程,綁定領(lǐng)域模型和技術(shù)模型,以保證領(lǐng)域模型和技術(shù)模型在貫穿整個(gè)軟件開發(fā)的生命周期中(需求分析、建模、架構(gòu)、設(shè)計(jì)、編碼、測(cè)試與持續(xù)重構(gòu))的強(qiáng)一致性。領(lǐng)域模型指導(dǎo)著軟件設(shè)計(jì)以及技術(shù)編碼實(shí)現(xiàn),接著通過重構(gòu)實(shí)踐來(lái)挖掘隱式概念,完善統(tǒng)一語(yǔ)言和模型,運(yùn)用設(shè)計(jì)模式改進(jìn)設(shè)計(jì)與開發(fā)質(zhì)量。以下是領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)的粗略過程:

戰(zhàn)略設(shè)計(jì)

提煉問題域

回顧我們往日的分析和解決問題過程, 面對(duì)復(fù)雜問題,很多同學(xué)還沒完全理解問題的全貌就已經(jīng)在提出解決辦法,這些解決辦法只是針對(duì)問題的局部,經(jīng)典圖書《第五項(xiàng)修煉》把這種行為稱為“反應(yīng)式”的,碰到一個(gè)問題給出一個(gè)回應(yīng)辦法,而從這些問題整體來(lái)看這種方式會(huì)阻礙團(tuán)隊(duì)找出最佳解決方案。

DDD 作為一種建模和架構(gòu)方法,最大的突破是著重明確了區(qū)分了問題域和解決方案域,對(duì)業(yè)務(wù)問題的認(rèn)知不是技術(shù)人員最擅長(zhǎng)的,很多研發(fā)在碰到需求時(shí),腦子本能就閃現(xiàn)表、類、服務(wù)、架構(gòu),把解決方案當(dāng)終極問題來(lái)追求,而 DDD 要求研發(fā)進(jìn)行痛苦的蛻變,在業(yè)務(wù)分析和領(lǐng)域建模階段忘記技術(shù)解決方案。同時(shí) DDD 要求領(lǐng)域?qū)<液图夹g(shù)人員坐在一起通力合作、密切溝通來(lái)分析和建模,領(lǐng)域?qū)<覍?duì)業(yè)務(wù)有著深刻的理解,技術(shù)人員擅長(zhǎng)技術(shù)實(shí)現(xiàn)和架構(gòu)設(shè)計(jì),而領(lǐng)域?qū)<液图夹g(shù)人員由于工種的差異導(dǎo)致交流產(chǎn)生障礙,開發(fā)人員滿腦子是技術(shù)語(yǔ)言,領(lǐng)域?qū)<夷X子也都是業(yè)務(wù)概念,如果按照本能基于自己的專業(yè)背景進(jìn)行溝通,效率太低了,即使有翻譯的角色也會(huì)產(chǎn)生理解偏差,DDD 的一個(gè)核心原則是所有人員包括領(lǐng)域?qū)<液图夹g(shù)的進(jìn)行任何溝通都使用一種基于模型的通用語(yǔ)言(UL,Ubiquitous Language),在代碼中也是這樣。

DDD 幫助技術(shù)人員對(duì)需求進(jìn)行本質(zhì)思考和理解,關(guān)注點(diǎn)不在是聚焦在功能上,而是理解需求的真正意圖和愿景,而非開發(fā)一個(gè) feature,更深層次地理解隱含的愿景才能開發(fā)出真正地解決問題和創(chuàng)造價(jià)值的系統(tǒng)來(lái)。在提煉問題域過程中,領(lǐng)域?qū)<液图夹g(shù)專家通過充分交流,進(jìn)行需求分析和知識(shí)提煉,獲得清晰的問題子域,識(shí)別出核心域、通用域、支撐域。通用域是開發(fā)該軟件系統(tǒng)根本競(jìng)爭(zhēng)力所在,也是領(lǐng)域建模的重心,建議分配最精銳的研發(fā);

通用域是指多個(gè)子域依賴的通用功能子域,比如權(quán)限、郵件、日志系統(tǒng)等;支撐域是指系統(tǒng)中非核心域和通用域的業(yè)務(wù)域。

需求分析時(shí)從用例開始,列出達(dá)成業(yè)務(wù)目標(biāo)需要的步驟,切忌跳轉(zhuǎn)到解決方案上,識(shí)別出用于構(gòu)建模型的知識(shí),通過 UML 表示分析模型和業(yè)務(wù)模型,形成業(yè)務(wù)和技術(shù)人員達(dá)成共識(shí)的通用語(yǔ)言。

該階段領(lǐng)域?qū)<抑粚W⒂趩栴}域而不是解決方案,業(yè)務(wù)和技術(shù)人員基于 UL 溝通,并且考慮投入產(chǎn)出比,團(tuán)隊(duì)只為核心業(yè)務(wù)進(jìn)行領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)并創(chuàng)建 UL,訂單系統(tǒng)為下單模塊進(jìn)行 DDD,訂單監(jiān)控模塊用普通的事務(wù)腳本方式來(lái)即可,我們通天塔的活動(dòng)模板和積木業(yè)務(wù)非常復(fù)雜和核心,非常適合使用 DDD 來(lái)建模和架構(gòu)設(shè)計(jì),而通天塔后端的 Man 系統(tǒng)是面向開發(fā)者進(jìn)行后端和線上業(yè)務(wù)監(jiān)控的,進(jìn)行 DDD 就是小題大做。

識(shí)別限界上下文(Bounded Context)

Eric Evans 說(shuō):“對(duì)一個(gè)大型系統(tǒng),領(lǐng)域模型的完全統(tǒng)一將是不可行的或者不劃算的。”。DDD 的構(gòu)建塊不能盲目地應(yīng)用在一個(gè)無(wú)限大的領(lǐng)域模型上,一個(gè)無(wú)限大的領(lǐng)域模型也無(wú)助于我們開發(fā)出優(yōu)質(zhì)的軟件,限界上下文是分解領(lǐng)域模型的關(guān)鍵。限界上下文是一種“分而治之”的思維,也是一種高層的抽象機(jī)制,讓人們對(duì)領(lǐng)域進(jìn)行本質(zhì)思考,簡(jiǎn)化問題和應(yīng)對(duì)復(fù)雜性。

限界上下文如同細(xì)胞,細(xì)胞是上下文,細(xì)胞壁是邊界,細(xì)胞內(nèi)的信息負(fù)責(zé)對(duì)代謝和遺傳進(jìn)行調(diào)控,細(xì)胞壁對(duì)細(xì)胞起著支持和保護(hù)防御的作用,控制物質(zhì)進(jìn)出,讓對(duì)細(xì)胞有用的物質(zhì)不能出來(lái),有害的物質(zhì)也不能進(jìn)入細(xì)胞。而領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)中的限界上下文保證領(lǐng)域模型的一致性和完整性,清晰邊界的控制力保證了領(lǐng)域的安全和穩(wěn)定。

如何識(shí)別限界上下文?

明確了系統(tǒng)的問題域和業(yè)務(wù)期望后,梳理出主要的業(yè)務(wù)流程,這些業(yè)務(wù)流程體現(xiàn)了各種參與者在這個(gè)過程中通過業(yè)務(wù)活動(dòng)共同協(xié)作,最終完成具有業(yè)務(wù)價(jià)值的領(lǐng)域功能。業(yè)務(wù)流程結(jié)合了參與角色(Who)、業(yè)務(wù)活動(dòng)(What)和業(yè)務(wù)價(jià)值(Why)。在業(yè)務(wù)流程的基礎(chǔ)上,我們就可以抽象出不同的業(yè)務(wù)場(chǎng)景,這些業(yè)務(wù)場(chǎng)景又由多個(gè)業(yè)務(wù)活動(dòng)組成,可以利用領(lǐng)域場(chǎng)景分析方法剖析場(chǎng)景,以幫助我們識(shí)別業(yè)務(wù)活動(dòng),例如采用用例對(duì)場(chǎng)景進(jìn)行分析,此時(shí),一個(gè)業(yè)務(wù)活動(dòng)實(shí)則就是一個(gè)用例。業(yè)務(wù)流程是一個(gè)由多個(gè)用戶角色參與的動(dòng)態(tài)過程,而業(yè)務(wù)場(chǎng)景則是這些用戶角色執(zhí)行業(yè)務(wù)活動(dòng)的靜態(tài)上下文。

接下來(lái),我們利用領(lǐng)域場(chǎng)景分析的用例分析方法剖析這些場(chǎng)景。通過參與者(Actor)來(lái)驅(qū)動(dòng)對(duì)用例的識(shí)別,這些參與者恰好就是參與到場(chǎng)景業(yè)務(wù)活動(dòng)的角色。根據(jù)用例描述出來(lái)的業(yè)務(wù)活動(dòng)應(yīng)該與統(tǒng)一語(yǔ)言一致,最好直接從統(tǒng)一語(yǔ)言中擷取。一旦準(zhǔn)確地用統(tǒng)一語(yǔ)言描述出這些業(yè)務(wù)活動(dòng),我們就可以從語(yǔ)義相關(guān)性和功能相關(guān)性兩個(gè)方面識(shí)別業(yè)務(wù)邊界,進(jìn)而提煉出初步的限界上下文。

從不同角度看待限界上下文,限界上下文會(huì)呈現(xiàn)出對(duì)不同對(duì)象的控制力。

  • 領(lǐng)域邏輯層面:限界上下文確定了領(lǐng)域模型的業(yè)務(wù)邊界,維護(hù)了模型的完整性與一致性,從而降低系統(tǒng)的業(yè)務(wù)復(fù)雜度。
  • 團(tuán)隊(duì)合作層面:限界上下文確定了團(tuán)隊(duì)的工作邊界,建立了團(tuán)隊(duì)之間的合作模式,提升了團(tuán)隊(duì)間的協(xié)作效率,“康威定律”告訴我們,系統(tǒng)設(shè)計(jì)(產(chǎn)品結(jié)構(gòu))等同組織形式,每個(gè)設(shè)計(jì)系統(tǒng)的組織,其產(chǎn)生的設(shè)計(jì)等同于組織之間的溝通結(jié)構(gòu),限界上下文指導(dǎo)產(chǎn)生的團(tuán)隊(duì)結(jié)構(gòu)的工作模式是最高效的。
  • 技術(shù)架構(gòu)層面:限界上下文確定了系統(tǒng)架構(gòu)的應(yīng)用邊界,保證了系統(tǒng)層和上下文領(lǐng)域?qū)痈髯缘囊恢滦?,建立了上下文之間的集成方式。微服務(wù)中,限界上下文指導(dǎo)技術(shù)人員劃分微服務(wù)的邊界,通常一個(gè)限界上下文作為一個(gè)在獨(dú)立進(jìn)程中運(yùn)行的微服務(wù)。

DDD 驅(qū)動(dòng)我們把每一個(gè)限界上下文設(shè)計(jì)成一個(gè)個(gè)“自治”的單元,自治要滿足四個(gè)特點(diǎn):

最小完備是實(shí)現(xiàn)自治的基本條件,指的是自治單元履行的職責(zé)是根據(jù)業(yè)務(wù)價(jià)值的完整性和最小功能集進(jìn)行設(shè)計(jì)的,這讓自治單元無(wú)需求助其他自治單元獲得信息,避免了不必要的依賴關(guān)系,同時(shí)也避免了不必要和不合適的職責(zé)添加到該自治單元上。

自我履行意味著由自治單元自身決定要做什么。是否應(yīng)該履行某職責(zé),由限界上下文擁有的信息來(lái)決定。站在自治單元的角度去思考:“如果我擁有了這些信息,我究竟應(yīng)該履行哪些職責(zé)?”這些職責(zé)屬于當(dāng)前上下文的活動(dòng)范圍,一旦超出,就該毫不猶豫地將不屬于該范圍的請(qǐng)求轉(zhuǎn)交給別的上下文。自我履行其實(shí)意味著對(duì)知識(shí)的掌握,為避免風(fēng)險(xiǎn),你要履行的職責(zé)一定是你掌握的知識(shí)范疇之內(nèi)。

穩(wěn)定空間指的是減少外界變化對(duì)限界上下文內(nèi)部的影響。穩(wěn)定空間符合開放封閉原則(OCP),即對(duì)修改是封閉的,對(duì)擴(kuò)展是開放的,該原則其實(shí)體現(xiàn)了一個(gè)單元的封閉空間與開放空間。封閉空間體現(xiàn)為對(duì)細(xì)節(jié)的封裝與隱藏,開放空間體現(xiàn)為對(duì)共性特征的抽象與統(tǒng)一,二者共同確保了整個(gè)空間的穩(wěn)定。

獨(dú)立進(jìn)化指的是減少限界上下文的變化對(duì)外界的影響。用限界上下文的上下游關(guān)系來(lái)闡釋,則穩(wěn)定空間寓意下游限界上下文,無(wú)論上游怎么變,我自巋然不動(dòng)。要做到獨(dú)立進(jìn)化,就必須保證對(duì)外公開接口的穩(wěn)定性,因?yàn)檫@些接口被眾多消費(fèi)者依賴和調(diào)用,一旦發(fā)生變更,就會(huì)牽一發(fā)而動(dòng)全身。一個(gè)獨(dú)立進(jìn)化的限界上下文,需要一個(gè)穩(wěn)定、設(shè)計(jì)良好的接口設(shè)計(jì),并在版本上考慮了兼容與演化。

最小完備是基礎(chǔ),只有賦予了限界上下文足夠的信息,才能保證它的自我履行。穩(wěn)定空間與獨(dú)立進(jìn)化則一個(gè)對(duì)內(nèi)一個(gè)對(duì)外,是對(duì)變化的有效應(yīng)對(duì),而它們又是通過最小完備和自我履行來(lái)保障限界上下文受到變化的影響最小。

上下文映射

限界上下文僅是一種對(duì)領(lǐng)域問題域的靜態(tài)劃分,還缺少一個(gè)重要的關(guān)注點(diǎn),即:限界上下文之間是如何協(xié)作的?當(dāng)我們發(fā)現(xiàn)彼此協(xié)作存在問題時(shí),說(shuō)明限界上下文的劃分出現(xiàn)了問題,也是識(shí)別限界上下文的一種驗(yàn)證方法。Eric Evans 將這種體現(xiàn)限界上下文協(xié)作方式的要素稱之為“上下文映射(Context Map)”,并給出了 9 種上下文映射關(guān)系:

Open Host Service 相當(dāng)于微服務(wù)之間的協(xié)作關(guān)系;防腐層(Anti-Corruption)是一種高度防御性的策略,結(jié)合門面(Facade)模式和適配器(Adapter)設(shè)計(jì)模式,將模型與其需要集成的其他模型隔離開來(lái),以防止被頻繁變更或不穩(wěn)定的依賴模型污染和腐敗。

架構(gòu)設(shè)計(jì)

“DDD 不需要特殊的架構(gòu),只要是能將技術(shù)問題與業(yè)務(wù)問題分離的架構(gòu)即可。” -- Eric Evans

傳統(tǒng)的三層架構(gòu)分而治之、降低耦合、提高復(fù)用,但存在弊端,業(yè)務(wù)邏輯在不同層泄露,導(dǎo)致替換某一層變得困難、難以對(duì)核心邏輯完整測(cè)試。領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)給出了 DDD 分層架構(gòu)、六邊形架構(gòu)、整潔架構(gòu)等分層架構(gòu),它們遵循“關(guān)注點(diǎn)分離”原則,旨在分離和隔離業(yè)務(wù)復(fù)雜度和技術(shù)復(fù)雜度,凸顯了領(lǐng)域模型,保證了領(lǐng)域模型的穩(wěn)定性和一致性。

DDD 分層架構(gòu)

DDD 分層架構(gòu)將屬于業(yè)務(wù)邏輯的關(guān)注點(diǎn)放到領(lǐng)域?qū)?Domain Layer)中,將支撐業(yè)務(wù)邏輯的技術(shù)實(shí)現(xiàn)放到基礎(chǔ)設(shè)施層(Infrastructure Layer)中,DDD 創(chuàng)新性地引入了應(yīng)用層(Application Layer),應(yīng)用層扮演了兩重角色。一作為業(yè)務(wù)邏輯的門面(Facade),暴露了能夠體現(xiàn)業(yè)務(wù)用例的應(yīng)用服務(wù)接口,又是業(yè)務(wù)邏輯與技術(shù)實(shí)現(xiàn)的粘合劑,實(shí)現(xiàn)二者之間的協(xié)作。下圖展現(xiàn)的是一個(gè)典型的領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)分層架構(gòu)。藍(lán)色區(qū)域和業(yè)務(wù)邏輯相關(guān),灰色區(qū)域與技術(shù)實(shí)現(xiàn)相關(guān),二者涇渭分明,然后匯合在應(yīng)用層。應(yīng)用層確定了業(yè)務(wù)邏輯與技術(shù)實(shí)現(xiàn)的邊界,通過直接依賴或者依賴注入(DI,Dependency Injection)的方式將二者結(jié)合起來(lái)。

我們?cè)敿?xì)介紹 DDD 分層架構(gòu)中每一層的用意和設(shè)計(jì):

表現(xiàn)層(User Interface Layer):負(fù)責(zé)向用戶顯示信息和解釋用戶命令,完成前端界面邏輯應(yīng)用層(Application Layer)很薄的一層,負(fù)責(zé)展現(xiàn)層與領(lǐng)域?qū)又g的協(xié)調(diào),不包含任何的業(yè)務(wù)邏輯和業(yè)務(wù)規(guī)則,也不保留業(yè)務(wù)對(duì)象的狀態(tài),是對(duì)領(lǐng)域服務(wù)的編排和轉(zhuǎn)發(fā)。應(yīng)用層扮演了兩重角色。一作為業(yè)務(wù)邏輯的門面(Facade),暴露了能夠體現(xiàn)業(yè)務(wù)用例的應(yīng)用服務(wù)接口,又是業(yè)務(wù)邏輯與技術(shù)實(shí)現(xiàn)的粘合劑,實(shí)現(xiàn)二者之間的協(xié)作。一個(gè) Application Service 代表一個(gè) Use Case,一個(gè) Use Case 代表了一個(gè)完整的業(yè)務(wù)場(chǎng)景,對(duì)于外部的客戶來(lái)說(shuō),應(yīng)用層是與客戶協(xié)作的應(yīng)用服務(wù),接口代表是業(yè)務(wù)的含義。

我們知道 DDD 分層架構(gòu)的主要目標(biāo)是分離業(yè)務(wù)復(fù)雜度與技術(shù)復(fù)雜度,應(yīng)用層扮演的就是這樣的分界線。從設(shè)計(jì)模式的角度來(lái)理解,應(yīng)用層的 Application Service 是一個(gè) Facade,對(duì)外部客戶,作為代表 Use Case 的整體應(yīng)用,對(duì)架構(gòu)內(nèi)部,它負(fù)責(zé)整合領(lǐng)域?qū)拥念I(lǐng)域邏輯與非業(yè)務(wù)相關(guān)的橫切關(guān)注點(diǎn)。

應(yīng)用中,存在與具體的業(yè)務(wù)邏輯無(wú)關(guān),在整個(gè)系統(tǒng)中會(huì)被諸多服務(wù)調(diào)用的橫切關(guān)注點(diǎn)實(shí)現(xiàn),他們?cè)诼氊?zé)上是內(nèi)聚的,散布在所有代碼層次中,包括異常處理、事務(wù)、監(jiān)控、日志、認(rèn)證和授權(quán)等。所以與橫切關(guān)注點(diǎn)協(xié)作的服務(wù)應(yīng)被定義為應(yīng)用服務(wù)。

領(lǐng)域?qū)?Domain Layer),是業(yè)務(wù)軟件的核心所在,也是軟件架構(gòu)的核心,包含了業(yè)務(wù)所涉及的領(lǐng)域?qū)ο?實(shí)體、值對(duì)象)、領(lǐng)域服務(wù),負(fù)責(zé)表達(dá)業(yè)務(wù)概念、業(yè)務(wù)狀態(tài)信息以及業(yè)務(wù)規(guī)則,具體表現(xiàn)形式就是領(lǐng)域模型。領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)提倡富領(lǐng)域模型,將業(yè)務(wù)邏輯歸屬到領(lǐng)域?qū)ο笊稀;A(chǔ)設(shè)施層(Infrastructure Layer):基礎(chǔ)層為各層提供通用的技術(shù)能力,包括:為應(yīng)用層傳遞消息、提供 API 管理,為領(lǐng)域?qū)犹峁?shù)據(jù)庫(kù)持久化機(jī)制等。它還能通過技術(shù)框架來(lái)支持各層之間的交互。

整潔架構(gòu)(Clean Architecture)

整潔架構(gòu)中,同心圓代表應(yīng)用軟件架構(gòu)的不同部分,也是一種以領(lǐng)域模型為中心的架構(gòu),從里到外依次是 Entities、Use Cases、Interface Adapters、Frameworks and Drivers。整潔架構(gòu)明確了各層的依賴關(guān)系,越往里,依賴越低,越抽象,外圓代碼依賴只能指向內(nèi)圓,內(nèi)圓不知道外圓的任何事情。

六邊形架構(gòu)(Hexagonal Architecture)

又稱為端口-適配器,六邊形架構(gòu)也是一種分層架構(gòu),不是從上下或左右分,而是從內(nèi)部和外部來(lái)分。六邊形架構(gòu)在領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)和微服務(wù)架構(gòu)設(shè)計(jì)中扮演了較重要的角色。六邊形架構(gòu)將系統(tǒng)分為內(nèi)部(內(nèi)部六邊形)和外部,內(nèi)部代表了應(yīng)用的業(yè)務(wù)邏輯,外部代表應(yīng)用的驅(qū)動(dòng)邏輯、基礎(chǔ)設(shè)施(諸如 REST,SOAP,NoSQL,SQL,Message Queue 等)或其他應(yīng)用,UI 層、DB 層、和各種中間件層實(shí)際上是沒有本質(zhì)上區(qū)別的,都只是數(shù)據(jù)的輸入和輸出。內(nèi)部通過端口和外部系統(tǒng)通信,端口代表了一定協(xié)議,以 API 呈現(xiàn)。

一個(gè)端口對(duì)應(yīng)多個(gè)適配器,對(duì)應(yīng)多個(gè)外部系統(tǒng),對(duì)這一類外部系統(tǒng)的歸納,不同的外部系統(tǒng)需要使用不同的適配器,適配器負(fù)責(zé)對(duì)協(xié)議進(jìn)行轉(zhuǎn)換。六邊形架構(gòu)有一個(gè)明確的關(guān)注點(diǎn),一開始就強(qiáng)調(diào)把重心放在業(yè)務(wù)邏輯上,外部的驅(qū)動(dòng)邏輯或被驅(qū)動(dòng)邏輯存在可變性、可替換性,依賴具體技術(shù)細(xì)節(jié)。而核心的業(yè)務(wù)領(lǐng)域相對(duì)穩(wěn)定,體現(xiàn)應(yīng)用的核心價(jià)值。六邊形的六并沒有實(shí)質(zhì)意義,只是為了留足夠的空間放置端口和適配器,一般端口數(shù)不會(huì)超過 4 個(gè)。適配器可以分為 2 類,“主”、“從”適配器,也可稱為“驅(qū)動(dòng)者”和“被驅(qū)動(dòng)者”。

代碼依賴只能使由外向內(nèi)。對(duì)于驅(qū)動(dòng)者適配器(也稱主適配器,Driving Adapter),就是外部依賴內(nèi)部的。但是對(duì)于被驅(qū)動(dòng)者適配器(也稱次適配器,Driven Adapter),實(shí)際是內(nèi)部依賴外部,這時(shí)需要使用依賴倒置,由驅(qū)動(dòng)者適配器將被驅(qū)動(dòng)者適配器注入到應(yīng)用內(nèi)部,這時(shí)端口的定義在應(yīng)用內(nèi)部,但是實(shí)現(xiàn)是由適配器實(shí)現(xiàn)。

CQRS(命令與查詢職責(zé)分離)

CQRS 使用分離的接口將數(shù)據(jù)查詢操作(Queries)和數(shù)據(jù)修改操作(Commands)分離開來(lái),這也意味著在查詢和更新過程中使用的數(shù)據(jù)模型也是不一樣的,這樣讀和寫邏輯就隔離開來(lái)了。使用 CQRS 分離了讀寫職責(zé)之后,可以對(duì)數(shù)據(jù)進(jìn)行讀寫分離操作來(lái)改進(jìn)性能,可擴(kuò)展性和安全。DDD 和 CQRS 結(jié)合,可以分別對(duì)讀和寫建模:

查詢模型是一種非規(guī)范化數(shù)據(jù)模型,不反映領(lǐng)域行為,只用于數(shù)據(jù)查詢和顯示。命令模型執(zhí)行領(lǐng)域行為,在領(lǐng)域行為執(zhí)行完成后通知查詢模型。如果查詢模型和領(lǐng)域模型共享數(shù)據(jù)源,則可以省略這一步;如果沒有共享數(shù)據(jù)源,可以借助于發(fā)布訂閱的消息模式通知到查詢模型,從而達(dá)到數(shù)據(jù)最終一致性。對(duì)于寫少讀多的共享類通用數(shù)據(jù)服務(wù)(如主數(shù)據(jù)類應(yīng)用)可以采用讀寫分離架構(gòu)模式。單數(shù)據(jù)中心寫入數(shù)據(jù),通過發(fā)布訂閱模式將數(shù)據(jù)副本分發(fā)到多數(shù)據(jù)中心。通過查詢模型微服務(wù),實(shí)現(xiàn)多數(shù)據(jù)中心數(shù)據(jù)共享和查詢。

通天塔從系統(tǒng)維度對(duì)數(shù)據(jù)庫(kù)進(jìn)行了讀寫分離,通天塔的 C 端應(yīng)用和服務(wù)大部分是讀場(chǎng)景,CMS 是多寫應(yīng)用,所以 CMS 的寫走主庫(kù),讀服務(wù)按照使用場(chǎng)景不同訪問不同的從庫(kù),實(shí)時(shí)請(qǐng)求、同步數(shù)據(jù)到集市、數(shù)據(jù)中心等,這點(diǎn)也從數(shù)據(jù)庫(kù)基礎(chǔ)架構(gòu)上保證了通天塔系統(tǒng)的低延時(shí)和穩(wěn)定。

綜述

六邊形架構(gòu)的內(nèi)部六邊形、DDD 分層架構(gòu)的領(lǐng)域?qū)雍蛻?yīng)用層、以及整潔架構(gòu) Use Cases 和 Entities 區(qū)域?qū)崿F(xiàn)了核心業(yè)務(wù)邏輯。但是核心業(yè)務(wù)邏輯又由兩部分來(lái)完成:應(yīng)用層和領(lǐng)域?qū)舆壿嫛nI(lǐng)域?qū)訉?shí)現(xiàn)了最核心的業(yè)務(wù)領(lǐng)域部分的邏輯,對(duì)外提供領(lǐng)域模型內(nèi)細(xì)粒度的領(lǐng)域服務(wù),應(yīng)用層依賴領(lǐng)域?qū)訕I(yè)務(wù)邏輯,通過服務(wù)組合和編排通過 API 網(wǎng)關(guān)向前臺(tái)應(yīng)用提供粗粒度的服務(wù)。業(yè)務(wù)需求變幻莫測(cè),但我們總能在這些變化找出一些規(guī)律,用戶體驗(yàn)、操作交互、以及業(yè)務(wù)流程的變化,往往只會(huì)導(dǎo)致 UI 層和流程的變化,總體來(lái)說(shuō),不管前端和外部如何變化,核心領(lǐng)域邏輯基本不會(huì)大變。把握好這個(gè)規(guī)律,我們就知道如何設(shè)計(jì)應(yīng)用層和領(lǐng)域?qū)?,如何進(jìn)行邏輯劃界了。架構(gòu)模型正是通過分層方式來(lái)控制需求變化對(duì)系統(tǒng)的影響,確保從外向里受的影響逐步減小。面向用戶端的展現(xiàn)層可以快速響應(yīng)外部需求進(jìn)行調(diào)整和發(fā)布,靈活多變;應(yīng)用層通過服務(wù)組合和編排實(shí)現(xiàn)業(yè)務(wù)流程的快速適配上線,以滿足不同的業(yè)務(wù)場(chǎng)景;領(lǐng)域?qū)邮墙?jīng)過抽象和提煉的業(yè)務(wù)原子單元,是非常穩(wěn)定的。這些架構(gòu)設(shè)計(jì)的好處是可以保證領(lǐng)域?qū)拥暮诵臉I(yè)務(wù)邏輯不會(huì)因?yàn)橥獠啃枨蠛土鞒痰淖儎?dòng)而調(diào)整,對(duì)于建立前臺(tái)靈活、中臺(tái)穩(wěn)固的架構(gòu)能力是很有好處的。下面是 Herberto Graca 的一張包含了六邊形、整潔、CQRS 等架構(gòu)的綜合圖,全面的說(shuō)明了這些架構(gòu)的設(shè)計(jì)要點(diǎn)和不同的出發(fā)點(diǎn)。

戰(zhàn)術(shù)設(shè)計(jì)

戰(zhàn)略設(shè)計(jì)為我們提供一種高層視角來(lái)審視我們的軟件系統(tǒng),而戰(zhàn)術(shù)設(shè)計(jì)則將戰(zhàn)略設(shè)計(jì)的成果具體化和細(xì)節(jié)化,它關(guān)注的是單個(gè)限界上下文內(nèi)部技術(shù)層面的實(shí)施。DDD 給我們提供了一整套技術(shù)工具集,包括實(shí)體、值對(duì)象、領(lǐng)域服務(wù)和資源庫(kù)等,如下:

行為飽滿的領(lǐng)域?qū)ο?/h3>

讓我們先看幾個(gè)概念:

  • 失血模型:是僅包含屬性的 getter/setter 方法的數(shù)據(jù)載體,沒有行為和動(dòng)作,業(yè)務(wù)邏輯由服務(wù)層完成。貧血模型:包括了屬性、getter/setter 方法,和不依賴于持久化的原子領(lǐng)域邏輯,依賴于持久層的業(yè)務(wù)邏輯將會(huì)放到服務(wù)層中。
  • 充血模型:包含了屬性、getter/setter 方法、大部分的業(yè)務(wù)邏輯,包括依賴于持久層的業(yè)務(wù)邏輯,所以使用充血模型的領(lǐng)域?qū)邮且蕾囉诔志脤樱?wù)層是很薄的一層,僅僅封裝事務(wù)和少量邏輯。
  • 脹血模型:取消了 Service 層,脹血模型就是把和業(yè)務(wù)邏輯不相關(guān)的其他應(yīng)用邏輯(如授權(quán)、事務(wù)等)都放到領(lǐng)域模型中。

脹血模型是顯而易見不可取的,這里不做過多討論。失血模型是絕大數(shù)企業(yè)開發(fā)應(yīng)用的模式,一些火熱的 ORM 工具比如 Hibernate,Entity Framework 實(shí)際上助長(zhǎng)了失血模型的擴(kuò)散,而且傳統(tǒng)三層架構(gòu)中的服務(wù)層,承受了太多的職責(zé),如事務(wù)管理、業(yè)務(wù)邏輯、權(quán)限檢查等,這違反了單一職責(zé)原則和關(guān)注分離原則,并且產(chǎn)生了大量的依賴和循環(huán)依賴,當(dāng)業(yè)務(wù)復(fù)雜度上升時(shí),服務(wù)層所包含的代碼將會(huì)非常龐大和復(fù)雜,直接導(dǎo)致了維護(hù)成本和測(cè)試成本的上升。同時(shí)也會(huì)導(dǎo)致業(yè)務(wù)邏輯、狀態(tài)會(huì)散落到在大量方法中,原本的代碼意圖會(huì)漸漸不明確,我們將這種情況稱為由失血癥引起的失憶癥,它會(huì)導(dǎo)致系統(tǒng)變得愈發(fā)復(fù)雜和難以維護(hù)。

采用領(lǐng)域模型的開發(fā)方式,將數(shù)據(jù)和業(yè)務(wù)邏輯封裝在一起,從服務(wù)層移動(dòng)到領(lǐng)域?qū)I(yè)務(wù)邏輯模型中,這樣服務(wù)層可以只負(fù)責(zé)應(yīng)用邏輯(事務(wù)、日志、認(rèn)證、監(jiān)控、編排等),領(lǐng)域模型可以專門負(fù)責(zé)其相關(guān)的業(yè)務(wù)邏輯,相關(guān)的業(yè)務(wù)分別內(nèi)聚到不同的領(lǐng)域模型中,與現(xiàn)實(shí)領(lǐng)域的業(yè)務(wù)對(duì)象映射,一些很有可能重復(fù)的業(yè)務(wù)代碼都會(huì)被集中到一處,降低重復(fù)代碼,提升業(yè)務(wù)邏輯的復(fù)用、可測(cè)試性和維護(hù)性。貧血模型和充血模型都是滿足數(shù)據(jù)+行為的,應(yīng)該采用哪種模式,大家這是一個(gè)爭(zhēng)論了曠日持久的問題,關(guān)注點(diǎn)還是在于領(lǐng)域模型是否要依賴持久層,我個(gè)人還是偏重于貧血模式,依賴持久層就意味著單元測(cè)試的展開要更加困難,而且領(lǐng)域?qū)ο蟮纳芷趹?yīng)該交給外部模型才更合理。

領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)元模型

實(shí)體(Entity)實(shí)體是一種具有唯一身份標(biāo)識(shí)的對(duì)象,具有持續(xù)的生命周期,除唯一標(biāo)識(shí)其他屬性是可變的。實(shí)體通過它的唯一標(biāo)識(shí)被區(qū)分。例如實(shí)體訂單 Order,標(biāo)識(shí)為 oderId,通天塔的活動(dòng)實(shí)體 Activity,標(biāo)識(shí)為 activityId。

值對(duì)象(Value Object)當(dāng)我們只關(guān)心一個(gè)模型元素的屬性時(shí),應(yīng)把它歸類為值對(duì)象。應(yīng)該使這個(gè)模型元素能夠表示出其屬性的意義,并為它提供相關(guān)功能。建議將值對(duì)象設(shè)計(jì)成一個(gè)不變(Immutable)對(duì)象,這樣就不需要擔(dān)心并發(fā)帶來(lái)的諸如同步、沖突等問題了,這既降低了編程的難度,又可以無(wú)需引入額外的同步鎖影響程序的性能。也不要為它分配任何標(biāo)識(shí),這樣應(yīng)用也無(wú)需去管理值對(duì)象的生命周期。值對(duì)象通過比較其屬性(equals)區(qū)分是否是相同值對(duì)象。應(yīng)該盡量使用值對(duì)象來(lái)建模而不是實(shí)體對(duì)象。在領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)中,提倡盡量定義值對(duì)象來(lái)替代基本類型,因?yàn)榛绢愋蜔o(wú)法體現(xiàn)統(tǒng)一語(yǔ)言中的領(lǐng)域概念。假設(shè)一個(gè)實(shí)體定義了許多屬性,這些屬性都是基本類型,就會(huì)導(dǎo)致與這些屬性相關(guān)的領(lǐng)域行為都要放到實(shí)體中,導(dǎo)致實(shí)體的職責(zé)變得不夠單一。引入值對(duì)象后情況就不同了,我們可以利用合理的職責(zé)分配,將這些職責(zé)(領(lǐng)域行為)按照內(nèi)聚性分配到各個(gè)值對(duì)象中,這個(gè)領(lǐng)域模型就能變得協(xié)作良好。值對(duì)象可以與其所在的實(shí)體對(duì)象保存在同一張表中,值對(duì)象的每一個(gè)屬性保存為一列;值對(duì)象也可以獨(dú)立于其所在的實(shí)體對(duì)象保存在另一張表中,值對(duì)象獲得委派主鍵,該主鍵對(duì)客戶端是不可見的。

聚合(Aggregate)聚合中所包含的對(duì)象之間具有密不可分的聯(lián)系,一個(gè)聚合中可以包含多個(gè)實(shí)體和值對(duì)象,因此聚合也被稱為根實(shí)體。聚合是持久化的基本單位,它和資源庫(kù)具有一一對(duì)應(yīng)的關(guān)系。在聚合中,根是唯一允許外部對(duì)象保持對(duì)它的引用的元素,而邊界內(nèi)部的對(duì)象之間則可以互相引用。除根以外的其他 Entity 都有本地表示,但這些標(biāo)識(shí)只有在聚合內(nèi)部才需要加以區(qū)別,因?yàn)橥獠繉?duì)象除了根 Entity 之外看不到其他對(duì)象。在一個(gè)聚合中直接引用另外一個(gè)聚合并不是 DDD 所鼓勵(lì)的,但是我們可以通過 ID 的方式引用另外的聚合,

聚合是一個(gè)事務(wù)的邊界。如果一次業(yè)務(wù)操作涉及到了對(duì)多個(gè)聚合狀態(tài)的更改,那么應(yīng)該采用發(fā)布領(lǐng)域事件(參考下文)的方式通知相應(yīng)的聚合。此時(shí)的數(shù)據(jù)一致性便從事務(wù)一致性變成了最終一致性(Eventual Consistency)。

領(lǐng)域服務(wù)(Domain Service)建模一個(gè)領(lǐng)域概念,把它放在實(shí)體上不合適,它放在值對(duì)象上也不合適,或者碰到跨聚合實(shí)例業(yè)務(wù)邏輯,沒辦法合理放到某個(gè)實(shí)體中的業(yè)務(wù)邏輯,領(lǐng)域服務(wù)就是應(yīng)對(duì)這些情況的服務(wù)。如果勉強(qiáng)地把這些重要的領(lǐng)域功能歸為 Entity 或 Value Object 的職責(zé),那么不是歪曲了基于模型的對(duì)象的定義,就是人為地增加了一些無(wú)意義的對(duì)象;領(lǐng)域服務(wù)和上文中提到的應(yīng)用服務(wù)是不同的,領(lǐng)域服務(wù)是領(lǐng)域模型的一部分,而應(yīng)用服務(wù)不是。應(yīng)用服務(wù)是領(lǐng)域服務(wù)的客戶,它將領(lǐng)域模型變成對(duì)外界可用的軟件系統(tǒng)。如果將太多的領(lǐng)域邏輯放在領(lǐng)域服務(wù)上,實(shí)體和值對(duì)象上的業(yè)務(wù)邏輯會(huì)越來(lái)越弱,將變成貧血對(duì)象。在分層架構(gòu)中要區(qū)分什么時(shí)候應(yīng)該定義領(lǐng)域服務(wù),什么時(shí)候應(yīng)該定義應(yīng)用服務(wù),一個(gè)根本的判斷依據(jù)是看需要封裝的職責(zé)是否與領(lǐng)域相關(guān)。

資源庫(kù)(Repository)資源庫(kù)用于保存和獲取聚合對(duì)象,將實(shí)際的存儲(chǔ)和查詢技術(shù)封裝起來(lái),對(duì)外隱藏封裝了數(shù)據(jù)訪問機(jī)制。只為那些確實(shí)需要直接訪問的聚合提供 Repository。讓客戶始終聚焦于模型,而將所有對(duì)象的存儲(chǔ)和訪問操作交給 Repository 來(lái)完成。資源庫(kù)與 DAO 有些相似,但也存在顯著區(qū)別,DAO 是比 Repository 更低的一層,同時(shí) DAO 只是對(duì)數(shù)據(jù)庫(kù)的一層很薄的封裝,而資源庫(kù)則更加具有領(lǐng)域特征,以“領(lǐng)域”為中心,所描述的是“領(lǐng)域語(yǔ)言”。另外,所有的實(shí)體都可以有相應(yīng)的 DAO,但并不是所有的實(shí)體都有資源庫(kù),只有聚合才有相應(yīng)的資源庫(kù)。

領(lǐng)域事件(Repository)在 Eric 的《領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)》中并沒有提到領(lǐng)域事件,領(lǐng)域事件是最近幾年才加入 DDD 生態(tài)系統(tǒng)的。在傳統(tǒng)的軟件系統(tǒng)中,對(duì)數(shù)據(jù)一致性的處理都是通過事務(wù)完成的,其中包括本地事務(wù)和全局事務(wù)。DDD 的一個(gè)重要原則便是一次事務(wù)只能更新一個(gè)聚合實(shí)例,但存在一個(gè)業(yè)務(wù)流程涉及修改多個(gè)聚合的事務(wù),怎么實(shí)現(xiàn)整個(gè)業(yè)務(wù)流程的數(shù)據(jù)一致性呢?在 DDD 中,領(lǐng)域事件便可以用于處理上述問題,此時(shí)最終一致性取代了事務(wù)一致性,通過領(lǐng)域事件的方式達(dá)到各個(gè)組件之間的數(shù)據(jù)一致性。既然是領(lǐng)域事件,他們便應(yīng)該從領(lǐng)域模型中發(fā)布,一個(gè)領(lǐng)域事件是指一個(gè)在領(lǐng)域中“有意義”的事件。領(lǐng)域事件的最終接收者可以是本限界上下文中的組件,也可以是另一個(gè)限界上下文。再進(jìn)一步發(fā)展,事件驅(qū)動(dòng)架構(gòu)可以演變成事件源(Event Sourcing),即對(duì)聚合的獲取并不是通過加載數(shù)據(jù)庫(kù)中的瞬時(shí)狀態(tài),而是通過重放發(fā)生在聚合生命周期中的所有領(lǐng)域事件完成。

工廠(Factories)當(dāng)創(chuàng)建一個(gè)對(duì)象或創(chuàng)建整個(gè)聚合時(shí),如果創(chuàng)建工作很復(fù)雜,或者暴露了過多的內(nèi)部結(jié)構(gòu),則可以使用 Factory 進(jìn)行封裝,應(yīng)該將創(chuàng)建復(fù)雜對(duì)象的實(shí)例和聚合的職責(zé)轉(zhuǎn)移到一個(gè)單獨(dú)的對(duì)象,這個(gè)對(duì)象本身在領(lǐng)域模型中可能沒有職責(zé),但它仍是領(lǐng)域設(shè)計(jì)的一部分。

模塊(Modules)可以從兩種維度來(lái)觀察模型,一是可以在 Module 中查看細(xì)節(jié),而不會(huì)被整個(gè)模型淹沒;二是觀察 Module 之間的關(guān)系,而不考慮其內(nèi)部細(xì)節(jié)。模塊之間應(yīng)該是低耦合的,而在模塊內(nèi)部則是高內(nèi)聚的。模塊并不僅僅是代碼的劃分,而且也是概念的劃分。找到一種低耦合的概念組織方式,從而可以相互獨(dú)立地理解和分析這些概念。對(duì)模型進(jìn)行精化,直到可以根據(jù)高層領(lǐng)域概念對(duì)模型進(jìn)行劃分,同時(shí)相應(yīng)的代碼也不會(huì)產(chǎn)生耦合。

模型關(guān)系:

對(duì)象概念

VO(View Object):視圖對(duì)象,用于展示層,它的作用是把某個(gè)指定頁(yè)面(或組件)的所有數(shù)據(jù)封裝起來(lái)。DTO(Data Transfer Object)

數(shù)據(jù)傳輸對(duì)象,分布式應(yīng)用提供粗粒度的數(shù)據(jù)實(shí)體,也是一種數(shù)據(jù)傳輸協(xié)議,以減少分布式調(diào)用的次數(shù),從而提高分布式調(diào)用的性能和降低網(wǎng)絡(luò)負(fù)載,這里泛指用于展示層與服務(wù)層之間的數(shù)據(jù)傳輸對(duì)象。RPC 對(duì)外暴露的服務(wù)涉及對(duì)象 API 就是 DTO,如 JSF(京東 RPC 框架)、Dubbo。對(duì)比 VO:絕大多數(shù)應(yīng)用場(chǎng)景下,VO 與 DTO 的屬性值基本一致,但對(duì)于設(shè)計(jì)層面來(lái)說(shuō),概念上還是存在區(qū)別,DTO 代表服務(wù)層需要接收的數(shù)據(jù)和返回的數(shù)據(jù),而 VO 代表展示層需要顯示的數(shù)據(jù)。

DO(Domain Object):領(lǐng)域?qū)ο螅褪菑默F(xiàn)實(shí)世界中抽象出來(lái)的有形或無(wú)形的業(yè)務(wù)實(shí)體。DO 不是簡(jiǎn)單的 POJO,它具有領(lǐng)域業(yè)務(wù)邏輯。PO(Persistent Object):持久化對(duì)象。

對(duì)比 DO:DO 和 PO 在絕大部分情況下是一一對(duì)應(yīng)的,但也存在區(qū)別,例如 DO 在某些場(chǎng)景下不需要進(jìn)行顯式的持久化,只駐留在靜態(tài)內(nèi)存。同樣 PO 也可以沒有對(duì)應(yīng)的 DO,比如一對(duì)多表關(guān)系在領(lǐng)域模型層面不需要單獨(dú)的領(lǐng)域?qū)ο蟆?/p>

下面是這些對(duì)象在系統(tǒng)架構(gòu)中的分布:

Domain Primitive

Domain Primitive 是一個(gè)在特定領(lǐng)域里,擁有精準(zhǔn)定義的、可自我驗(yàn)證的、擁有豐富行為和業(yè)務(wù)邏輯的 Value Object,DP 使用業(yè)務(wù)域中的原生語(yǔ)言,可以是業(yè)務(wù)域的最小組成部分、也可以構(gòu)建復(fù)雜組合。Domain Primitive 是 Value Object 的進(jìn)階版,在原始 VO 的基礎(chǔ)上要求每個(gè) DP 擁有概念的整體,而不僅僅是值對(duì)象。在 VO 的 Immutable 基礎(chǔ)上增加了 Validity 和行為。在項(xiàng)目中,散落在各個(gè)服務(wù)或工具類里面的代碼,都可以抽出來(lái)放在 DP 里,成為 DP 自己的行為或?qū)傩浴T瓌t是:所有抽離出來(lái)的方法要做到無(wú)狀態(tài),比如原來(lái)是 static 的方法。如果原來(lái)的方法有狀態(tài)變更,需要將改變狀態(tài)的部分和不改狀態(tài)的部分分離,然后將無(wú)狀態(tài)的部分融入 DP。因?yàn)?DP 也是一種 Object Value,本身不能帶狀態(tài),所以一切需要改變狀態(tài)的代碼都不屬于 DP 的范疇。Domain Primitive 涉及三種手段:

讓隱性的概念顯性化(Make Implicit Concepts Explicit)通天塔活動(dòng)類型就是一個(gè)簡(jiǎn)單的 int 類型,屬于隱式概念,但活動(dòng)類型包含了很多相關(guān)業(yè)務(wù)邏輯,比如類型名稱,不同類型活動(dòng)具有獨(dú)特的 Icon,判斷活動(dòng)類型是否是判斷等,我們把活動(dòng)類型顯性化,定義為一個(gè) Value Object。

讓隱性的上下文顯性化(Make Implicit Context Explicit)當(dāng)要實(shí)現(xiàn)一個(gè)功能或進(jìn)行邏輯判斷依賴多個(gè)概念時(shí),可以把這些概念封裝到一個(gè)獨(dú)立地完整概念,也是一種 Object Value:

封裝多對(duì)象行為(Encapsulate Multi-Object Behavior)常見推薦使用 Domain Primitive 的場(chǎng)景有:

  • 有格式要求的 String:比如 Name,PhoneNumber,OrderNumber,ZipCode,Address 等。
  • 限制的 Integer:比如 OrderId(>0),Percentage(0-100%),Quantity(>=0)等。
  • 可枚舉的 int:比如 Status(一般不用 Enum 因?yàn)榉葱蛄谢瘑栴})。
  • Double 或 BigDecimal:一般用到的 Double 或 BigDecimal 都是有業(yè)務(wù)含義的,比如 Temperature、Money、Amount、ExchangeRate、Rating 等。
  • 復(fù)雜的數(shù)據(jù)結(jié)構(gòu):比如 Map等,盡量能把 Map 的所有操作包裝掉,僅暴露必要行為,如通天塔的活動(dòng) Map 類。

接口變得清晰可讀,校驗(yàn)邏輯內(nèi)聚,在接口邊界外完成,無(wú)膠水代碼,業(yè)務(wù)邏輯清晰可讀,代碼變得更容易測(cè)試,也更安全。

最后

DDD 不是一套框架,而是一種面向復(fù)雜問題的建模方法論和實(shí)踐,所以在代碼層面缺乏了足夠的約束,導(dǎo)致 DDD 在實(shí)際應(yīng)用中上手門檻很高,甚至可以說(shuō)絕大部分人都對(duì) DDD 的理解有所偏差。

而且 DDD 諸多實(shí)踐在真正踐行時(shí)面臨很多挑戰(zhàn):

  • 首先是領(lǐng)域?qū)<液图夹g(shù)人員在建模過程中要摒棄自己固有的專業(yè)背景和思維定式,專注于問題域,基于統(tǒng)一語(yǔ)言緊密溝通和協(xié)作,具有深度業(yè)務(wù)領(lǐng)域理解和洞察的領(lǐng)域?qū)<液鸵粋€(gè)精通領(lǐng)域建模和架構(gòu)設(shè)計(jì)的技術(shù)團(tuán)隊(duì)一樣少見,都必須經(jīng)過長(zhǎng)時(shí)間學(xué)習(xí)和實(shí)踐的。
  • 其次技術(shù)人員必須轉(zhuǎn)變思維和架構(gòu)習(xí)慣,軟件系統(tǒng)最終交付的是業(yè)務(wù)價(jià)值,不是功能和技術(shù)方案,一切要以問題和業(yè)務(wù)為核心去建模和架構(gòu)。

通天塔后端團(tuán)隊(duì)在高并發(fā)和高性能應(yīng)用構(gòu)建方面有著非常豐富的經(jīng)驗(yàn),但在 DDD 實(shí)踐和享受到它的巨大價(jià)值層面我們還是剛起步,千里之行始于足下,我們正在邁出堅(jiān)實(shí)一步,后續(xù)我們也會(huì)出 DDD 通天塔實(shí)踐篇,講述我們的經(jīng)驗(yàn)和心得。

責(zé)任編輯:未麗燕 來(lái)源: Dockone.io
相關(guān)推薦

2021-09-08 09:22:23

領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)

2017-07-14 10:55:05

2020-09-02 08:12:05

CodeDDD代碼

2024-12-31 11:05:07

2023-01-09 09:00:00

樹服務(wù)架構(gòu)驅(qū)動(dòng)決策

2014-09-26 10:00:25

驅(qū)動(dòng)設(shè)計(jì)DDD領(lǐng)域

2024-11-27 15:33:17

軟件架構(gòu)DDD

2024-11-08 08:37:25

2023-02-15 13:50:58

DDD戰(zhàn)略設(shè)計(jì)

2022-07-17 07:37:29

微服務(wù)DDD工程化落地

2022-04-25 10:44:08

微服務(wù)架構(gòu)設(shè)計(jì)

2024-07-17 08:12:06

2022-12-29 18:07:25

DDD電話機(jī)器人

2024-09-25 08:00:00

領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)軟件開發(fā)

2023-08-29 07:53:17

領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)

2018-12-11 14:18:11

領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)ThoughtWork

2013-04-08 13:50:19

.NET系統(tǒng)架構(gòu)設(shè)計(jì)DDD

2023-03-31 11:38:01

平臺(tái)研發(fā)團(tuán)隊(duì)工程

2024-04-17 08:06:41

六邊形洋蔥架構(gòu)領(lǐng)域

2019-12-01 23:07:45

ThoughtWork領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)