[半翻] 设计面向DDD的微服务
這篇文章行文結(jié)構(gòu)對照微軟博客, 結(jié)合本人意譯和多年實(shí)踐的回顧性思考形成此次讀書筆記。
Domian-driven Design
領(lǐng)域-驅(qū)動-設(shè)計(DDD)提倡基于(用例相關(guān)的現(xiàn)實(shí)業(yè)務(wù))進(jìn)行建模。
1. DDD的視角
DDD將現(xiàn)實(shí)問題視為領(lǐng)域;
DDD將獨(dú)立的問題描述為有界限的上下文(一個有界上下文對應(yīng)一個微服務(wù)),并強(qiáng)調(diào)通用語言討論這些問題
2. DDD提出的概念
許多技術(shù)概念和模式,例如充血模型(對應(yīng)我們常寫貧血模型)、值對象、聚合和聚合根規(guī)則。
3. 目前實(shí)施DDD的現(xiàn)狀
有時DDD技術(shù)規(guī)則和模式被視為障礙/啰嗦,對于實(shí)施DDD方法而言,學(xué)習(xí)曲線比較陡峭。
不要為了實(shí)施而實(shí)施,最重要的是使用通用語言編寫與業(yè)務(wù)問題一致的領(lǐng)域代碼。
此外僅當(dāng)您要實(shí)現(xiàn)具有復(fù)雜業(yè)務(wù)規(guī)則的微服務(wù)時,才應(yīng)使用DDD方法,諸如CRUD服務(wù)之類的簡單職責(zé)可以通過更簡單的方法進(jìn)行管理。
DDD模式可以協(xié)助劃分微服務(wù)邊界
在已經(jīng)確定的界限上下文,您可以為領(lǐng)域建模:實(shí)體模型、值對象和聚合,DDD與邊界有關(guān),微服務(wù)也與邊界有關(guān)。
盡量保持小型微服務(wù)
劃分界限上下文,要平衡兩個目標(biāo):
創(chuàng)建盡可能小的微服務(wù)(這一點(diǎn)不應(yīng)該成為主要動力)
要避免微服務(wù)之間過密的通信
這兩個目標(biāo)可能彼此矛盾,兩者通過演進(jìn)的方式達(dá)到平衡:
盡可能分解系統(tǒng),直到在下次分解時感到服務(wù)通信迅速增加。
DDD微服務(wù)中的層
DDD定義的多層是為了管控代碼的復(fù)雜性, 這些層是邏輯組件(類似環(huán)環(huán)相扣的齒輪)。
不同的層(例如領(lǐng)域模型層與表示層等)可能具有不同的類型,此時層間類型需要轉(zhuǎn)換。
例如從數(shù)據(jù)庫中加載的實(shí)體,有時候需要做一下修正(截取部分信息、增加信息)才能適配客戶端UI。
領(lǐng)域模型層中的領(lǐng)域?qū)嶓w不應(yīng)傳播到它不屬于的其他區(qū)域(如表示層)
重要的是有一個由聚合根控制的域模型,以確保與該實(shí)體組(聚合)相關(guān)的所有不變式和規(guī)則都是通過單個入口點(diǎn)或(聚合根)執(zhí)行。
訂單DDD微服務(wù)有三層:
應(yīng)用程序?qū)?Ordering.API
領(lǐng)域?qū)?Ordering.Domain
基礎(chǔ)設(shè)施層 Ordering.Infrastructure
三層形成的類庫有清晰且明確的依賴關(guān)系
1. The domain model layer
負(fù)責(zé)表達(dá)業(yè)務(wù)概念、業(yè)務(wù)場景和業(yè)務(wù)規(guī)則。這一層會將技術(shù)細(xì)節(jié)傳遞到基礎(chǔ)設(shè)施層,這一層控制、反映業(yè)務(wù)場景,是業(yè)務(wù)軟件的核心。
領(lǐng)域模型層是表達(dá)業(yè)務(wù)的地方,在編程上體現(xiàn)為捕獲數(shù)據(jù)和行為(具有邏輯方法)的領(lǐng)域?qū)嶓w的類庫
遵循持久性無感知和基礎(chǔ)設(shè)施無感知原則
領(lǐng)域模型層必須完全忽略數(shù)據(jù)持久性細(xì)節(jié),這些持久性任務(wù)應(yīng)由基礎(chǔ)設(shè)施層執(zhí)行,因此,此層不應(yīng)直接依賴基礎(chǔ)設(shè)施,這意味著一個重要規(guī)則是領(lǐng)域模型實(shí)體類應(yīng)為POCO。
領(lǐng)域?qū)嶓w不應(yīng)直接依賴于任何數(shù)據(jù)訪問基礎(chǔ)框架(EF、NHibernate),理想情況下,您的域?qū)嶓w不應(yīng)繼承自或?qū)崿F(xiàn)任何基礎(chǔ)設(shè)施中定義的任何類型。大多數(shù)現(xiàn)代的ORM框架(例如Entity Framework Core)都支持這種方法,因此您的領(lǐng)域模型不會與基礎(chǔ)設(shè)施耦合。
領(lǐng)域模型中遵循持久性無感知原則很重要,但也不應(yīng)忽略持久性問題
理解物理數(shù)據(jù)模型以及它如何映射到您的實(shí)體對象模型仍然非常重要,否則你的設(shè)計將會是空中樓閣。而且,大多數(shù)時候你將本應(yīng)該采用關(guān)系數(shù)據(jù)庫的設(shè)計直接遷移到 NoSQL或面向文檔的數(shù)據(jù)庫,領(lǐng)域模型層很可能不適用(基于存儲技術(shù)和ORM技術(shù),您的實(shí)體模型仍然必須遵守一些約束條件)。
2. Application Layer
定義軟件要執(zhí)行的工作,并引導(dǎo)(充血的領(lǐng)域?qū)ο?#xff09;解決問題。
該層對對業(yè)務(wù)負(fù)責(zé),有時會與其他系統(tǒng)的應(yīng)用程序?qū)咏换ァ?br />該層保持薄:它不包含業(yè)務(wù)規(guī)則或知識,而僅協(xié)調(diào)任務(wù)并將工作委托給下一層的域?qū)ο髤f(xié)作;
它沒有反映業(yè)務(wù)情況的狀態(tài),但是可以具有反映用戶或程序的任務(wù)進(jìn)度的狀態(tài)。
微服務(wù)的應(yīng)用層在.NET中一般表現(xiàn)為WebAPI,webapi實(shí)現(xiàn)交互、遠(yuǎn)程網(wǎng)絡(luò)連接、為UI/Client app提供的外部請求中轉(zhuǎn)。再次強(qiáng)調(diào)webapi不應(yīng)該包含業(yè)務(wù)規(guī)則或領(lǐng)域知識(尤其是用于事務(wù)或更新的領(lǐng)域規(guī)則),這些應(yīng)歸領(lǐng)域模型類庫所有。
應(yīng)用層只協(xié)調(diào)任務(wù),不能保存或定義任何域狀態(tài)(域模型),它將業(yè)務(wù)規(guī)則的執(zhí)行委托給領(lǐng)域模型類本身(聚合根和領(lǐng)域?qū)嶓w),這將最終更新這些領(lǐng)域?qū)嶓w中的數(shù)據(jù)。
總體來看,應(yīng)用層是為實(shí)現(xiàn)前端用例的地方。
3. ?The infrastructure layer
基礎(chǔ)設(shè)施層: 定義如何將最初保存在領(lǐng)域?qū)嶓w中的數(shù)據(jù)持久化到數(shù)據(jù)庫或者其他存儲結(jié)構(gòu)的過程。
一個示例是使用Entity Framework Core代碼實(shí)現(xiàn)存儲庫模式類: 該存儲庫模式類使用DBContext將數(shù)據(jù)持久存儲在關(guān)系數(shù)據(jù)庫中。
根據(jù)前面提到的持久化無感知和基礎(chǔ)設(shè)施無感知原則,基礎(chǔ)設(shè)施層不得“污染”領(lǐng)域模型層。
總結(jié)
在DDD中,應(yīng)用層依賴于領(lǐng)域和基礎(chǔ)設(shè)施層,而基礎(chǔ)設(shè)施依賴于領(lǐng)域?qū)?#xff0c;但是領(lǐng)域?qū)硬灰蕾囉谌魏螌印?/p>
只在領(lǐng)域?qū)泳帉憳I(yè)務(wù)規(guī)則和通用的領(lǐng)域知識,而應(yīng)用層負(fù)責(zé)針對軟件的目標(biāo)來組合、協(xié)調(diào)領(lǐng)域?qū)拥臉I(yè)務(wù)規(guī)則。
領(lǐng)域?qū)拥念I(lǐng)域?qū)嶓w、值類型、聚合根反映了真實(shí)業(yè)務(wù)的核心,需要用一種通用的語言來定義,這樣不管應(yīng)用層多么復(fù)雜,核心領(lǐng)域?qū)幼詭h然不動。
領(lǐng)域?qū)硬荒苤苯右蕾嚺c基礎(chǔ)設(shè)施層,現(xiàn)代ORM框架一般都提出倉儲模型來幫助領(lǐng)域?qū)雍图夹g(shù)設(shè)施層解耦。
意譯自:https://docs.microsoft.com/en-us/dotnet/architecture/microservices/microservice-ddd-cqrs-patterns/ddd-oriented-microservice
https://en.wikipedia.org/wiki/Plain_Old_CLR_Object
https://domainlanguage.com/ddd/
總結(jié)
以上是生活随笔為你收集整理的[半翻] 设计面向DDD的微服务的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 视频号,张小龙的星辰大海
- 下一篇: 借助Redis完成延时任务