18video性欧美19sex,欧美高清videosddfsexhd,性少妇videosexfreexxx片中国,激情五月激情综合五月看花,亚洲人成网77777色在线播放

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

2萬字帶你入門DDD

jf_ro2CN3Fa ? 來源:程序員鶴涵 ? 2023-06-15 10:10 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

DDD理論

微服務(wù)和DDD的淵源

軟件架構(gòu)模式的演進

fc37a67c-0b1c-11ee-962d-dac502259ad0.jpg

我們先來分析一下軟件架構(gòu)模式演進的三個階段。

第一階段是單機架構(gòu): 采用面向過程的設(shè)計方法,系統(tǒng)包括客戶端UI層和數(shù)據(jù)庫兩層,采用C/S架構(gòu)模式,整個系統(tǒng)圍繞數(shù)據(jù)庫驅(qū)動設(shè)計和開發(fā),并且總是從設(shè)計數(shù)據(jù)庫和字段開始。

第二階段是集中式架構(gòu): 采用面向?qū)ο蟮脑O(shè)計方法,系統(tǒng)包括業(yè)務(wù)接入層、業(yè)務(wù)邏輯層和數(shù)據(jù)庫層,采用經(jīng)典的三層架構(gòu),也有部分應(yīng)用采用傳統(tǒng)的SOA架構(gòu)。這種架構(gòu)容易使系統(tǒng)變得臃腫,可擴展性和彈性伸縮性差。

第三階段是分布式微服務(wù)架構(gòu): 隨著微服務(wù)架構(gòu)理念的提出,集中式架構(gòu)正向分布式微服務(wù)架構(gòu)演進。微服務(wù)架構(gòu)可以很好地實現(xiàn)應(yīng)用之間的解耦,解決單體應(yīng)用擴展性和彈性伸縮能力不足的問題。

在單機和集中式架構(gòu)時代,系統(tǒng)分析、設(shè)計和開發(fā)往往是獨立、分階段割裂進行的。

很容易導(dǎo)致需求、設(shè)計與代碼實現(xiàn)的不一致,往往到了軟件上線后,我們才發(fā)現(xiàn)很多功能并不是自己想要的,或者做出來的功能跟自己提出的需求偏差太大

微服務(wù)設(shè)計和拆分的困境

那進入微服務(wù)架構(gòu)時代以后,微服務(wù)確實也解決了原來采用集中式架構(gòu)的單體應(yīng)用的很多問題,比如擴展性、彈性伸縮能力、小規(guī)模團隊的敏捷開發(fā)等等。

微服務(wù)的粒度應(yīng)該多大呀?微服務(wù)到底應(yīng)該如何拆分和設(shè)計呢?微服務(wù)的邊界應(yīng)該在哪里?

2004年埃里克·埃文斯(Eric Evans)發(fā)表了《領(lǐng)域驅(qū)動設(shè)計》(Domain-Driven Design –Tackling Complexity in the Heart of Software)這本書,從此領(lǐng)域驅(qū)動設(shè)計(Domain Driven Design,簡稱DDD)誕生。DDD核心思想是通過領(lǐng)域驅(qū)動設(shè)計方法定義領(lǐng)域模型,從而確定業(yè)務(wù)和應(yīng)用邊界,保證業(yè)務(wù)模型與代碼模型的一致性。

但DDD提出后在軟件開發(fā)領(lǐng)域一直都是“雷聲大,雨點小”!直到Martin Fowler提出微服務(wù)架構(gòu),DDD才真正迎來了自己的時代。

利用DDD設(shè)計方法來建立領(lǐng)域模型,劃分領(lǐng)域邊界,再根據(jù)這些領(lǐng)域邊界從業(yè)務(wù)視角來劃分微服務(wù)邊界。而按照DDD方法設(shè)計出的微服務(wù)的業(yè)務(wù)和應(yīng)用邊界都非常合理,可以很好地實現(xiàn)微服務(wù)內(nèi)部和外部的“高內(nèi)聚、低耦合”。

現(xiàn)在,很多大型互聯(lián)網(wǎng)企業(yè)已經(jīng)將DDD設(shè)計方法作為微服務(wù)的主流設(shè)計方法了。DDD也開始真正火爆起來。

為什么DDD適合微服務(wù)

DDD是一種處理 高度復(fù)雜領(lǐng)域的設(shè)計思想,它試圖分離技術(shù)實現(xiàn)的復(fù)雜性,并圍繞業(yè)務(wù)概念構(gòu)建領(lǐng)域模型來控制業(yè)務(wù)的復(fù)雜性,以解決軟件難以理解,難以演進的問題。DDD不是架構(gòu),而是一種架構(gòu)設(shè)計方法論,它通過邊界劃分將復(fù)雜業(yè)務(wù)領(lǐng)域簡單化,幫我們設(shè)計出清晰的領(lǐng)域和應(yīng)用邊界,可以很容易地實現(xiàn)架構(gòu)演進。

DDD包括戰(zhàn)略設(shè)計和戰(zhàn)術(shù)設(shè)計兩部分。

戰(zhàn)略設(shè)計:主要從 業(yè)務(wù)視角出發(fā),建立業(yè)務(wù)領(lǐng)域模型,劃分領(lǐng)域邊界,建立通用語言的限界上下文,限界上下文可以作為微服務(wù)設(shè)計的參考邊界。

戰(zhàn)術(shù)設(shè)計:則從技術(shù)視角出發(fā),側(cè)重于領(lǐng)域模型的技術(shù)實現(xiàn),完成軟件開發(fā)和落地,包括:聚合根、實體、值對象、領(lǐng)域服務(wù)、應(yīng)用服務(wù)和資源庫等代碼邏輯的設(shè)計和實現(xiàn)。

我們不妨來看看DDD是如何進行戰(zhàn)略設(shè)計的。

DDD戰(zhàn)略設(shè)計會建立領(lǐng)域模型,領(lǐng)域模型可以用于指導(dǎo)微服務(wù)的設(shè)計和拆分。

事件風(fēng)暴 是建立領(lǐng)域模型的主要方法,它是一個從發(fā)散到收斂的過程。

它通常采用用例分析、場景分析和用戶旅程分析 ,盡可能全面不遺漏地分解業(yè)務(wù)領(lǐng)域,并梳理領(lǐng)域?qū)ο笾g的關(guān)系,這是一個發(fā)散的過程。事件風(fēng)暴過程會產(chǎn)生很多的實體、命令、事件等領(lǐng)域?qū)ο?,我們將這些領(lǐng)域?qū)ο髲牟煌木S度進行聚類,形成如聚合、限界上下文等邊界,建立領(lǐng)域模型,這就是一個收斂的過程。

fc52b5f2-0b1c-11ee-962d-dac502259ad0.jpg

我們可以用三步來劃定領(lǐng)域模型和微服務(wù)的邊界。

戰(zhàn)略設(shè)計主要包括三步:

通過事件風(fēng)暴梳理業(yè)務(wù)過程中的要素,確定領(lǐng)域?qū)嶓w等領(lǐng)域?qū)ο蟆?/p>

根據(jù)領(lǐng)域?qū)嶓w之間的業(yè)務(wù)關(guān)聯(lián)性,將業(yè)務(wù)緊密相關(guān)的實體組合形成聚合。

根據(jù)業(yè)務(wù)和語義邊界等因素,將一個或多個聚合劃定在一個限界上下文內(nèi),形成領(lǐng)域模型。

戰(zhàn)術(shù)設(shè)計的主要工作是將領(lǐng)域模型中的領(lǐng)域?qū)ο笈c代碼模型中的代碼對象建立映射關(guān)系,并調(diào)整業(yè)務(wù)架構(gòu)和領(lǐng)域模型以響應(yīng)業(yè)務(wù)變化。最終,將系統(tǒng)架構(gòu)與業(yè)務(wù)架構(gòu)綁定,建立新的映射關(guān)系。

DDD與微服務(wù)的關(guān)系

DDD主要關(guān)注:從業(yè)務(wù) 領(lǐng)域視角劃分領(lǐng)域邊界,構(gòu)建通用語言進行高效溝通,通過業(yè)務(wù)抽象,建立領(lǐng)域模型,維持業(yè)務(wù)和代碼的邏輯一致性。

微服務(wù)主要關(guān)注:運行時的進程間通信、容錯和故障隔離,實現(xiàn)去中心化數(shù)據(jù)管理和去中心化服務(wù)治理,關(guān)注微服務(wù)的獨立開發(fā)、測試、構(gòu)建和部署。

總體來說:

DDD是一套完整而系統(tǒng)的設(shè)計方法,它能帶給你從戰(zhàn)略設(shè)計到戰(zhàn)術(shù)設(shè)計的標準設(shè)計過程,使得你的設(shè)計思路能夠更加清晰,設(shè)計過程更加規(guī)范。

DDD善于處理與領(lǐng)域相關(guān)的擁有高復(fù)雜度業(yè)務(wù)的產(chǎn)品開發(fā),通過它可以建立一個核心而穩(wěn)定的領(lǐng)域模型,有利于領(lǐng)域知識的傳遞與傳承。

DDD強調(diào)團隊與領(lǐng)域?qū)<业暮献?,能夠幫助你的團隊建立一個溝通良好的氛圍,構(gòu)建一致的架構(gòu)體系。

DDD的設(shè)計思想、原則與模式有助于提高你的架構(gòu)設(shè)計能力。

無論是在新項目中設(shè)計微服務(wù),還是將系統(tǒng)從單體架構(gòu)演進到微服務(wù),都可以遵循DDD的架構(gòu)原則。

DDD不僅適用于微服務(wù),也適用于傳統(tǒng)的單體應(yīng)用 。

關(guān)鍵概念

領(lǐng)域和子域Domain

我們先看一下漢語詞典中對領(lǐng)域的解釋:“領(lǐng)域是從事一種專門活動或事業(yè)的范圍 、部類或部門?!卑俣劝倏茖︻I(lǐng)域的解釋:“領(lǐng)域具體指一種特定的范圍 或區(qū)域。”

領(lǐng)域就是用來確定范圍的,范圍即邊界 ,這也是DDD在設(shè)計中不斷強調(diào)邊界的原因。

既然領(lǐng)域是用來限定業(yè)務(wù)邊界和范圍的,那么就會有大小之分,領(lǐng)域越大,業(yè)務(wù)范圍就越大,反之則相反。

領(lǐng)域可以進一步劃分為子領(lǐng)域。我們把劃分出來的多個子領(lǐng)域稱為子域,每個子域?qū)?yīng)一個更小的問題域或更小的業(yè)務(wù)范圍

fc755e54-0b1c-11ee-962d-dac502259ad0.jpg

我們來看一下上面這張圖。這個例子是在講如何給桃樹建立一個完整的生物學(xué)知識體系。初中生物課其實早就告訴我們研究方法了。它的研究過程是這樣的。

第一步:確定研究對象,即研究領(lǐng)域 ,這里是一棵桃樹。

第二步:對研究對象進行細分,將桃樹細分為器官,器官又分為營養(yǎng)器官和生殖器官兩種。其中營養(yǎng)器官包括根、莖和葉,生殖器官包括花、果實和種子。桃樹的知識體系是我們已經(jīng)確定要研究的問題域,對應(yīng)DDD的領(lǐng)域。根、莖、葉、花、果實和種子等器官則是細分后的問題子域。這個過程就是DDD將領(lǐng)域細分為多個子域 的過程。

第三步:對器官進行細分,將器官細分為組織。比如,葉子器官可細分為保護組織、營養(yǎng)組織和輸導(dǎo)組織等。這個過程就是DDD將子域進一步細分為多個子域 的過程。

第四步:對組織進行細分,將組織細分為細胞,細胞成為我們研究的最小單元。細胞之間的細胞壁確定了單元的邊界,也確定了研究的最小邊界 。

第五步:細胞核、線粒體、細胞膜等物質(zhì)共同構(gòu)成細胞,這些物質(zhì)一起協(xié)作讓細胞具有這類細胞特定的生物功能。在這里你可以把細胞理解為DDD的聚合 ,細胞內(nèi)的這些物質(zhì)就可以理解為聚合里面的聚合根、實體以及值對象 等,在聚合內(nèi)這些實體一起協(xié)作完成特定的業(yè)務(wù)功能。這個過程類似DDD設(shè)計時,確定微服務(wù)內(nèi)功能要素和邊界的過程。

核心域,通用域和支撐域

在領(lǐng)域不斷劃分的過程中,領(lǐng)域會細分為不同的子域,子域可以根據(jù)自身重要性和功能屬性劃分為三類子域,它們分別是:核心域、通用域和支撐域。

決定產(chǎn)品和公司核心競爭力的子域是核心域 ,它是業(yè)務(wù)成功的主要因素和公司的核心競爭力。

沒有太多個性化的訴求,同時被多個子域使用的通用功能子域是通用域 。

還有一種功能子域是必需的,但既不包含決定產(chǎn)品和公司核心競爭力的功能,也不包含通用功能的子域,它就是支撐域

這三類子域相較之下,核心域是最重要的。

通用域和支撐域如果對應(yīng)到企業(yè)系統(tǒng),舉例來說的話,通用域則是你需要用到的通用系統(tǒng),比如認證、權(quán)限、短信等等,這類應(yīng)用很容易買到,沒有企業(yè)特點限制,不需要做太多的定制化。

而支撐域則具有企業(yè)特性,但不具有通用性,例如數(shù)據(jù)代碼類的數(shù)據(jù)字典,站內(nèi)信等系統(tǒng)。

那為什么要劃分核心域、通用域和支撐域,主要目的是什么呢?

要事為先

公司在IT系統(tǒng)建設(shè)過程中,由于預(yù)算和資源有限,對不同類型的子域應(yīng)有不同的關(guān)注度和資源投入策略,記住好鋼要用在刀刃上。

很多公司的業(yè)務(wù),表面看上去相似,但商業(yè)模式和戰(zhàn)略方向是存在很大差異的,因此公司的關(guān)注點會不一樣,在劃分核心域、通用域和支撐域時,其結(jié)果也會出現(xiàn)非常大的差異。

比如同樣都是電商平臺的淘寶、天貓、京東和蘇寧易購,他們的商業(yè)模式是不同的。淘寶是C2C網(wǎng)站,個人賣家對個人買家,而天貓、京東和蘇寧易購則是B2C網(wǎng)站,是公司賣家對個人買家。即便是蘇寧易購與京東都是B2C的模式,他們的商業(yè)模式也是不一樣的,蘇寧易購是典型的傳統(tǒng)線下賣場轉(zhuǎn)型成為電商,京東則是直營加部分平臺模式。

商業(yè)模式的不同會導(dǎo)致核心域劃分結(jié)果的不同。有的公司核心域可能在客戶服務(wù),有的可能在產(chǎn)品質(zhì)量,有的可能在物流 。在公司領(lǐng)域細分、建立領(lǐng)域模型和系統(tǒng)建設(shè)時,我們就要結(jié)合公司戰(zhàn)略重點和商業(yè)模式,找到核心域了,且重點關(guān)注核心域。

通用語言

在事件風(fēng)暴過程中,通過團隊交流達成共識的,能夠簡單、清晰、準確描述業(yè)務(wù)涵義和規(guī)則的語言就是通用語言。也就是說,通用語言是團隊統(tǒng)一的語言 ,不管你在團隊中承擔什么角色,在同一個領(lǐng)域的軟件生命周期里都使用統(tǒng)一的語言進行交流。

通用語言的價值也就很明了了,它可以解決交流障礙這個問題 ,使領(lǐng)域?qū)<液烷_發(fā)人員能夠協(xié)同合作,從而確保業(yè)務(wù)需求的正確表達。

但是,對這個概念的理解,到這里還不夠。

通用語言包含術(shù)語和用例場景 ,并且能夠直接反映在代碼中。通用語言中的名詞可以給領(lǐng)域?qū)ο竺?/strong> ,如商品、訂單等,對應(yīng)實體對象;而動詞則表示一個動作或事件 ,如商品已下單、訂單已付款等,對應(yīng)領(lǐng)域事件或者命令。

通用語言貫穿DDD的整個設(shè)計過程。作為項目團隊溝通和協(xié)商形成的統(tǒng)一語言,基于它,你就能夠開發(fā)出可讀性更好的代碼,將業(yè)務(wù)需求準確轉(zhuǎn)化為代碼設(shè)計。

這張圖描述了從事件風(fēng)暴建立通用語言到領(lǐng)域?qū)ο笤O(shè)計和代碼落地的完整過程。

簡單來說,通用語言確定了項目團隊內(nèi)部交流的統(tǒng)一語言,而這個語言所在的語義環(huán)境則是由限界上下文來限定的,以確保語義的唯一性。

限界上下文BoundedContext

我們可以將限界上下文拆解為兩個詞:限界和上下文。限界就是領(lǐng)域的邊界,而上下文則是語義環(huán)境 。通過領(lǐng)域的限界上下文,我們就可以在統(tǒng)一的領(lǐng)域邊界內(nèi)用統(tǒng)一的語言進行交流。

綜合一下,我認為限界上下文的定義就是:用來封裝通用語言和領(lǐng)域?qū)ο?,提供上下文環(huán)境,保證在領(lǐng)域之內(nèi)的一些術(shù)語、業(yè)務(wù)相關(guān)對象等(通用語言)有一個確切的含義,沒有二義性。這個邊界定義了模型的適用范圍,使團隊所有成員能夠明確地知道什么應(yīng)該在模型中實現(xiàn),什么不應(yīng)該在模型中實現(xiàn)。

領(lǐng)域?qū)<?、架?gòu)師和開發(fā)人員的主要工作就是通過事件風(fēng)暴來劃分限界上下文。限界上下文確定了微服務(wù)的設(shè)計和拆分方向,是微服務(wù)設(shè)計和拆分的主要依據(jù)。如果不考慮技術(shù)異構(gòu)、團隊溝通等其它外部因素,一個限界上下文理論上就可以設(shè)計為一個微服務(wù)。

實體Entity

我們先來看一下實體是什么東西?

在DDD中有這樣一類對象,它們擁有唯一標識符,且標識符在歷經(jīng)各種狀態(tài)變更后仍能保持一致 。對這些對象而言,重要的不是其屬性,而是其延續(xù)性和標識,對象的延續(xù)性和標識會跨越甚至超出軟件的生命周期。我們把這樣的對象稱為實體。

1. 實體的業(yè)務(wù)形態(tài)

在DDD不同的設(shè)計過程中,實體的形態(tài)是不同的。在戰(zhàn)略設(shè)計時,實體是領(lǐng)域模型的一個重要對象。領(lǐng)域模型中的實體是多個屬性、操作或行為的載體。在事件風(fēng)暴中,我們可以根據(jù)命令、操作或者事件,找出產(chǎn)生這些行為的業(yè)務(wù)實體對象,進而按照一定的業(yè)務(wù)規(guī)則將依存度高和業(yè)務(wù)關(guān)聯(lián)緊密的多個實體對象和值對象進行聚類,形成聚合。你可以這么理解,實體和值對象是組成領(lǐng)域模型的基礎(chǔ)單元。

2. 實體的代碼形態(tài)

在代碼模型中,實體的表現(xiàn)形式是實體類,這個類包含了實體的屬性和方法,通過這些方法實現(xiàn)實體自身的業(yè)務(wù)邏輯。在DDD里,這些實體類通常采用充血模型 ,與這個實體相關(guān)的所有業(yè)務(wù)邏輯都在實體類的方法中實現(xiàn),跨多個實體的領(lǐng)域邏輯則在領(lǐng)域服務(wù)中實現(xiàn)

3. 實體的運行形態(tài)

實體以DO(領(lǐng)域?qū)ο螅┑男问酱嬖冢?strong>每個實體對象都有唯一的ID 。我們可以對一個實體對象進行多次修改,修改后的數(shù)據(jù)和原來的數(shù)據(jù)可能會大不相同。但是,由于它們擁有相同的ID,它們依然是同一個實體。比如商品是商品上下文的一個實體,通過唯一的商品ID來標識,不管這個商品的數(shù)據(jù)如何變化,商品的ID一直保持不變,它始終是同一個商品。

4. 實體的數(shù)據(jù)庫形態(tài)

與傳統(tǒng)數(shù)據(jù)模型設(shè)計優(yōu)先不同,DDD是先構(gòu)建領(lǐng)域模型 ,針對實際業(yè)務(wù)場景構(gòu)建實體對象和行為,再將實體對象映射到數(shù)據(jù)持久化對象。

在領(lǐng)域模型映射到數(shù)據(jù)模型時,一個實體可能對應(yīng)0個、1個或者多個數(shù)據(jù)庫持久化對象。大多數(shù)情況下實體與持久化對象是一對一 。在某些場景中,有些實體只是暫駐靜態(tài)內(nèi)存的一個運行態(tài)實體,它不需要持久化。比如,基于多個價格配置數(shù)據(jù)計算后生成的折扣實體。

而在有些復(fù)雜場景下,實體與持久化對象則可能是一對多或者多對一的關(guān)系。比如,用戶user與角色role兩個持久化對象可生成權(quán)限實體,一個實體對應(yīng)兩個持久化對象,這是一對多的場景。再比如,有些場景為了避免數(shù)據(jù)庫的聯(lián)表查詢,提升系統(tǒng)性能,會將客戶信息customer和賬戶信息account兩類數(shù)據(jù)保存到同一張數(shù)據(jù)庫表中,客戶和賬戶兩個實體可根據(jù)需要從一個持久化對象中生成,這就是多對一的場景。

值對象ValueObject

《實現(xiàn)領(lǐng)域驅(qū)動設(shè)計》一書中對值對象的定義:通過對象屬性值來識別的對象,它將多個相關(guān)屬性組合為一個概念整體。在DDD中用來描述領(lǐng)域的特定方面,并且是一個沒有標識符的對象,叫作值對象。

值對象描述了領(lǐng)域中的一件東西,這個東西是不可變的 ,它將不同的相關(guān)屬性組合成了一個概念整體。當度量和描述改變時,可以用另外一個值對象予以替換。它可以和其它值對象進行相等性比較,且不會對協(xié)作對象造成副作用。這部分在后面講“值對象的運行形態(tài)”時還會有例子。

簡單來說就是一堆不可變的屬性的集合,為了避免屬性的零碎

fc88a09a-0b1c-11ee-962d-dac502259ad0.jpg

人員實體原本包括:姓名、年齡、性別以及人員所在的省、市、縣和街道等屬性。這樣顯示地址相關(guān)的屬性就很零碎了對不對?現(xiàn)在,我們可以將“省、市、縣和街道等屬性”拿出來構(gòu)成一個“地址屬性集合”,這個集合就是值對象了。

1. 值對象的業(yè)務(wù)形態(tài)

值對象是DDD領(lǐng)域模型中的一個基礎(chǔ)對象,它跟實體一樣都來源于事件風(fēng)暴所構(gòu)建的領(lǐng)域模型,都包含了若干個屬性,它與實體一起構(gòu)成聚合。

我們不妨對照實體,來看值對象的業(yè)務(wù)形態(tài),這樣更好理解。本質(zhì)上,實體是看得到、摸得著的實實在在的業(yè)務(wù)對象,實體具有業(yè)務(wù)屬性、業(yè)務(wù)行為和業(yè)務(wù)邏輯。而值對象只是若干個屬性的集合 ,只有數(shù)據(jù)初始化操作和有限的不涉及修改數(shù)據(jù)的行為,基本不包含業(yè)務(wù)邏輯。值對象的屬性集雖然在物理上獨立出來了,但在邏輯上它仍然是實體屬性的一部分,用于描述實體的特征。

在值對象中也有部分共享的標準類型的值對象,它們有自己的限界上下文,有自己的持久化對象,可以建立共享的數(shù)據(jù)類微服務(wù),比如數(shù)據(jù)字典。

2. 值對象的代碼形態(tài)

值對象在代碼中有這樣兩種形態(tài)。如果值對象是單一屬性,則直接定義為實體類的屬性;如果值對象是屬性集合,則把它設(shè)計為Class類 ,Class將具有整體概念的多個屬性歸集到屬性集合,這樣的值對象沒有ID,會被實體整體引用。

我們看一下下面這段代碼,person這個實體有若干個單一屬性的值對象,比如Id、name等屬性;同時它也包含多個屬性的值對象,比如地址address。

fca0e5e2-0b1c-11ee-962d-dac502259ad0.jpg

3. 值對象的運行形態(tài)

實體實例化后的DO對象的業(yè)務(wù)屬性和業(yè)務(wù)行為非常豐富,但值對象實例化的對象則相對簡單和乏味。除了值對象數(shù)據(jù)初始化和整體替換的行為外,其它業(yè)務(wù)行為就很少了。

值對象嵌入到實體的話,有這樣兩種不同的數(shù)據(jù)格式,也可以說是兩種方式,分別是屬性嵌入的方式和序列化大對象的方式。

引用單一屬性的值對象或只有一條記錄的多屬性值對象的實體,可以采用屬性嵌入的方式嵌入。引用一條或多條記錄的多屬性值對象的實體,可以采用序列化大對象的方式嵌入。比如,人員實體可以有多個通訊地址,多個地址序列化后可以嵌入人員的地址屬性。值對象創(chuàng)建后就不允許修改了,只能用另外一個值對象來整體替換。

案例1:以屬性嵌入的方式形成的人員實體對象,地址值對象直接以屬性值嵌入人員實體中。

fcc6e738-0b1c-11ee-962d-dac502259ad0.jpg

案例2:以序列化大對象的方式形成的人員實體對象,地址值對象被序列化成大對象Json串后,嵌入人員實體中。

fcd51718-0b1c-11ee-962d-dac502259ad0.jpg

4. 值對象的數(shù)據(jù)庫形態(tài)

DDD引入值對象是希望實現(xiàn)從“數(shù)據(jù)建模為中心”向“領(lǐng)域建模為中心”轉(zhuǎn)變,減少數(shù)據(jù)庫表的數(shù)量和表與表之間復(fù)雜的依賴關(guān)系,盡可能地簡化數(shù)據(jù)庫設(shè)計,提升數(shù)據(jù)庫性能。

如何理解用值對象來簡化數(shù)據(jù)庫設(shè)計呢?

傳統(tǒng)的數(shù)據(jù)建模大多是根據(jù)數(shù)據(jù)庫范式設(shè)計的,每一個數(shù)據(jù)庫表對應(yīng)一個實體,每一個實體的屬性值用單獨的一列來存儲,一個實體主表會對應(yīng)N個實體從表。而值對象在數(shù)據(jù)庫持久化方面簡化了設(shè)計,它的數(shù)據(jù)庫設(shè)計大多采用非數(shù)據(jù)庫范式,值對象的屬性值和實體對象的屬性值保存在同一個數(shù)據(jù)庫實體表中 。

舉個例子,還是基于上述人員和地址那個場景,實體和數(shù)據(jù)模型設(shè)計通常有兩種解決方案:

第一是把地址值對象的所有屬性都放到人員實體表中,創(chuàng)建人員實體,創(chuàng)建人員數(shù)據(jù)表;

第二是創(chuàng)建人員和地址兩個實體,同時創(chuàng)建人員和地址兩張表。

第一個方案會破壞地址的業(yè)務(wù)涵義和概念完整性,第二個方案增加了不必要的實體和表,需要處理多個實體和表的關(guān)系,從而增加了數(shù)據(jù)庫設(shè)計的復(fù)雜性。

那到底應(yīng)該怎樣設(shè)計,才能讓業(yè)務(wù)含義清楚,同時又不讓數(shù)據(jù)庫變得復(fù)雜呢?

在領(lǐng)域建模時,我們可以將部分對象設(shè)計為值對象,保留對象的業(yè)務(wù)涵義,同時又減少了實體的數(shù)量;在數(shù)據(jù)建模時,我們可以將值對象嵌入實體,減少實體表的數(shù)量,簡化數(shù)據(jù)庫設(shè)計。

要想發(fā)揮對象的威力,就需要優(yōu)先做領(lǐng)域建模,弱化數(shù)據(jù)庫的作用,只把數(shù)據(jù)庫作為一個保存數(shù)據(jù)的倉庫即可 。即使違反數(shù)據(jù)庫設(shè)計原則,也不用大驚小怪,只要業(yè)務(wù)能夠順利運行,就沒什么關(guān)系。

聚合根AggregateRoot

聚合根的主要目的是為了避免由于復(fù)雜數(shù)據(jù)模型缺少統(tǒng)一的業(yè)務(wù)規(guī)則控制,而導(dǎo)致聚合、實體之間數(shù)據(jù)不一致性的問題。

如果把聚合比作組織,那聚合根就是這個組織的負責人。聚合根也稱為根實體,它不僅是實體,還是聚合的管理者。

首先它作為實體本身,擁有實體的屬性和業(yè)務(wù)行為,實現(xiàn)自身的業(yè)務(wù)邏輯。

其次它作為聚合的管理者,在聚合內(nèi)部負責協(xié)調(diào)實體和值對象按照固定的業(yè)務(wù)規(guī)則協(xié)同完成共同的業(yè)務(wù)邏輯。

最后在聚合之間,它還是聚合對外的接口人,以聚合根ID關(guān)聯(lián)的方式接受外部任務(wù)和請求,在上下文內(nèi)實現(xiàn)聚合之間的業(yè)務(wù)協(xié)同。也就是說,聚合之間通過聚合根ID關(guān)聯(lián)引用,如果需要訪問其它聚合的實體,就要先訪問聚合根,再導(dǎo)航到聚合內(nèi)部實體,外部對象不能直接訪問聚合內(nèi)實體。

聚合Aggregate

在DDD中,實體和值對象是很基礎(chǔ)的領(lǐng)域?qū)ο?。實體一般對應(yīng)業(yè)務(wù)對象,它具有業(yè)務(wù)屬性和業(yè)務(wù)行為;而值對象主要是屬性集合,對實體的狀態(tài)和特征進行描述。但實體和值對象都只是個體化的對象,它們的行為表現(xiàn)出來的是個體的能力。

舉個例子。社會是由一個個的個體組成的,象征著我們每一個人。隨著社會的發(fā)展,慢慢出現(xiàn)了社團、機構(gòu)、部門等組織,我們開始從個人變成了組織的一員,大家可以協(xié)同一致的工作,朝著一個最大的目標前進,發(fā)揮出更大的力量。

領(lǐng)域模型內(nèi)的實體和值對象就好比個體,而能讓實體和值對象協(xié)同工作的組織就是聚合,它用來確保這些領(lǐng)域?qū)ο笤趯崿F(xiàn)共同的業(yè)務(wù)邏輯時,能保證數(shù)據(jù)的一致性。

聚合就是由業(yè)務(wù)和邏輯緊密關(guān)聯(lián)的實體和值對象組合而成的 ,聚合是數(shù)據(jù)修改和持久化的基本單元,每一個聚合對應(yīng)一個倉儲,實現(xiàn)數(shù)據(jù)的持久化。

聚合有一個聚合根和上下文邊界,這個邊界根據(jù)業(yè)務(wù)單一職責和高內(nèi)聚原則,定義了聚合內(nèi)部應(yīng)該包含哪些實體和值對象,而聚合之間的邊界是松耦合的。按照這種方式設(shè)計出來的微服務(wù)很自然就是“高內(nèi)聚、低耦合”的。

聚合在DDD分層架構(gòu)里屬于領(lǐng)域?qū)樱I(lǐng)域?qū)影硕鄠€聚合,共同實現(xiàn)核心業(yè)務(wù)邏輯。聚合內(nèi)實體以充血模型實現(xiàn)個體業(yè)務(wù)能力,以及業(yè)務(wù)邏輯的高內(nèi)聚 ??缍鄠€實體的業(yè)務(wù)邏輯通過領(lǐng)域服務(wù)來實現(xiàn),跨多個聚合的業(yè)務(wù)邏輯通過應(yīng)用服務(wù)來實現(xiàn)。比如有的業(yè)務(wù)場景需要同一個聚合的A和B兩個實體來共同完成,我們就可以將這段業(yè)務(wù)邏輯用領(lǐng)域服務(wù)來實現(xiàn);而有的業(yè)務(wù)邏輯需要聚合C和聚合D中的兩個服務(wù)共同完成,這時你就可以用應(yīng)用服務(wù)來組合這兩個服務(wù)。

怎樣設(shè)計聚合?

DDD領(lǐng)域建模通常采用事件風(fēng)暴,它通常采用用例分析、場景分析和用戶旅程 分析等方法,通過頭腦風(fēng)暴列出所有可能的業(yè)務(wù)行為和事件,然后找出產(chǎn)生這些行為的領(lǐng)域?qū)ο?,并梳理領(lǐng)域?qū)ο笾g的關(guān)系,找出聚合根,找出與聚合根業(yè)務(wù)緊密關(guān)聯(lián)的實體和值對象,再將聚合根、實體和值對象組合,構(gòu)建聚合。

下面我們以保險的投保業(yè)務(wù)場景為例,看一下聚合的構(gòu)建過程主要都包括哪些步驟。

fcec5d4c-0b1c-11ee-962d-dac502259ad0.png

第 1 步: 采用事件風(fēng)暴,根據(jù)業(yè)務(wù)行為,梳理出在投保過程中發(fā)生這些行為的所有的實體和值對象 ,比如投保單、標的、客戶、被保人等等。

第 2 步: 從眾多實體中選出適合作為對象管理者的根實體,也就是聚合根。判斷一個實體是否是聚合根,你可以結(jié)合以下場景分析:是否有獨立的生命周期?是否有全局唯一ID?是否可以創(chuàng)建或修改其它對象?是否有專門的模塊來管這個實體。圖中的聚合根分別是投保單和客戶實體。

第 3 步: 根據(jù)業(yè)務(wù)單一職責和高內(nèi)聚原則,找出與聚合根關(guān)聯(lián)的所有緊密依賴的實體和值對象。構(gòu)建出 1 個包含聚合根(唯一)、多個實體和值對象的對象集合,這個集合就是聚合。在圖中我們構(gòu)建了客戶和投保這兩個聚合。

第 4 步: 在聚合內(nèi)根據(jù)聚合根、實體和值對象的依賴關(guān)系,畫出對象的引用和依賴模型。這里我需要說明一下:投保人和被保人的數(shù)據(jù),是通過關(guān)聯(lián)客戶ID從客戶聚合中獲取的,在投保聚合里它們是投保單的值對象,這些值對象的數(shù)據(jù)是客戶的冗余數(shù)據(jù),即使未來客戶聚合的數(shù)據(jù)發(fā)生了變更,也不會影響投保單的值對象數(shù)據(jù)。從圖中我們還可以看出實體之間的引用關(guān)系,比如在投保聚合里投保單聚合根引用了報價單實體,報價單實體則引用了報價規(guī)則子實體。

第 5 步: 多個聚合根據(jù)業(yè)務(wù)語義和上下文一起劃分到同一個限界上下文內(nèi)。

這就是一個聚合誕生的完整過程了。

聚合的一些設(shè)計原則

《實現(xiàn)領(lǐng)域驅(qū)動設(shè)計》一書中對聚合設(shè)計原則的描述

1. 在一致性邊界內(nèi)建模真正的不變條件。 聚合用來封裝真正的不變性,而不是簡單地將對象組合在一起。聚合內(nèi)有一套不變的業(yè)務(wù)規(guī)則,各實體和值對象按照統(tǒng)一的業(yè)務(wù)規(guī)則運行,實現(xiàn)對象數(shù)據(jù)的一致性,邊界之外的任何東西都與該聚合無關(guān),這就是聚合能實現(xiàn)業(yè)務(wù)高內(nèi)聚的原因。

2. 設(shè)計小聚合。 如果聚合設(shè)計得過大,聚合會因為包含過多的實體,導(dǎo)致實體之間的管理過于復(fù)雜,高頻操作時會出現(xiàn)并發(fā)沖突或者數(shù)據(jù)庫鎖,最終導(dǎo)致系統(tǒng)可用性變差。而小聚合設(shè)計則可以降低由于業(yè)務(wù)過大導(dǎo)致聚合重構(gòu)的可能性,讓領(lǐng)域模型更能適應(yīng)業(yè)務(wù)的變化。

3. 通過唯一標識引用其它聚合。 聚合之間是通過關(guān)聯(lián)外部聚合根ID的方式引用,而不是直接對象引用的方式。外部聚合的對象放在聚合邊界內(nèi)管理,容易導(dǎo)致聚合的邊界不清晰,也會增加聚合之間的耦合度。

4. 在邊界之外使用最終一致性。 聚合內(nèi)數(shù)據(jù)強一致性,而聚合之間數(shù)據(jù)最終一致性。在一次事務(wù)中,最多只能更改一個聚合的狀態(tài)。如果一次業(yè)務(wù)操作涉及多個聚合狀態(tài)的更改,應(yīng)采用領(lǐng)域事件的方式異步修改相關(guān)的聚合,實現(xiàn)聚合之間的解耦。

5. 通過應(yīng)用層實現(xiàn)跨聚合的服務(wù)調(diào)用。 為實現(xiàn)微服務(wù)內(nèi)聚合之間的解耦,以及未來以聚合為單位的微服務(wù)組合和拆分,應(yīng)避免跨聚合的領(lǐng)域服務(wù)調(diào)用和跨聚合的數(shù)據(jù)庫表關(guān)聯(lián)。

原則需要消化吸收后靈活運用到自己的系統(tǒng)中才能產(chǎn)生威力

領(lǐng)域事件

領(lǐng)域事件是領(lǐng)域模型中非常重要的一部分,用來表示領(lǐng)域中發(fā)生的事件。一個領(lǐng)域事件將導(dǎo)致進一步的業(yè)務(wù)操作,在實現(xiàn)業(yè)務(wù)解耦的同時,還有助于形成完整的業(yè)務(wù)閉環(huán)。

舉例來說的話

領(lǐng)域事件可以是業(yè)務(wù)流程的一個步驟,比如投保業(yè)務(wù)繳費完成后,觸發(fā)投保單轉(zhuǎn)保單的動作;

也可能是定時批處理過程中發(fā)生的事件,比如批處理生成季繳保費通知單,觸發(fā)發(fā)送繳費郵件通知操作;

或者一個事件發(fā)生后觸發(fā)的后續(xù)動作,比如密碼連續(xù)輸錯三次,觸發(fā)鎖定賬戶的動作。

那如何識別領(lǐng)域事件呢?

很簡單,和剛才講的定義是強關(guān)聯(lián)的。在做用戶旅程或者場景分析時,我們要捕捉業(yè)務(wù)、需求人員或領(lǐng)域?qū)<铱谥械年P(guān)鍵詞:“如果發(fā)生……,則……”“當做完……的時候,請通知……”“發(fā)生……時,則……”等。在這些場景中,如果發(fā)生某種事件后,會觸發(fā)進一步的操作,那么這個事件很可能就是領(lǐng)域事件 。

領(lǐng)域事件總體架構(gòu)

領(lǐng)域事件的執(zhí)行需要一系列的組件和技術(shù)來支撐。

領(lǐng)域事件處理包括:事件構(gòu)建和發(fā)布、事件數(shù)據(jù)持久化、事件總線、消息中間件、事件接收和處理等。下面我們逐一講一下。

fd1f1174-0b1c-11ee-962d-dac502259ad0.jpg

1. 事件構(gòu)建和發(fā)布

事件基本屬性至少包括:事件唯一標識、發(fā)生時間、事件類型和事件源 ,其中事件唯一標識應(yīng)該是全局唯一的,以便事件能夠無歧義地在多個限界上下文中傳遞。事件基本屬性主要記錄事件自身以及事件發(fā)生背景的數(shù)據(jù)。

另外事件中還有一項更重要,那就是業(yè)務(wù)屬性,用于記錄事件發(fā)生那一刻的業(yè)務(wù)數(shù)據(jù),這些數(shù)據(jù)會隨事件傳輸?shù)接嗛喎?,以開展下一步的業(yè)務(wù)操作。

事件基本屬性和業(yè)務(wù)屬性一起構(gòu)成事件實體,事件實體依賴聚合根。領(lǐng)域事件發(fā)生后,事件中的業(yè)務(wù)數(shù)據(jù)不再修改,因此業(yè)務(wù)數(shù)據(jù)可以以序列化值對象的形式保存,這種存儲格式在消息中間件中也比較容易解析和獲取。

為了保證事件結(jié)構(gòu)的統(tǒng)一,我們還會創(chuàng)建事件基類 DomainEvent(參考下圖),子類可以擴充屬性和方法。由于事件沒有太多的業(yè)務(wù)行為,實現(xiàn)方法一般比較簡單。

fd37bb7a-0b1c-11ee-962d-dac502259ad0.jpg

事件發(fā)布之前需要先構(gòu)建事件實體并持久化。事件發(fā)布的方式有很多種,你可以通過應(yīng)用服務(wù)或者領(lǐng)域服務(wù)發(fā)布到事件總線或者消息中間件,也可以從事件表中利用定時程序或數(shù)據(jù)庫日志捕獲技術(shù)獲取增量事件數(shù)據(jù),發(fā)布到消息中間件。

2. 事件數(shù)據(jù)持久化

事件數(shù)據(jù)持久化可用于系統(tǒng)之間的數(shù)據(jù)對賬,或者實現(xiàn)發(fā)布方和訂閱方事件數(shù)據(jù)的審計。當遇到消息中間件、訂閱方系統(tǒng)宕機或者網(wǎng)絡(luò)中斷,在問題解決后仍可繼續(xù)后續(xù)業(yè)務(wù)流轉(zhuǎn),保證數(shù)據(jù)的一致性。

事件數(shù)據(jù)持久化有兩種方案,在實施過程中你可以根據(jù)自己的業(yè)務(wù)場景進行選擇。

持久化到本地業(yè)務(wù)數(shù)據(jù)庫的事件表中,利用本地事務(wù)保證業(yè)務(wù)和事件數(shù)據(jù)的一致性。

持久化到共享的事件數(shù)據(jù)庫中。這里需要注意的是:業(yè)務(wù)數(shù)據(jù)庫和事件數(shù)據(jù)庫不在一個數(shù)據(jù)庫中,它們的數(shù)據(jù)持久化操作會跨數(shù)據(jù)庫,因此需要分布式事務(wù)機制來保證業(yè)務(wù)和事件數(shù)據(jù)的強一致性,結(jié)果就是會對系統(tǒng)性能造成一定的影響。

3. 事件總線(EventBus)

事件總線是實現(xiàn)微服務(wù)內(nèi)聚合之間領(lǐng)域事件的重要組件,它提供事件分發(fā)和接收等服務(wù)。事件總線是進程內(nèi)模型,它會在微服務(wù)內(nèi)聚合之間遍歷訂閱者列表,采取同步或異步的模式傳遞數(shù)據(jù)。事件分發(fā)流程大致如下:

如果是微服務(wù)內(nèi)的訂閱者(其它聚合),則直接分發(fā)到指定訂閱者;

如果是微服務(wù)外的訂閱者,將事件數(shù)據(jù)保存到事件庫(表)并異步發(fā)送到消息中間件;

如果同時存在微服務(wù)內(nèi)和外訂閱者,則先分發(fā)到內(nèi)部訂閱者,將事件消息保存到事件庫(表),再異步發(fā)送到消息中間件。

4. 消息中間件

跨微服務(wù)的領(lǐng)域事件大多會用到消息中間件,實現(xiàn)跨微服務(wù)的事件發(fā)布和訂閱。消息中間件的產(chǎn)品非常成熟,市場上可選的技術(shù)也非常多,比如Kafka,RabbitMQ等。

5. 事件接收和處理

微服務(wù)訂閱方在應(yīng)用層采用監(jiān)聽機制,接收消息隊列中的事件數(shù)據(jù),完成事件數(shù)據(jù)的持久化后,就可以開始進一步的業(yè)務(wù)處理。領(lǐng)域事件處理可在領(lǐng)域服務(wù)中實現(xiàn)。

領(lǐng)域事件運行機制案例

承保業(yè)務(wù)流程的繳費通知單事件,來給你解釋一下領(lǐng)域事件的運行機制。這個領(lǐng)域事件發(fā)生在投保和收款微服務(wù)之間。發(fā)生的領(lǐng)域事件是:繳費通知單已生成。下一步的業(yè)務(wù)操作是:繳費。

fd5b22f4-0b1c-11ee-962d-dac502259ad0.jpg

事件起點:出單員生成投保單,核保通過后,發(fā)起生成繳費通知單的操作。

1.投保微服務(wù)應(yīng)用服務(wù),調(diào)用聚合中的領(lǐng)域服務(wù)createPaymentNotice和createPaymentNoticeEvent,分別創(chuàng)建繳費通知單、繳費通知單事件。其中繳費通知單事件類PaymentNoticeEvent繼承基類DomainEvent。

2.利用倉儲服務(wù)持久化繳費通知單相關(guān)的業(yè)務(wù)和事件數(shù)據(jù)。為了避免分布式事務(wù),這些業(yè)務(wù)和事件數(shù)據(jù)都持久化到本地投保微服務(wù)數(shù)據(jù)庫中。

3.通過數(shù)據(jù)庫日志捕獲技術(shù)或者定時程序,從數(shù)據(jù)庫事件表中獲取事件增量數(shù)據(jù),發(fā)布到消息中間件。這里說明:事件發(fā)布也可以通過應(yīng)用服務(wù)或者領(lǐng)域服務(wù)完成發(fā)布。

4.收款微服務(wù)在應(yīng)用層從消息中間件訂閱繳費通知單事件消息主題,監(jiān)聽并獲取事件數(shù)據(jù)后,應(yīng)用服務(wù)調(diào)用領(lǐng)域?qū)拥念I(lǐng)域服務(wù)將事件數(shù)據(jù)持久化到本地數(shù)據(jù)庫中。

5.收款微服務(wù)調(diào)用領(lǐng)域?qū)拥念I(lǐng)域服務(wù)PayPremium,完成繳費。

6.事件結(jié)束。

事件風(fēng)暴

事件風(fēng)暴需要準備些什么

1. 事件風(fēng)暴的參與者

除了領(lǐng)域?qū)<?對業(yè)務(wù)極其了解的人),事件風(fēng)暴的其他參與者可以是DDD專家、架構(gòu)師、產(chǎn)品經(jīng)理、項目經(jīng)理、開發(fā)人員和測試人員等項目團隊成員。

領(lǐng)域建模是統(tǒng)一團隊語言的過程,因此項目團隊應(yīng)盡早地參與到領(lǐng)域建模中,這樣才能高效建立起團隊的通用語言。到了微服務(wù)建設(shè)時,領(lǐng)域模型也更容易和系統(tǒng)架構(gòu)保持一致。

2. 事件風(fēng)暴要準備的材料

在這個過程中,我們要用不同顏色的貼紙區(qū)分領(lǐng)域行為。如下圖,

用藍色表示命令

用綠色表示實體

橙色表示領(lǐng)域事件

黃色表示補充信息(補充信息主要用來說明注意事項,比如外部依賴等。)

fd90d7c8-0b1c-11ee-962d-dac502259ad0.jpg

3. 事件風(fēng)暴的場地

事件風(fēng)暴的發(fā)明者曾經(jīng)建議要準備八米長的墻,這樣設(shè)計就不會受到空間的限制了。當然,這個不是必要條件,看各自的現(xiàn)實條件吧,不要讓思維受限就好。

或者是一個多人在線協(xié)作的白板。

4. 事件風(fēng)暴分析的關(guān)注點

在領(lǐng)域建模的過程中,我們需要重點關(guān)注這類業(yè)務(wù)的語言和行為。比如某些業(yè)務(wù)動作或行為(事件)是否會觸發(fā)下一個業(yè)務(wù)動作,這個動作(事件)的輸入和輸出是什么?是誰(實體)發(fā)出的什么動作(命令),觸發(fā)了這個動作(事件)…我們可以從這些暗藏的詞匯中,分析出領(lǐng)域模型中的事件、命令和實體等領(lǐng)域?qū)ο蟆?/p>

如何用事件風(fēng)暴構(gòu)建領(lǐng)域模型

領(lǐng)域建模的過程主要包括產(chǎn)品愿景、業(yè)務(wù)場景分析、領(lǐng)域建模和微服務(wù)拆分與設(shè)計這幾個重要階段。下面以用戶中臺為例,介紹一下如何用事件風(fēng)暴構(gòu)建領(lǐng)域模型。

1. 產(chǎn)品愿景

產(chǎn)品愿景的主要目的是對產(chǎn)品頂層價值的設(shè)計,使產(chǎn)品目標用戶、核心價值、差異化競爭點等信息達成一致,避免產(chǎn)品偏離方向。

產(chǎn)品愿景的參與角色:領(lǐng)域?qū)<?、業(yè)務(wù)需求方、產(chǎn)品經(jīng)理、項目經(jīng)理和開發(fā)經(jīng)理。

在建模之前,項目團隊要思考這樣兩點:

用戶中臺到底能夠做什么?

它的業(yè)務(wù)范圍、目標用戶、核心價值和愿景,與其它同類產(chǎn)品的差異和優(yōu)勢在哪里?

這個過程也是明確用戶中臺建設(shè)方向和統(tǒng)一團隊思想的過程。參與者要對每一個點(下圖最左側(cè)列的內(nèi)容)發(fā)表意見,用水筆寫在貼紙上,貼在黃色貼紙的位置。這個過程會讓參與者充分發(fā)表意見,最后會將發(fā)散的意見統(tǒng)一為通用語言。如果你的團隊的產(chǎn)品愿景和目標已經(jīng)很清晰了,那這個步驟你可以忽略。

2. 業(yè)務(wù)場景分析

場景分析是從用戶視角出發(fā)的,根據(jù)業(yè)務(wù)流程或用戶旅程,采用用例和場景分析 ,探索領(lǐng)域中的典型場景,找出領(lǐng)域事件、實體和命令等領(lǐng)域?qū)ο?,支撐領(lǐng)域建模。事件風(fēng)暴參與者要盡可能地遍歷所有業(yè)務(wù)細節(jié),充分發(fā)表意見,不要遺漏業(yè)務(wù)要點。

場景分析的參與角色:領(lǐng)域?qū)<?、產(chǎn)品經(jīng)理、需求分析人員、架構(gòu)師、項目經(jīng)理、開發(fā)經(jīng)理和測試經(jīng)理。

用戶中臺有這樣三個典型的業(yè)務(wù)場景:

第一個是系統(tǒng)和崗位設(shè)置,設(shè)置系統(tǒng)中崗位的菜單權(quán)限;

第二個是用戶權(quán)限配置,為用戶建立賬戶和密碼,設(shè)置用戶崗位;

第三個是用戶登錄系統(tǒng)和權(quán)限校驗,生成用戶登錄和操作日志。

我們可以按照業(yè)務(wù)流程,一步一步搜尋用戶業(yè)務(wù)流程中的關(guān)鍵領(lǐng)域事件,比如崗位已創(chuàng)建,用戶已創(chuàng)建等事件。再找出什么行為會引起這些領(lǐng)域事件,這些行為可能是一個或若干個命令組合在一起產(chǎn)生的,比如創(chuàng)建用戶時,第一個命令是從公司HR系統(tǒng)中獲取用戶信息,第二個命令是根據(jù)HR的員工信息在用戶中臺創(chuàng)建用戶,創(chuàng)建完用戶后就會產(chǎn)生用戶已創(chuàng)建的領(lǐng)域事件。當然這個領(lǐng)域事件可能會觸發(fā)下一步的操作,比如發(fā)布到郵件系統(tǒng)通知用戶已創(chuàng)建,但也可能到此就結(jié)束了,你需要根據(jù)具體情況來分析是否還有下一步的操作。

fda2442c-0b1c-11ee-962d-dac502259ad0.jpg

3. 領(lǐng)域建模

領(lǐng)域建模時,我們會根據(jù)場景分析過程中產(chǎn)生的領(lǐng)域?qū)ο螅热缑?、事件等之間關(guān)系,找出產(chǎn)生命令的實體,分析實體之間的依賴關(guān)系組成聚合,為聚合劃定限界上下文,建立領(lǐng)域模型以及模型之間的依賴。領(lǐng)域模型利用限界上下文向上可以指導(dǎo)微服務(wù)設(shè)計,通過聚合向下可以指導(dǎo)聚合根、實體和值對象的設(shè)計。

領(lǐng)域建模的參與角色:領(lǐng)域?qū)<?、產(chǎn)品經(jīng)理、需求分析人員、架構(gòu)師、項目經(jīng)理、開發(fā)經(jīng)理和測試經(jīng)理。

具體可以分為這樣三步。

第一步:從命令和事件中提取產(chǎn)生這些行為的實體。用綠色貼紙表示實體。通過分析用戶中臺的命令和事件等行為數(shù)據(jù),提取了產(chǎn)生這些行為的用戶、賬戶、認證票據(jù)、系統(tǒng)、菜單、崗位和用戶日志七個實體。

fdca69de-0b1c-11ee-962d-dac502259ad0.jpg

第二步:根據(jù)聚合根的管理性質(zhì)從七個實體中找出聚合根,比如,用戶管理用戶相關(guān)實體以及值對象,系統(tǒng)可以管理與系統(tǒng)相關(guān)的菜單等實體等,可以找出用戶和系統(tǒng)等聚合根。然后根據(jù)業(yè)務(wù)依賴和業(yè)務(wù)內(nèi)聚原則,將聚合根以及它關(guān)聯(lián)的實體和值對象組合為聚合,比如系統(tǒng)和菜單實體可以組合為“系統(tǒng)功能”聚合。按照上述方法,用戶中臺就有了系統(tǒng)功能、崗位、用戶信息、用戶日志、賬戶和認證票據(jù)六個聚合。

第三步:劃定限界上下文,根據(jù)上下文語義將聚合歸類。根據(jù)用戶域的上下文語境,用戶基本信息和用戶日志信息這兩個聚合共同構(gòu)成用戶信息域,分別管理用戶基本信息、用戶登錄和操作日志。認證票據(jù)和賬戶這兩個聚合共同構(gòu)成認證域,分別實現(xiàn)不同方式的登錄和認證。系統(tǒng)功能和崗位這兩個聚合共同構(gòu)成權(quán)限域,分別實現(xiàn)系統(tǒng)和菜單管理以及系統(tǒng)的崗位配置。根據(jù)業(yè)務(wù)邊界,我們可以將用戶中臺劃分為三個限界上下文:用戶信息、認證和權(quán)限。

fde4bfd2-0b1c-11ee-962d-dac502259ad0.jpg

到這里我們就完成了用戶中臺領(lǐng)域模型的構(gòu)建了。那由于領(lǐng)域建模的過程中產(chǎn)生的領(lǐng)域?qū)ο髮嵲谔嗔?,我們可以借助表格來記錄?/p>

fe005490-0b1c-11ee-962d-dac502259ad0.jpg

4. 微服務(wù)拆分與設(shè)計

我們在基礎(chǔ)篇講過,原則上一個領(lǐng)域模型就可以設(shè)計為一個微服務(wù),但由于領(lǐng)域建模時只考慮了業(yè)務(wù)因素,沒有考慮微服務(wù)落地時的技術(shù)、團隊以及運行環(huán)境等非業(yè)務(wù)因素,因此在微服務(wù)拆分與設(shè)計時,我們不能簡單地將領(lǐng)域模型作為拆分微服務(wù)的唯一標準,它只能作為微服務(wù)拆分的一個重要依據(jù)。

一般來說一個限界上下文拆分成一個微服務(wù)

微服務(wù)的設(shè)計還需要考慮服務(wù)的粒度、分層、邊界劃分、依賴關(guān)系和集成關(guān)系。除了考慮業(yè)務(wù)職責單一外,我們還需要考慮將敏態(tài)與穩(wěn)態(tài)業(yè)務(wù)的分離、非功能性需求(如彈性伸縮要求、安全性等要求)、團隊組織和溝通效率、軟件包大小以及技術(shù)異構(gòu)等非業(yè)務(wù)因素。

微服務(wù)設(shè)計建議參與的角色:領(lǐng)域?qū)<?、產(chǎn)品經(jīng)理、需求分析人員、架構(gòu)師、項目經(jīng)理、開發(fā)經(jīng)理和測試經(jīng)理。

用戶中臺微服務(wù)設(shè)計如果不考慮非業(yè)務(wù)因素,我們完全可以按照領(lǐng)域模型與微服務(wù)一對一的關(guān)系來設(shè)計,將用戶中臺設(shè)計為:用戶、認證和權(quán)限三個微服務(wù)。但如果用戶日志數(shù)據(jù)量巨大,大到需要采用大數(shù)據(jù)技術(shù)來實現(xiàn),這時用戶信息聚合與用戶日志聚合就會有技術(shù)異構(gòu)。雖然在領(lǐng)域建模時,我們將他們放在一個了領(lǐng)域模型內(nèi),但如果考慮技術(shù)異構(gòu),這兩個聚合就不適合放到同一個微服務(wù)里了。我們可以以聚合作為拆分單位,將用戶基本信息管理和用戶日志管理拆分為兩個技術(shù)異構(gòu)的微服務(wù),分別用不同的技術(shù)來實現(xiàn)它們。

分層架構(gòu)

DDD分層架構(gòu)

DDD的分層架構(gòu)在不斷發(fā)展。最早是傳統(tǒng)的四層架構(gòu);后來四層架構(gòu)有了進一步的優(yōu)化,實現(xiàn)了各層對基礎(chǔ)層的解耦;再后來領(lǐng)域?qū)雍蛻?yīng)用層之間增加了上下文環(huán)境(Context)層,五層架構(gòu)(DCI)就此形成了。

fe0f64c6-0b1c-11ee-962d-dac502259ad0.jpg

我們看一下上面這張圖,在最早的傳統(tǒng)四層架構(gòu)中,基礎(chǔ)層是被其它層依賴的,它位于最核心的位置,那按照分層架構(gòu)的思想,它應(yīng)該就是核心,但實際上領(lǐng)域?qū)硬攀擒浖暮诵?,所以這種依賴是有問題的。后來我們采用了依賴倒置(Dependency inversion principle,DIP)的設(shè)計,優(yōu)化了傳統(tǒng)的四層架構(gòu),實現(xiàn)了各層對基礎(chǔ)層的解耦。

我們今天講的DDD分層架構(gòu)就是優(yōu)化后的四層架構(gòu)。在下面這張圖中,從上到下依次是:用戶接口層、應(yīng)用層、領(lǐng)域?qū)雍突A(chǔ)層。那DDD各層的主要職責是什么呢?下面我來逐一介紹一下。

fe3868f8-0b1c-11ee-962d-dac502259ad0.png

1.用戶接口層

用戶接口層負責向用戶顯示信息和解釋用戶指令。這里的用戶可能是:用戶、程序、自動化測試和批處理腳本等等。

2.應(yīng)用層

應(yīng)用層是很薄的一層,理論上不應(yīng)該有業(yè)務(wù)規(guī)則或邏輯,主要面向用例和流程相關(guān)的操作。但應(yīng)用層又位于領(lǐng)域?qū)又?,因為領(lǐng)域?qū)影鄠€聚合,所以它可以協(xié)調(diào)多個聚合的服務(wù)和領(lǐng)域?qū)ο笸瓿煞?wù)編排和組合,協(xié)作完成業(yè)務(wù)操作。

此外,應(yīng)用層也是微服務(wù)之間交互的通道,它可以調(diào)用其它微服務(wù)的應(yīng)用服務(wù),完成微服務(wù)之間的服務(wù)組合和編排。

這里我要提醒你一下:在設(shè)計和開發(fā)時,不要將本該放在領(lǐng)域?qū)拥臉I(yè)務(wù)邏輯放到應(yīng)用層中實現(xiàn)。因為龐大的應(yīng)用層會使領(lǐng)域模型失焦,時間一長你的微服務(wù)就會演化為傳統(tǒng)的三層架構(gòu),業(yè)務(wù)邏輯會變得混亂。

另外,應(yīng)用服務(wù)是在應(yīng)用層的,它負責服務(wù)的組合、編排和轉(zhuǎn)發(fā),負責處理業(yè)務(wù)用例的執(zhí)行順序以及結(jié)果的拼裝,以粗粒度的服務(wù)通過API網(wǎng)關(guān)向前端發(fā)布。還有,應(yīng)用服務(wù)還可以進行安全認證、權(quán)限校驗、事務(wù)控制、發(fā)送或訂閱領(lǐng)域事件等。

3.領(lǐng)域?qū)?/strong>

領(lǐng)域?qū)拥淖饔檬菍崿F(xiàn)企業(yè)核心業(yè)務(wù)邏輯 ,通過各種校驗手段保證業(yè)務(wù)的正確性。領(lǐng)域?qū)又饕w現(xiàn)領(lǐng)域模型的業(yè)務(wù)能力,它用來表達業(yè)務(wù)概念、業(yè)務(wù)狀態(tài)和業(yè)務(wù)規(guī)則。

領(lǐng)域?qū)影?strong>聚合根、實體、值對象、領(lǐng)域服務(wù) 等領(lǐng)域模型中的領(lǐng)域?qū)ο蟆?/p>

這里我要特別解釋一下其中幾個領(lǐng)域?qū)ο蟮年P(guān)系,以便你在設(shè)計領(lǐng)域?qū)拥臅r候能更加清楚。

首先,領(lǐng)域模型的業(yè)務(wù)邏輯主要是由實體和領(lǐng)域服務(wù)來實現(xiàn)的,其中實體會采用充血模型來實現(xiàn)所有與之相關(guān)的業(yè)務(wù)功能。

其次,你要知道,實體和領(lǐng)域服務(wù)在實現(xiàn)業(yè)務(wù)邏輯上不是同級的,當領(lǐng)域中的某些功能,單一實體(或者值對象)不能實現(xiàn)時,領(lǐng)域服務(wù)就會出馬,它可以組合聚合內(nèi)的多個實體(或者值對象),實現(xiàn)復(fù)雜的業(yè)務(wù)邏輯。

4.基礎(chǔ)層

基礎(chǔ)層是貫穿所有層的,它的作用就是為其它各層提供通用的技術(shù)和基礎(chǔ)服務(wù),包括第三方工具、驅(qū)動、消息中間件、網(wǎng)關(guān)、文件、緩存以及數(shù)據(jù)庫 等。比較常見的功能還是提供數(shù)據(jù)庫持久化。

基礎(chǔ)層包含基礎(chǔ)服務(wù),它采用依賴倒置設(shè)計,封裝基礎(chǔ)資源服務(wù),實現(xiàn)應(yīng)用層、領(lǐng)域?qū)优c基礎(chǔ)層的解耦,降低外部資源變化對應(yīng)用的影響。

比如說,在傳統(tǒng)架構(gòu)設(shè)計中,由于上層應(yīng)用對數(shù)據(jù)庫的強耦合,很多公司在架構(gòu)演進中最擔憂的可能就是換數(shù)據(jù)庫了,因為一旦更換數(shù)據(jù)庫,就可能需要重寫大部分的代碼,這對應(yīng)用來說是致命的。那采用依賴倒置的設(shè)計以后,應(yīng)用層就可以通過解耦來保持獨立的核心業(yè)務(wù)邏輯。當數(shù)據(jù)庫變更時,我們只需要更換數(shù)據(jù)庫基礎(chǔ)服務(wù)就可以了,這樣就將資源變更對應(yīng)用的影響降到了最低。

DDD分層架構(gòu)最重要的原則

在《實現(xiàn)領(lǐng)域驅(qū)動設(shè)計》一書中,DDD分層架構(gòu)有一個重要的原則:每層只能與位于其下方的層發(fā)生耦合 。

而架構(gòu)根據(jù)耦合的緊密程度又可以分為兩種:嚴格分層架構(gòu)和松散分層架構(gòu)。優(yōu)化后的DDD分層架構(gòu)模型就屬于嚴格分層架構(gòu),任何層只能對位于其直接下方的層產(chǎn)生依賴。而傳統(tǒng)的DDD分層架構(gòu)則屬于松散分層架構(gòu),它允許某層與其任意下方的層發(fā)生依賴。

建議采用嚴格分層架構(gòu)。

在嚴格分層架構(gòu)中,領(lǐng)域服務(wù)只能被應(yīng)用服務(wù)調(diào)用,而應(yīng)用服務(wù)只能被用戶接口層調(diào)用,服務(wù)是逐層對外封裝或組合的,依賴關(guān)系清晰。而在松散分層架構(gòu)中,領(lǐng)域服務(wù)可以同時被應(yīng)用層或用戶接口層調(diào)用,服務(wù)的依賴關(guān)系比較復(fù)雜且難管理,甚至容易使核心業(yè)務(wù)邏輯外泄。

試想下,如果領(lǐng)域?qū)又械哪硞€服務(wù)發(fā)生了重大變更,那該如何通知所有調(diào)用方同步調(diào)整和升級呢?但在嚴格分層架構(gòu)中,你只需要逐層通知上層服務(wù)就可以了。

代碼架構(gòu)

整潔架構(gòu)

整潔架構(gòu)又名“洋蔥架構(gòu) ”。為什么叫它洋蔥架構(gòu)?看看下面這張圖你就明白了。整潔架構(gòu)的層就像洋蔥片一樣,它體現(xiàn)了分層的設(shè)計思想。

在整潔架構(gòu)里,同心圓代表應(yīng)用軟件的不同部分,從里到外依次是領(lǐng)域模型、領(lǐng)域服務(wù)、應(yīng)用服務(wù)和最外圍的容易變化的內(nèi)容,比如用戶界面和基礎(chǔ)設(shè)施。

整潔架構(gòu)最主要的原則是依賴原則,它定義了各層的依賴關(guān)系,越往里依賴越低,代碼級別越高,越是核心能力。外圓代碼依賴只能指向內(nèi)圓,內(nèi)圓不需要知道外圓的任何情況。

fe48985e-0b1c-11ee-962d-dac502259ad0.png

在洋蔥架構(gòu)中,各層的職能是這樣劃分的:

領(lǐng)域模型實現(xiàn)領(lǐng)域內(nèi)核心業(yè)務(wù)邏輯,它封裝了企業(yè)級的業(yè)務(wù)規(guī)則。領(lǐng)域模型的主體是實體,一個實體可以是一個帶方法的對象,也可以是一個數(shù)據(jù)結(jié)構(gòu)和方法集合。

領(lǐng)域服務(wù)實現(xiàn)涉及多個實體的復(fù)雜業(yè)務(wù)邏輯。

應(yīng)用服務(wù)實現(xiàn)與用戶操作相關(guān)的服務(wù)組合與編排,它包含了應(yīng)用特有的業(yè)務(wù)流程規(guī)則,封裝和實現(xiàn)了系統(tǒng)所有用例。

最外層主要提供適配的能力,適配能力分為主動適配和被動適配。主動適配主要實現(xiàn)外部用戶、網(wǎng)頁、批處理和自動化測試等對內(nèi)層業(yè)務(wù)邏輯訪問適配。被動適配主要是實現(xiàn)核心業(yè)務(wù)邏輯對基礎(chǔ)資源訪問的適配,比如數(shù)據(jù)庫、緩存、文件系統(tǒng)和消息中間件等。

紅圈內(nèi)的領(lǐng)域模型、領(lǐng)域服務(wù)和應(yīng)用服務(wù)一起組成軟件核心業(yè)務(wù)能力。

六邊形架構(gòu)

六邊形架構(gòu)又名“端口適配器架構(gòu)” 。追溯微服務(wù)架構(gòu)的淵源,一般都會涉及到六邊形架構(gòu)。

六邊形架構(gòu)的核心理念是:應(yīng)用是通過端口與外部進行交互的 。我想這也是微服務(wù)架構(gòu)下API網(wǎng)關(guān)盛行的主要原因吧。

也就是說,在下圖的六邊形架構(gòu)中,紅圈內(nèi)的核心業(yè)務(wù)邏輯(應(yīng)用程序和領(lǐng)域模型)與外部資源(包括APP、Web應(yīng)用以及數(shù)據(jù)庫資源等)完全隔離,僅通過適配器進行交互。它解決了業(yè)務(wù)邏輯與用戶界面的代碼交錯問題,很好地實現(xiàn)了前后端分離。六邊形架構(gòu)各層的依賴關(guān)系與整潔架構(gòu)一樣,都是由外向內(nèi)依賴。

fe66739c-0b1c-11ee-962d-dac502259ad0.png

六邊形架構(gòu)將系統(tǒng)分為內(nèi)六邊形和外六邊形兩層,這兩層的職能劃分如下:

紅圈內(nèi)的六邊形實現(xiàn)應(yīng)用的核心業(yè)務(wù)邏輯;

外六邊形完成外部應(yīng)用、驅(qū)動和基礎(chǔ)資源等的交互和訪問,對前端應(yīng)用以API主動適配的方式提供服務(wù),對基礎(chǔ)資源以依賴倒置被動適配的方式實現(xiàn)資源訪問。

六邊形架構(gòu)的一個端口可能對應(yīng)多個外部系統(tǒng),不同的外部系統(tǒng)也可能會使用不同的適配器,由適配器負責協(xié)議轉(zhuǎn)換。這就使得應(yīng)用程序能夠以一致的方式被用戶、程序、自動化測試和批處理腳本使用。

三種模型對比

雖然DDD分層架構(gòu)、整潔架構(gòu)、六邊形架構(gòu)的架構(gòu)模型表現(xiàn)形式不一樣,但你不要被它們的表象所迷惑,這三種架構(gòu)模型的設(shè)計思想正是微服務(wù)架構(gòu)高內(nèi)聚低耦合原則的完美體現(xiàn),而它們身上閃耀的正是以領(lǐng)域模型為中心的設(shè)計思想。

fe8bd2fe-0b1c-11ee-962d-dac502259ad0.png

我們看下上面這張圖,結(jié)合圖示對這三種架構(gòu)模型做一個分析。

請你重點關(guān)注圖中的紅色線框,它們是非常重要的分界線,這三種架構(gòu)里面都有,它的作用就是將核心業(yè)務(wù)邏輯與外部應(yīng)用、基礎(chǔ)資源進行隔離。

紅色框內(nèi)部主要實現(xiàn)核心業(yè)務(wù)邏輯,但核心業(yè)務(wù)邏輯也是有差異的,有的業(yè)務(wù)邏輯屬于領(lǐng)域模型的能力,有的則屬于面向用戶的用例和流程編排能力。按照這種功能的差異,我們在這三種架構(gòu)中劃分了應(yīng)用層和領(lǐng)域?qū)?,來承擔不同的業(yè)務(wù)邏輯。

領(lǐng)域?qū)訉崿F(xiàn)面向領(lǐng)域模型,實現(xiàn)領(lǐng)域模型的核心業(yè)務(wù)邏輯,屬于原子模型,它需要保持領(lǐng)域模型和業(yè)務(wù)邏輯的穩(wěn)定,對外提供穩(wěn)定的細粒度的領(lǐng)域服務(wù),所以它處于架構(gòu)的核心位置。

應(yīng)用層實現(xiàn)面向用戶操作相關(guān)的用例和流程,對外提供粗粒度的API服務(wù)。它就像一個齒輪一樣進行前臺應(yīng)用和領(lǐng)域?qū)拥倪m配,接收前臺需求,隨時做出響應(yīng)和調(diào)整,盡量避免將前臺需求傳導(dǎo)到領(lǐng)域?qū)印?yīng)用層作為配速齒輪則位于前臺應(yīng)用和領(lǐng)域?qū)又g。

COLA4.0

GitHub:https://github.com/alibaba/COLA 作者博客:https://blog.csdn.net/significantfrank/article/details/110934799

生成器:https://start.aliyun.com/bootstrap.html

fea732c4-0b1c-11ee-962d-dac502259ad0.png

基于 Spring Boot + MyBatis Plus + Vue & Element 實現(xiàn)的后臺管理系統(tǒng) + 用戶小程序,支持 RBAC 動態(tài)權(quán)限、多租戶、數(shù)據(jù)權(quán)限、工作流、三方登錄、支付、短信、商城等功能

項目地址:https://github.com/YunaiV/ruoyi-vue-pro

視頻教程:https://doc.iocoder.cn/video/

DDD實戰(zhàn)

feb9e162-0b1c-11ee-962d-dac502259ad0.png

模塊劃分如下

fed0aaa0-0b1c-11ee-962d-dac502259ad0.png

本次我們重點完成

賬戶模塊

廣告管理模塊

廣告下發(fā)模塊

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

戰(zhàn)略設(shè)計階段:此階段主要是依賴于事件風(fēng)暴(可理解為基于事件流程的頭腦風(fēng)暴),來呈現(xiàn)出產(chǎn)品的發(fā)展方向以及核心流程和場景,并文檔化。

1.產(chǎn)品要解決的問題,以及從用戶角度歸納出典型業(yè)務(wù)場景,落實文檔 -----> 產(chǎn)品愿景、場景分析

2.找出上一步總結(jié)出的關(guān)鍵名詞,作為各個場景的實體 -----> 領(lǐng)域建模:找出領(lǐng)域?qū)ο?/p>

3.根據(jù)上一步總結(jié)出實體,總結(jié)出之間的關(guān)系(聚合根、值對象、普通實體),劃分出聚合 -----> 領(lǐng)域建模:定義聚合

4.以上一步歸納出的聚合為單位,根據(jù)業(yè)務(wù)場景將聚合分組,得到限界上下文(也就是所屬的領(lǐng)域) ----->領(lǐng)域建模:定義界限上下文

在第 1 步落實文檔后,后面的 2,3,4 領(lǐng)域建模階段都要不斷的參照第 1 步總結(jié)出的業(yè)務(wù)流程場景來進行拆解與合并;產(chǎn)品愿景、場景分析 兩個階段是從宏觀到微觀的過程,而 領(lǐng)域建模階段是從微觀到宏觀的過程,也就是自底向上的思想。整體就像是總分、分總的過程。

產(chǎn)品愿景

產(chǎn)品愿景是對產(chǎn)品頂層價值設(shè)計,對產(chǎn)品目標用戶、核心價值、差異化競爭點等信息達成一致,避免產(chǎn)品偏離方向。

服務(wù)用戶

想投廣告的人。廣告主以及代理商的優(yōu)化師

提供能力

給廣告主提供豐富的廣告資源,實現(xiàn)廣告的管理和投放。廣告投放效果,以及效率 。

提高交互效率。提供open-api,可以讓客戶通過程序化的方式管理廣告。

定位

業(yè)界先進的一站式效果投放平臺。提供RTA,DPA,OCPX等專業(yè)能力

優(yōu)勢

依托于手機廠商提供的數(shù)據(jù)能力,給廣告主提供更好的投放效果。

場景分析

fee0a892-0b1c-11ee-962d-dac502259ad0.png

領(lǐng)域建模

領(lǐng)域建模是通過對業(yè)務(wù)和問題域進行分析,建立領(lǐng)域模型。

向上通過限界上下文指導(dǎo)微服務(wù)邊界設(shè)計,向下通過聚合指導(dǎo)實體對象設(shè)計。

領(lǐng)域建模是一個收斂的過程,分三步:

第一步找出領(lǐng)域?qū)嶓w和值對象等領(lǐng)域?qū)ο螅?/p>

第二步找出聚合根,根據(jù)實體、值對象與聚合根的依賴關(guān)系,建立聚合;

第三步根據(jù)業(yè)務(wù)及語義邊界等因素,定義限界上下文。

第一步:找出實體和值對象等領(lǐng)域?qū)ο?/p>

根據(jù)場景分析,分析并找出發(fā)起或產(chǎn)生這些命令或領(lǐng)域事件的實體和值對象,將與實體或值對象有關(guān)的命令和事件聚集到實體。

fef84f88-0b1c-11ee-962d-dac502259ad0.png

第二步:定義聚合

定義聚合前,先找出聚合根。然后找出與聚合根緊密依賴的實體和值對象。我們發(fā)現(xiàn)審批意見、審批規(guī)則和請假單緊密關(guān)聯(lián),組織關(guān)系和人員緊密關(guān)聯(lián)。

ff2fd71e-0b1c-11ee-962d-dac502259ad0.png

第三步:定義限界上下文

把整個定義為廣告管理限界上下文

通用語言

廣告業(yè)務(wù):

中文 英文
廣告計劃 AdCampaign
廣告組 AdGroup
廣告定向 AdTargeting
廣告創(chuàng)意 AdCreative
廣告素材 AdAsset
操作日志 OperationLog
賬號 Account

微服務(wù)拆分

理論上一個限界上下文就可以設(shè)計為一個微服務(wù),但還需要綜合考慮多種外部因素,比如:職責單一性、敏態(tài)與穩(wěn)態(tài)業(yè)務(wù)分離、非功能性需求(如彈性伸縮、版本發(fā)布頻率和安全等要求)、軟件包大小、團隊溝通效率和技術(shù)異構(gòu)等非業(yè)務(wù)要素。

可以微服務(wù)的拆分粒度大一些,但是聚合和限界上下文一定要邊界清晰,后續(xù)隨著某些功能逐漸變大再去拆分也會比較容易

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

有了戰(zhàn)略設(shè)計階段的結(jié)果,反而戰(zhàn)術(shù)設(shè)計階段相對清晰一些。

1.按照 DDD 四層模型建包,咱們這里使用COLA生成的包結(jié)構(gòu)

2.確定聚合中的對象關(guān)系,定義哪些是實體,哪些是值對象,具體字段都有什么。

3.通過戰(zhàn)略設(shè)計階段文檔中的命令、事件來編排充血模型的領(lǐng)域?qū)ο?,?gòu)建應(yīng)用服務(wù)與領(lǐng)域服務(wù)

詳細設(shè)計

技術(shù)選型跟上面的關(guān)系不大。可以使用COLA4.0分層框架。

使用SpringCloud技術(shù)棧,以及根據(jù)業(yè)務(wù)建模選擇中間件。





審核編輯:劉清

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴

原文標題:2萬字帶你入門DDD

文章出處:【微信號:芋道源碼,微信公眾號:芋道源碼】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。

收藏 人收藏
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

    評論

    相關(guān)推薦
    熱點推薦

    Redis Sentinel和Cluster模式如何選擇

    在我十年的運維生涯中,見過太多團隊在Redis集群方案選擇上踩坑。有的團隊盲目追求"高大上"的Cluster模式,結(jié)果運維復(fù)雜度爆表;有的團隊死守Sentinel不放,最后擴展性成了瓶頸。今天,我想通過這篇萬字長文,把我在生產(chǎn)環(huán)境中積累的經(jīng)驗全部分享給你。
    的頭像 發(fā)表于 09-08 09:31 ?285次閱讀

    3萬字長文!深度解析大語言模型LLM原理

    我們正在參加全球電子成就獎的評選,歡迎大家?guī)臀覀兺镀薄x謝支持本文轉(zhuǎn)自:騰訊技術(shù)工程作者:royceshao大語言模型LLM的精妙之處在于很好地利用數(shù)學(xué)解決了工業(yè)場景的問題,筆者基于過往工程經(jīng)驗繼續(xù)追本溯源,與騰訊學(xué)堂合作撰寫本文,嘗試讓人人都能懂大語言模型的基礎(chǔ)原理。1、大語言模型簡述截止到2025年“大模型”一般泛指“超大參數(shù)模型”,參數(shù)是指深度神經(jīng)
    的頭像 發(fā)表于 09-02 13:34 ?2712次閱讀
    3<b class='flag-5'>萬字</b>長文!深度解析大語言模型LLM原理

    萬字全文科普:什么是IP?

    半導(dǎo)體行業(yè)在一個復(fù)雜且快速發(fā)展的生態(tài)系統(tǒng)中運作,并由持續(xù)創(chuàng)新驅(qū)動。該生態(tài)系統(tǒng)的核心是半導(dǎo)體價值鏈,它包含幾個關(guān)鍵階段:芯片設(shè)計、晶圓制造、最終組裝和原材料采購。每個階段對于半導(dǎo)體器件的生產(chǎn)和功能都至關(guān)重要。IP提供商在這一框架中發(fā)揮著關(guān)鍵作用,尤其是在芯片設(shè)計階段,該階段是整個價值鏈的基礎(chǔ)。他們提供專業(yè)的尖端技術(shù),以增強創(chuàng)新、促進無縫集成、確保合規(guī)性并加快產(chǎn)
    的頭像 發(fā)表于 07-21 09:53 ?549次閱讀
    <b class='flag-5'>萬字</b>全文科普:什么是IP?

    萬字長文】物聯(lián)網(wǎng)的激蕩二十年

    2005年11月,在突尼斯舉辦的信息社會世界峰會(WSIS)上,國際電信聯(lián)盟(ITU)發(fā)布了一份名為《ITU互聯(lián)網(wǎng)報告2005:物聯(lián)網(wǎng)》,正式向世人展示了什么是“物聯(lián)網(wǎng)(InternetofThings)”。雖然業(yè)界一致認為,1999年,麻省理工學(xué)院的KevinAshton首次提出”物聯(lián)網(wǎng)”這一術(shù)語,但僅僅只是一個理念,沒有成體系的解釋,也無法形成共識。而I
    的頭像 發(fā)表于 06-27 13:42 ?1162次閱讀
    【<b class='flag-5'>萬字</b>長文】物聯(lián)網(wǎng)的激蕩二十年

    電子工程師自學(xué)速成——入門

    本文共3冊,由于資料內(nèi)存過大,分開上傳,有需要的朋友可以去主頁搜索下載哦~ 電子工程師自學(xué)速成分為:入門篇、提高篇和設(shè)計篇,本文為入門篇,內(nèi)容包括電子技術(shù)入門基礎(chǔ)、電子元器件(電阻器、電容器
    發(fā)表于 05-15 15:50

    全面解析新概念模擬電路(建議下載!)

    全文共五冊,近50萬字,一樣的風(fēng)趣幽默,一樣的social化語言,深入淺出地將枯燥深奧的模電知識講得簡單易學(xué)。 《新概念模擬電路》內(nèi)容包含了《晶體管》、《負反饋和運算放大器》、《運放電路的頻率特性
    發(fā)表于 04-16 13:37

    萬字聊聊什么是智能車載終端?為什么智駕發(fā)展離不開它?

    智能車載終端作為車聯(lián)網(wǎng)技術(shù)的核心,近年來發(fā)展迅速,已成為汽車智能化和自動駕駛領(lǐng)域的關(guān)鍵支撐技術(shù)。其核心功能涵蓋智能導(dǎo)航、實時通信、娛樂互動、安全監(jiān)控等,為駕駛者和乘客提供全面的服務(wù)支持。隨著自動駕駛和智能網(wǎng)聯(lián)汽車的發(fā)展需求不斷增長,智能車載終端的市場規(guī)模快速擴展,同時也面臨技術(shù)創(chuàng)新、市場競爭、產(chǎn)業(yè)鏈協(xié)同及政策規(guī)范等多重挑戰(zhàn)。 ? 引言 智能車載終端作為汽車智能化發(fā)展的核心技術(shù)之一,其重要性日益凸顯。在汽
    的頭像 發(fā)表于 03-31 09:12 ?6966次閱讀
    <b class='flag-5'>萬字</b>聊聊什么是智能車載終端?為什么智駕發(fā)展離不開它?

    【電子工具】DM40數(shù)字用表,60000計數(shù)(Max),精準且創(chuàng)新設(shè)計,快捷高效;集用表,示波器及信號發(fā)生器功能于一體!

    】DM40用表功能全方位展示?。c擊觀看) (2)【原子哥介紹】原子哥帶你詳細了解DM40用表!(點擊觀看) 二、PDF資料下載 三、圖片介紹
    發(fā)表于 02-17 15:35

    Xmind完成對AI總結(jié)工具Briefy的戰(zhàn)略收購

    全球知名的知識管理企業(yè)Xmind近日宣布,已完成對AI總結(jié)工具Briefy的戰(zhàn)略收購。Briefy以其強大的大語言模型驅(qū)動的多模態(tài)解析技術(shù)著稱,能夠?qū)㈤L視頻和萬字文檔等復(fù)雜信息轉(zhuǎn)化為結(jié)構(gòu)清晰的大綱或思維導(dǎo)圖,并通過知識庫功能幫助用戶高效消化和管理知識。
    的頭像 發(fā)表于 02-13 16:01 ?732次閱讀

    手把手帶你入門AWStudio運動控制編程

    導(dǎo)讀面對一臺ZMC600E運動控制器與多臺伺服電機,我們該怎樣讓它工作起來?本文帶你了解PLCOPen,并詳細講解如何使用AWStudio控制電機運動。在自動化領(lǐng)域,運動控制是一件很復(fù)雜的事情,包含
    的頭像 發(fā)表于 02-10 11:38 ?964次閱讀
    手把手<b class='flag-5'>帶你</b><b class='flag-5'>入門</b>AWStudio運動控制編程

    萬字長文!工業(yè)5.0的內(nèi)涵、體系架構(gòu)和使能技術(shù)

    摘要: 工業(yè)4.0誕生以來,強化了數(shù)字化、數(shù)據(jù)驅(qū)動和互聯(lián)的工業(yè)所帶來的高度變革性影響。但是工業(yè)4.0沒有強調(diào)工業(yè)在全球范圍內(nèi)為人類提供長期服務(wù)的重要性,也沒有很好解決如何利用技術(shù)創(chuàng)新來促進工業(yè)與社會之間的協(xié)作和“雙贏”互動等問題。工業(yè)5.0系統(tǒng)地提出將勞動者作為工業(yè)生產(chǎn)的核心,從而實現(xiàn)就業(yè)和增長之外的社會目標,穩(wěn)健地提供繁榮。但是,工業(yè)5.0作為對工業(yè)未來發(fā)展的再思考,目前其研究尚處于探索階段,研究成果相對較少且缺乏
    的頭像 發(fā)表于 02-05 11:30 ?1587次閱讀
    <b class='flag-5'>萬字</b>長文!工業(yè)5.0的內(nèi)涵、體系架構(gòu)和使能技術(shù)

    萬字長文,看懂激光基礎(chǔ)知識!

    深入介紹激光基礎(chǔ)知識,幫助您輕松理解激光領(lǐng)域的關(guān)鍵概念和原理。
    的頭像 發(fā)表于 12-20 09:49 ?1621次閱讀
    <b class='flag-5'>萬字</b>長文,看懂激光基礎(chǔ)知識!

    瑞薩 FPB-RA6E2 評估板入門學(xué)習(xí)

    瑞薩 FPB-RA6E2 評估板入門學(xué)習(xí)
    的頭像 發(fā)表于 12-11 09:22 ?1138次閱讀
    瑞薩 FPB-RA6E<b class='flag-5'>2</b> 評估板<b class='flag-5'>入門</b>學(xué)習(xí)

    socket 編程基礎(chǔ)入門

    進行通信。本文將帶你入門 Socket 編程,幫助你理解基本概念和步驟。 1. Socket 的基本概念 Socket 是一個通信端點,它允許程序發(fā)送和接收數(shù)據(jù)。在 TCP/IP 協(xié)議族中,有兩種主要
    的頭像 發(fā)表于 11-12 14:03 ?1500次閱讀

    智慧公交是什么?一文帶你詳解智慧公交的解決方案!

    智慧公交是什么?一文帶你詳解智慧公交的解決方案!
    的頭像 發(fā)表于 11-05 12:26 ?1314次閱讀
    智慧公交是什么?一文<b class='flag-5'>帶你</b>詳解智慧公交的解決方案!