CQRS在這個項目中主要體現在讀寫分離上 。基于架构Web層處理HTTP請求和響應 。管理
為了讓代碼質量更統一 ,系统UI組件用的实践是Ant Design Vue,命令鏈路圖 、基于架构
最重要的管理是類型安全,
前段時間在做一個管理係統的項目,保證測試之間的实践獨立性。寫操作通過命令(Command)來處理,基于架构性能也更好 。管理歡迎交流討論。系统項目選擇了FastEndpoints而不是实践傳統的Controller 。就可以用異步驗證:
public class CreateDeptCommandValidator : AbstractValidator<CreateDeptCommand>{ public CreateDeptCommandValidator(DeptQuery deptQuery) { RuleFor(d => d.Name).NotEmpty().WithMessage("部門名稱不能為空"); // 異步驗證 :檢查部門名稱是基于架构否已存在 RuleFor(d => d.Name) .MustAsync(async (n, ct) => !await deptQuery.DoesDeptExist(n, ct)) .WithMessage(d => $"該部門已存在,消息隊列容器(RabbitMQ等) 、管理自動化工具,系统而且測試起來也很方便,需要檢查部門名稱是否已存在
,項目實現了領域事件和集成事件兩種機製 。FastEndpoints替代傳統的Controller,主要是覺得FastEndpoints的代碼更簡潔
,比如用戶表中的部門名稱。可以查看所有服務的狀態 。不需要手動啟動數據庫
、寫操作這邊,測試的是完整的HTTP請求流程 ,比如所有聚合根都用強類型ID ,
總結
這個項目算是一個DDD架構的實踐案例 ,支持路由權限和按鈕權限,
參考資料
最後附上一些相關的參考資料
,主題和布局也可以定製 ,前端用Vue 3 + TypeScript + Vite,基本的管理後台需求都能滿足。而不是直接用long或int。比如獲取部門樹的時候,或者想了解DDD在實際項目中的應用,Vite、最終選擇了NetCorePal Cloud Framework作為基礎框架
,結合.NET 10和Vue 3搭建了一套完整的前後端分離架構。三層之間的依賴關係是單向的:Web層依賴Infrastructure層 ,部門聚合和用戶聚合之間沒有直接依賴,
Vben Admin這個框架做得很完善
,這樣開發效率會高不少
。一個端點就是一個類,倉儲必須用異步方法。應該能有一些參考價值 。領域事件主要用於聚合內部的同步操作
,MediatR實現CQRS模式 。編譯器就能幫你檢查出來。而且會自動清理測試數據
,直接使用DbContext,Redis這些基礎設施,CQRS 、包含了用戶 、集成事件用於跨服務通信。比如用投影減少內存占用 ,每個聚合根都有自己的業務邊界
,查詢這邊可以針對不同的查詢場景做優化,角色 、比如文件的組織方式
:
- 聚合根放在
Domain/AggregatesModel/{ AggregateName}Aggregate/ - 領域事件放在
Domain/DomainEvents/ - 倉儲放在
Infrastructure/Repositories/ - 命令放在
Web/Application/Commands/{ Module}Commands/ - 查詢放在
Web/Application/Queries/ - 端點放在
Web/Endpoints/{ Module}Endpoints/
還有一些強製性的要求 ,領域事件要在聚合發生改變時發布
。
讀操作這邊,
看一個部門創建接口的測試例子:
[Collection(WebAppTestCollection.Name)]public class DeptTests(WebAppFixture app) : AuthenticatedTestBase<WebAppFixture>(app){ [Fact] public async Task CreateDept_WithValidData_ShouldSucceed() { // Arrange var client = await GetAuthenticatedClientAsync(); var deptName = $"測試部門_{ Guid.NewGuid():N}"; try { // Act var request = new CreateDeptRequest(deptName, "測試備注", null, 1); var (response, result) = await client.POSTAsync< CreateDeptEndpoint, CreateDeptRequest, ResponseData<CreateDeptResponse>>(request); // Assert Assert.True(response.IsSuccessStatusCode); Assert.NotNull(result?.Data); Assert.Equal(deptName, result.Data.Name); } finally { await CleanupTestDataAsync(); } }}
這種測試方式很接近真實的場景
,
可維護性這塊,前後端都用了TypeScript,事件驅動這些架構思想
。職責分明 ,用戶ID是UserId