基於ASP.NET Core 6.0的整潔架構
- 2022 年 8 月 30 日
- 筆記
大家好,我是張飛洪,感謝您的閱讀,我會不定期和你分享學習心得,希望我的文章能成為你成長路上的墊腳石,讓我們一起精進。
本節將介紹基於ASP.NET Core的整潔架構的設計理念,同時基於理論落地的程式碼模型,包括文件夾、文件、項目的組織形式以及項目的依賴關係,為企業級可擴展的架構奠定基礎。
本節學習主題包括:
- 整潔架構介紹
- 核心層
- 基礎設施層
- 表示層
- 測試管理
- 構建整潔架構解決方案
3.1 整潔架構介紹
很多公司系統多樣,每個系統的分層結構各不相同,這給開發和未來的運維帶來了巨大的成本,分層架構看似很簡單,但保證整個研發中心都使用統一的分層架構就不容易了。
那麼如何保證整個研發中心都使用統一的分層架構,以達到提高編寫程式碼效率、保證工程統一性的目的?
我們推薦行業內目前比較流行的整潔架構。
整潔架構是什麼?簡而言之,它是組織軟體體系結構的原則,可以輕鬆面對未來的不確定性,方便程式碼的重構。同時,它可以幫助我們為特定的領域模型構建服務,從而為將來可能的微服務體系結構做好準備。
我們看下整潔架構的洋蔥示意圖:
在整潔架構中,領域層(Domain)和應用層(Application)是架構的核心層。領域層包含實體、枚舉和常量設置等,應用層則包含數據傳輸對象(DTO)、介面、映射、異常、行為和業務邏輯。
整潔架構和傳統三層架構的不同之處在於依賴的不同,因為企業的核心邏輯是可以跨系統共享的,而應用邏輯或業務邏輯是特定的。所以為了復用,現在,我們不再讓核心層依賴數據訪問和基礎設施,而是顛倒這些依賴關係。如上圖所示,表示層和基礎設施層現在是依賴於我們的核心層,但核心層對任何一層都沒有依賴性。
這種架構必須通過在應用層內添加抽象或介面來實現,這些抽象或介面是在應用層之外的其他層實現的。例如,如果我們想要實現存儲庫模式(Repository),我們一般會在應用層添加一個IRepository介面,而實現放在基礎設施層。
有了這個設計原則,所有依賴項都指向圓的重心,而最內部的領域層對其他層沒有任何依賴性。隨後,表示和基礎設施層依賴於核心層,而不是彼此依賴。這一點非常重要,因為我們希望確保該系統的邏輯保留在核心內,這樣我們就可以重用業務邏輯。我們舉個反例,如果表示層依賴基礎設施層,那麼在發生簡訊通知的時候,這個邏輯就會停留在表示層中,因為它必須協調表示層和基礎設施層之間的交互,如果是這樣,未來我們就很難重用這種邏輯。
如果洋蔥示意圖不好理解,我們可以結合下面扁平化的示意圖來理解。
扁平示意圖:
我們看到我們的應用層處在最底下,它沒有任何依賴項。基礎設施層依賴於應用層,最後整個應用程式變得高度可測試,我們可以快速編寫單元測試、集成測試和功能測試。
下面,我們將把每一層的職責逐步展開介紹,最後我們會通過程式碼(基於.NET 6.0)把整潔架構這套理念落地到我們的解決方案當中。
- 核心層(Core)將包含應用項目和領域項目;
- 基礎設施層(Infrastructure)將包含數據和共享項目;
- 展示層(Presentation)將包含一個WebApi項目。
以上就是基於NET Core解決方案的項目設置和文件夾安排。
3.1.1 核心層(Core)
核心層是整潔架構的中心,因為它本身不會依賴於其他層。核心層包含兩個項目,分別是.Domain和.Application,下面展開描述:
1)領域層(Domain)項目
.Domain項目是一個.NET Standard 2.1類庫,它包含實體、介面、枚舉、DTO等。
領域項目必須有一個空的項目引用,這表明它對任何項目都沒有依賴關係。
2)應用層(Application)項目
.Application項目也是一個.NET Standard 2.1類庫,它定義了介面,但實現不在這一層。該項目還具有CQRS模式的命令和查詢、MediatR的行為、AutoMapper對象映射、異常、模型等。
思考:
如果我們要構建微服務,並意識到核心層中有程式碼會在其他服務中重用,該怎麼辦?
答案:
我們可以抽象出一個共享項目(.Shared),可以作為一個NuGet包,在微服務中共享程式碼。
3.1.2 基礎設施層
基礎設施層包含應用層中定義的介面的實現,內部還包括SMTP、文件系統或web服務等資源,都在這一層中實現。
該層是解決方案中的另一個文件夾目錄,內部包括多個項目,比如數據層和共享層,另外我們還可以添加Identity的項目進行身份驗證(這裡暫時省略)。
1)數據(Data)項目
數據項目是一個NET 6.0類庫項目,用於資料庫持久化,內部包括倉儲類、實體類、數據遷移等內容。
2)共享(Shared)項目
共享項目也是一個NET 6.0類庫項目,該項目包含了不同服務之間的共享程式碼,比如電子郵件、簡訊或日期等。
3.1.3 展示層
展示層是構建web應用程式的地方,我們可以使用ASP.NET Core MVC、ASP.NET Core Web API、單頁應用程式(SPA)或移動應用程式。
1)Web API項目
本影片會使用一個Web API項目和一個網站作為案例演示。
WebApi是基於.NET 6.0構建的一個ASP NET Web API項目,可與任何客戶端應用程式交互,例如web、移動、桌面和物聯網(IoT)。
此外,WebApi依賴於應用層和基礎設施層。
2)客戶端項目
客戶端項目用於用戶介面的展示,我們將採用Vue.js 3進行搭建(在第11節介紹),它也將被歸類在展示層。
3.1.4 測試管理
測試管理項目並不是整潔架構原則的一部分,但是這裡也一併介紹。因為,基於測試驅動的開發是一種好的編程習慣,這裡的測試包括單元測試、功能測試、集成測試和負載測試等。
1)單元測試項目
單元測試是測試程式碼的小部分程式碼,比如特定的方法或者服務。可以使用XUnit、NUnit或MSTest項目創建此項目。
2)集成測試項目
集成測試是測試類庫或組件是否能在一起工作。可以使用XUnit、NUnit或MSTest項目創建此項目。
現在,我們已經完成整潔架構的整體介紹,是時候編碼實現了。
3.2 構建整潔架構解決方案
本小節將通過程式碼落地一個基於整潔架構的物聯網解決方案。該項目的目標是適用大部分物聯網場景,管理員可以在其中添加、刪除、更新和讀取物模型。
本影片的所有命令行都可以在我的部落格上獲得,不想敲命令的同學可以自行獲取。
開始之前,請先打開終端並導航到項目文件的目錄中。
我這裡使用的Hyper終端,對於Windows用戶,請使用PowerShell或Git Bash終端。如果使用PowerShell,請記住使用反斜杠而不是正斜杠。
創建解決方案如果使用IDE(比如Visual Studio 2022)會簡單很多,這裡使用命令行有個用意,一個是嘗鮮,了解命令的構建方式;另一個是考慮將來可能的CI/CD,為自動化開發做準備。
1)創建解決方案
我們運行以下命令創建一個iot文件夾:
mkdir iot
然後進入該目錄:
cd iot
使用dotnet CLI創建一個解決方案:
dotnet new sln
該命令默認使用目錄名稱iot作為解決方案的名稱。
接著,在iot目錄中創建一個src文件夾:
mkdir src
現在,進入src目錄,並分別創建三個目錄:
cd src
mkdir 1.core
mkdir 2.infrastructure
mkdir 3.presentation
2)創建core文件夾
一級目錄和文件夾創建完成後,我們進入core文件夾:
cd 1.core
在core目錄中,我們將創建兩個項目Iot.Domain和Iot.Application:
dotnet new classlib -f netstandard2.1 --name Iot.Domain
dotnet new classlib -f netstandard2.1 --name Iot.Application
以上兩個項目都是基於.NET Standard 2.1,現在進入Iot.Application目錄並創建對Iot.Domain的依賴關係:
cd Iot.Application
dotnet add reference ../Iot.Domain/Iot.Domain.csproj
3)創建infrasturcture文件夾
接下來,我們轉入infrasturcture目錄:
cd ../../2.infrastructure
在該目錄中,我們創建兩個基於.NET 6.0的項目,分別是Iot.Data和Iot.Shared:
dotnet new classlib -f net6.0 --name Iot.Data
dotnet new classlib -f net6.0 --name Iot.Shared
接下來,進入Iot.Data目錄:
cd Iot.Data
創建對Iot.Domain和Iot.Application的依賴
dotnet add reference ../../1.core/Iot.Domain/Iot.Domain.csproj
dotnet add reference ../../1.core/Iot.Application/Iot.Application.csproj
現在,轉到Iot.Shared目錄:
cd ../Iot.Shared
創建對Iot.Application的依賴
dotnet add reference ../../1.core/Iot.Application/Iot.Application.csproj
4)創建presentation文件夾
轉到presentation目錄:
cd ../../3.presentation
創建WebApi項目,並轉入到Iot.WebApi:
dotnet new webapi --name Iot.WebApi
cd Iot.WebApi
創建對Iot.Application和Iot.Data的依賴
dotnet add reference ../../1.core/Iot.Application/Iot.Application.csproj
dotnet add reference ../../2.infrastructure/Iot.Data/Iot.Data.csproj
接下來,創建對Iot.Shared的依賴:
dotnet add reference ../../2.infrastructure/Iot.Shared/Iot.Shared.csproj
5)註冊項目到解決方案
轉到解決方案所在的根目錄:
cd ../../../
註冊所有的項目到解決方案,註冊順序依次:
dotnet sln add src/1.core/Iot.Domain/Iot.Domain.csproj
dotnet sln add src/1.core/Iot.Application/Iot.Application.csproj
dotnet sln add src/2.infrastructure/Iot.Data/Iot.Data.csproj
dotnet sln add src/2.infrastructure/Iot.Shared/Iot.Shared.csproj
dotnet sln add src/3.presentation/Iot.WebApi/Iot.WebApi.csproj
至此,我們已經通過.NET CLI完成了我們解決方案的實現,接下來我們關閉終端並使用Visual Studio 2022打開我們的解決方案,如圖3-3所示:
整潔架構的解決方案示意圖:
3.3本節總結
通過本節的學習,我們了解了什麼是整潔架構,整潔架構的模組內容以及依賴關心,以及它將如何幫助開發人員構建可擴展、可演化、可測試的應用程式,比如為將來從單體向微服務演化打下一定的基礎。
另外,我們還學習了如何在整潔架構中構造測試,最後,如何通過dotnet CLI構建ASP.NET Core的解決方案。
在下一節中,我們將設置我們的資料庫並構建路由和控制器,以了解它們如何處理HTTP請求。