聊聊 ASP.NET 6 整潔架構(gòu)開(kāi)發(fā)模板
2023-06-21 18:09:56 來(lái)源:博客園
大家好,我是Edison。
最近看了一些整潔架構(gòu)(CleanArchitecture)的文章,自己和同事也簡(jiǎn)單寫(xiě)了一個(gè)基于整潔架構(gòu)的ASP.NET 6開(kāi)發(fā)模板在玩。這里就僅僅拋個(gè)磚,案例主要以自己根據(jù)小組實(shí)際情況做了一些裁剪,可能不具有通用的應(yīng)用性,大家看看就好。
【資料圖】
整潔架構(gòu)的產(chǎn)生背景微服務(wù)架構(gòu)讓DDD(領(lǐng)域驅(qū)動(dòng)設(shè)計(jì))煥發(fā)了第二春,在DDD的推動(dòng)下,DDD的分層架構(gòu)被逐漸推上了舞臺(tái)。DDD的分層架構(gòu)就有好多種,例如整潔架構(gòu)、CQRS和六邊形架構(gòu)等等,每種架構(gòu)模式雖然提出的時(shí)代和背景不同,但其核心理念都是為了設(shè)計(jì)出“高內(nèi)聚低耦合”的架構(gòu),從而能夠?qū)崿F(xiàn)架構(gòu)的演進(jìn)。
DDD分層架構(gòu)在歐創(chuàng)新老師的《DDD實(shí)戰(zhàn)課》中,給出了一個(gè)優(yōu)化后的DDD四層架構(gòu),我們可以從下面這張圖中看到,從上到下分別是:用戶接口層、應(yīng)用層、領(lǐng)域?qū)雍突A(chǔ)層。
與傳統(tǒng)的三層架構(gòu)不同,DDD四層架構(gòu)的重點(diǎn)在于引入了一個(gè)領(lǐng)域?qū)?。領(lǐng)域?qū)拥淖饔檬?strong>實(shí)現(xiàn)企業(yè)核心業(yè)務(wù)邏輯,通過(guò)各種校驗(yàn)手段保證業(yè)務(wù)的正確性。領(lǐng)域?qū)又饕w現(xiàn)領(lǐng)域模型的業(yè)務(wù)能力,它用來(lái)表達(dá)業(yè)務(wù)概念、業(yè)務(wù)狀態(tài)和業(yè)務(wù)規(guī)則。領(lǐng)域?qū)影壕酆细?、?shí)體、值對(duì)象、領(lǐng)域服務(wù)等領(lǐng)域模型中的領(lǐng)域?qū)ο?。?duì)于領(lǐng)域?qū)?,領(lǐng)域模型的業(yè)務(wù)邏輯主要由實(shí)體和領(lǐng)域服務(wù)來(lái)實(shí)現(xiàn)。對(duì)于實(shí)體,一般建議采用充血模型來(lái)實(shí)現(xiàn)所有與之相關(guān)的業(yè)務(wù)功能。對(duì)于領(lǐng)域服務(wù),一般當(dāng)單個(gè)實(shí)體不能實(shí)現(xiàn)某些功能時(shí),領(lǐng)域服務(wù)才會(huì)出馬,組合聚合內(nèi)的多個(gè)實(shí)體來(lái)實(shí)現(xiàn)復(fù)雜的業(yè)務(wù)邏輯。下圖中展示了傳統(tǒng)的三層架構(gòu)與DDD四層架構(gòu)的對(duì)應(yīng)關(guān)系:
整潔架構(gòu)簡(jiǎn)單介紹簡(jiǎn)而言之,整潔架構(gòu)是組織軟件體系結(jié)構(gòu)的原則,可以輕松面對(duì)未來(lái)的不確定性,方便代碼的重構(gòu)。同時(shí),它可以幫助我們?yōu)樘囟ǖ念I(lǐng)域模型構(gòu)建服務(wù),從而為將來(lái)可能的微服務(wù)體系結(jié)構(gòu)做好準(zhǔn)備。在Jason Taylor的這篇文章中《Clean Architecture with .NET Core: Gettting Started》中給出了一張經(jīng)典的圖:
在整潔架構(gòu)中,所有依賴關(guān)系都向內(nèi)流動(dòng),而核心層不依賴于其他任何層。基礎(chǔ)設(shè)施層和展示層依賴于核心層,而不是彼此依賴。在Jason Taylor給出的圖中,只有三個(gè)圓圈,但在實(shí)際中,你可能需要更多,但是你可以以此作為起點(diǎn),只需要記住讓所有依賴都指向內(nèi)部即可。這里的內(nèi)部,我們可以將其稱為ApplicationCore,也就是Application + Domain。
整潔架構(gòu)模板搭建這里我試著搭建了一個(gè)基于ASP.NET 6的開(kāi)發(fā)模板,展示層有兩種可選:ASP.NET WebAPI / Blazor。需要說(shuō)明是:該模板僅僅是結(jié)合我司實(shí)際情況的構(gòu)想,沒(méi)有遵循DDD的一些原則思想(DDD是個(gè)好東西,但不是所有項(xiàng)目都適用,也不是所有團(tuán)隊(duì)都可以用好),也不具有廣泛應(yīng)用性,各位看官看看一笑而過(guò)就好。
在我司(一家制造業(yè)工廠的IT部),基于我們組的實(shí)際人員情況中(開(kāi)發(fā)基礎(chǔ)能力較弱,以前的工作基本以運(yùn)維為主,很少做開(kāi)發(fā)工作)和開(kāi)發(fā)項(xiàng)目的綜合復(fù)雜度(嚴(yán)格來(lái)說(shuō),復(fù)雜度并不高,以后臺(tái)管理信息系統(tǒng)為主),我不想引入太多DDD的概念增加學(xué)習(xí)成本,因此ValueObject和Domain Service被我移除了,但是充血模型的Entity是我們所倡導(dǎo)的,因此,最終的結(jié)構(gòu)如下圖所示:
對(duì)于展示層,分別使用WebAPI和Blazor實(shí)現(xiàn)API和UI的宿主;對(duì)于核心層(ApplicationCore),包含 Application 和 Domain 兩個(gè).NET 6.0類(lèi)庫(kù)項(xiàng)目。
(1)Application定義了Services、Handlers(對(duì)于MQ的Consumers)、Validators(基于FluentValidation的Validators)以及 各種Models(DTO、VO,以及基于AutoMapper的MappingProfiles)。
(2)Domain則定義了實(shí)體、枚舉、異常、常量等。這一層無(wú)需引入過(guò)多概念,只需要在原有實(shí)體的基礎(chǔ)上,使用充血模型,讓實(shí)體的行為豐富起來(lái)即可,這也可以讓開(kāi)發(fā)人員很快適應(yīng)和模仿。
對(duì)于基礎(chǔ)設(shè)施層,也是一個(gè).NET 6.0類(lèi)庫(kù),主要包含了基于EF Core的上下文(DbContext)、實(shí)體映射關(guān)系(EntityConfiguration)、Repositories、Gateways(針對(duì)依賴的外部接口HttpClient實(shí)現(xiàn),可以用HttpClientFactory來(lái)實(shí)現(xiàn),也可以用WebApiClient之類(lèi)的封裝項(xiàng)目)、Cache(比如RedisClient的注冊(cè))、MessageQueue(比如KafkaClient的注冊(cè),取決于你們組用了什么MQ)等。
除了上面的四層之外,設(shè)計(jì)一個(gè)CrossCuting的Shared類(lèi)庫(kù),用于存放一些各個(gè)層都可以復(fù)用(引用)的幫助類(lèi)、擴(kuò)展方法、基類(lèi)等,用于減少重復(fù)。整個(gè)項(xiàng)目在Visual Studio中的解決方案目錄如下圖所示:
整個(gè)項(xiàng)目在Visual Studio中的解決方案目錄如下圖所示:
最終的依賴關(guān)系如下:(1)Domain類(lèi)庫(kù)只引用Shared類(lèi)庫(kù)(即CrossCutting)。(2)Application類(lèi)庫(kù)引用:Domain、Infrastructure、Shared
這里我們沒(méi)有讓Application不依賴于Infrastructure,是因?yàn)槲覀兊腄B技術(shù)棧已經(jīng)固定,而且大家也比較習(xí)慣于在Infrastructure里邊定義Repository、Gateway等的interface,而不是在Application里面定義這些interface,Infrastructure通過(guò)應(yīng)用Application來(lái)做實(shí)現(xiàn)。
(3)Infrastructure類(lèi)庫(kù)引用:Domain、Shared
(4)Web項(xiàng)目引用:Application、Shared(其實(shí)這里Application引用了Shared,Web項(xiàng)目無(wú)需再添加引用)
(5)WebUI項(xiàng)目引用:Application、Shared(其實(shí)這里Application引用了Shared,Web項(xiàng)目無(wú)需再添加引用)通常情況下,WebAPI和WebUI項(xiàng)目二者只選選擇一個(gè),因此新項(xiàng)目創(chuàng)建好之后,刪除其中一個(gè)。
(6)Application.UnitTests項(xiàng)目引用:Application(7)Domain.UnitTests項(xiàng)目引用:Domain
(8)Web.IntegrationTests項(xiàng)目引用:Web
在實(shí)際模板中,針對(duì)ServiceCollection和ApplicationBuilder寫(xiě)了很多擴(kuò)展方法,用于一些常見(jiàn)組件的注冊(cè),例如Swagger、CAP(Event Bus)、Redis Client、健康檢查EndPoints、KeyCloak鑒權(quán)啟用等等。開(kāi)發(fā)者只需要根據(jù)需要在配置文件中添加或移除對(duì)應(yīng)部分的config即可,這些擴(kuò)展方法會(huì)根據(jù)配置文件中是否有這部分的config來(lái)判斷是否需要注冊(cè)。因此,大部分情況下,小組的開(kāi)發(fā)者要做的僅僅是做減法。比如,如果項(xiàng)目只用到了Cache沒(méi)有用到EventBus,那么只需要在配置中移除EventBus的部分即可,不用改任何一句代碼。又如,通常大部分項(xiàng)目里我們只會(huì)保留一個(gè)UnitTest類(lèi)庫(kù),而不是讓三個(gè)都在項(xiàng)目中,因?yàn)槲覀兊木Σ蛔阋詫?xiě)三種類(lèi)型的Test項(xiàng)目。但是某些大一點(diǎn)的項(xiàng)目,對(duì)質(zhì)量有要求的,我們可能會(huì)寫(xiě)兩中類(lèi)型的Test項(xiàng)目。
模板上傳Nuget倉(cāng)庫(kù)這里我們主要通過(guò)將其發(fā)布為一個(gè)Nuget包上傳到企業(yè)內(nèi)部的Nuget倉(cāng)庫(kù),然后客戶端可以通過(guò)安裝這個(gè)nuget包將其添加到Visual Studio中的項(xiàng)目模板中。
當(dāng)然,也可以直接通過(guò)dotnet new命令直接通過(guò)模板創(chuàng)建新項(xiàng)目。
-- installdotnet new install CleanArchitectureTemplate-- uninstalldotnet new uninstall CleanArchitectureTemplate
同理,當(dāng)將開(kāi)發(fā)模板發(fā)布了新的nuget包,客戶端也可以通過(guò)更新nuget包的方式將模板進(jìn)行更新,以便下次可以使用新的模板進(jìn)行項(xiàng)目的開(kāi)發(fā)。
-- checkdotnet new --update-check-- applydotnet new --update-apply
關(guān)于如何通過(guò)Nuget上傳開(kāi)發(fā)模板,可以參考Microsoft的這一篇文檔:https://learn.microsoft.com/zh-cn/dotnet/core/tools/custom-templates
小結(jié)本文介紹了DDD分層架構(gòu)的背景、整潔架構(gòu)的概念,隨后分享了一個(gè)基于我所在小組的實(shí)際情況的一個(gè)整潔架構(gòu)的模板案例。在實(shí)際情況中,ABP vNext也是一不錯(cuò)的選擇,對(duì)DDD有興趣應(yīng)用的建議仔細(xì)看看。
參考代碼GitHub:https://github.com/EdisonChou/CleanArchitectureTemplate
參考資料Jason Taylor,《Clean Architecture with .NET Core: Gettting Started》
歐創(chuàng)新,極客時(shí)間《DDD實(shí)戰(zhàn)課》
Jacky Fei,《基于ASP.NET 6的整潔架構(gòu)》
Alexander Zhao,《.NET Core整潔架構(gòu)入門(mén)》
Denny Zhang,《領(lǐng)域驅(qū)動(dòng)架構(gòu)及其演變歷史》
作者:周旭龍
出處:https://edisonchou.cnblogs.com
本文版權(quán)歸作者和博客園共有,歡迎轉(zhuǎn)載,但未經(jīng)作者同意必須保留此段聲明,且在文章頁(yè)面明顯位置給出原文鏈接。
關(guān)鍵詞:
相關(guān)閱讀
- (2023-06-21)聊聊 ASP.NET 6 整潔架構(gòu)開(kāi)發(fā)模板
- (2023-06-21)申請(qǐng)英國(guó)留學(xué)需要具備哪些條件?_環(huán)球短訊
- (2023-06-21)2023湖南省職高有哪些?
- (2023-06-21)鄭州高新區(qū)設(shè)置可垂釣區(qū)供市民“親水”-環(huán)球今日?qǐng)?bào)
- (2023-06-21)視訊!造價(jià)工程師幾年造價(jià)工程師幾年延續(xù)注冊(cè)
- (2023-06-21)天天滾動(dòng):河南魯山:熊背鄉(xiāng)血桃節(jié)開(kāi)幕 項(xiàng)目簽約近6.7億元
- (2023-06-21)【熱聞】新手鏟屎官怎么擼寵?貓咪的尾巴告訴你它們哪些心情?快來(lái)了解一下萌寵知識(shí)
- (2023-06-21)世界熱點(diǎn)評(píng)!端午假期,海洋主題新陽(yáng)江服務(wù)區(qū)等你來(lái)打卡
- (2023-06-21)天天看熱訊:注會(huì)考試交完費(fèi)后不知道是否交費(fèi)成功了?交費(fèi)狀態(tài)如何查詢?
- (2023-06-21)李秀滿成立個(gè)人新公司 俞永鎮(zhèn)或加盟
- (2023-06-21)天天滾動(dòng):樓市信號(hào)!存量房貸利率下調(diào)要來(lái)了?
- (2023-06-21)P 的謊言有一個(gè)卷土重來(lái)的機(jī)制,現(xiàn)在我想要它出現(xiàn)在每一個(gè)類(lèi)似靈魂的地方
- (2023-06-21)違規(guī)向房地產(chǎn)業(yè)發(fā)放社團(tuán)貸款,掩蓋資產(chǎn)質(zhì)量真實(shí)性,昆明市東川區(qū)農(nóng)村信用合作聯(lián)社被罰款140萬(wàn)元
- (2023-06-21)環(huán)球精選!興義市向陽(yáng)路小學(xué)民航校區(qū)開(kāi)展教職工消防安全知識(shí)培訓(xùn)活動(dòng)
- (2023-06-21)濱州醫(yī)學(xué)院2023年“全國(guó)碩士研究生招生調(diào)劑服務(wù)系統(tǒng)”第一輪開(kāi)放時(shí)間公告
- (2023-06-21)熱文:淘天、抖音爭(zhēng)奪“微信流量池”?丨南財(cái)號(hào)聯(lián)播
- (2023-06-21)投資策略轉(zhuǎn)變?yōu)檫M(jìn)攻,軟銀孫正義稱ChatGPT令人興奮
- (2023-06-21)中國(guó)最大海上油田累產(chǎn)原油突破5億噸
- (2023-06-21)【獨(dú)家焦點(diǎn)】湖南工業(yè)大學(xué):將捐贈(zèng)儀式變成一堂特殊的思政課
- (2023-06-21)動(dòng)態(tài):汽車(chē)電池管理上的霍爾電流傳感器
- (2023-06-21)速訊:4億,100萬(wàn)片!這個(gè)車(chē)規(guī)功率模塊項(xiàng)目今日開(kāi)工
- (2023-06-21)GPT-4是8x2200億參數(shù)的混合模型?這個(gè)小道消息今天傳瘋了 世界快資訊
- (2023-06-21)vivo V29或在未來(lái)幾周亮相 搭載驍龍778G+移動(dòng)平臺(tái)
- (2023-06-21)FAST發(fā)現(xiàn)迄今最短軌道周期脈沖雙星系統(tǒng)
- (2023-06-21)匯宇制藥向182名激勵(lì)對(duì)象授予290.03萬(wàn)股限制性股票
- (2023-06-21)田棗?野狗?Meiko談下路組昵稱:粉絲怎么開(kāi)心,想怎么叫都行
- (2023-06-21)要聞速遞:國(guó)家外匯管理局:1-5月中國(guó)外匯市場(chǎng)累計(jì)成交101.87萬(wàn)億元人民幣
- (2023-06-21)中國(guó)最大海上油田累產(chǎn)原油突破5億噸
- (2023-06-21)神話秦時(shí)里的劍圣第八區(qū)(神話秦時(shí)里的劍圣)
- (2023-06-21)天天快報(bào)!“小攬運(yùn)”/引入插混系統(tǒng) 新款路虎攬勝極光官圖發(fā)布