日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

基于ABP落地领域驱动设计-06.正确区分领域逻辑和应用逻辑

發布時間:2023/12/4 编程问答 22 豆豆
生活随笔 收集整理的這篇文章主要介紹了 基于ABP落地领域驱动设计-06.正确区分领域逻辑和应用逻辑 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

系列文章

基于ABP落地領域驅動設計-01.全景圖

基于ABP落地領域驅動設計-02.聚合和聚合根的最佳實踐和原則

基于ABP落地領域驅動設計-03.倉儲和規約最佳實踐和原則

基于ABP落地領域驅動設計-04.領域服務和應用服務的最佳實踐和原則

基于ABP落地領域驅動設計-05.實體創建和更新最佳實踐

圍繞DDDABP Framework兩個核心技術,后面還會陸續發布核心構件實現綜合案例實現系列文章,敬請關注!?ABP Framework 研習社(QQ群:726299208)?ABP Framework 學習及實施DDD經驗分享;示例源碼、電子書共享,歡迎加入!

領域邏輯和應用邏輯

正如前面提到的,領域驅動設計中的業務邏輯拆分為兩部分:領域邏輯應用邏輯

領域邏輯由系統的核心領域規則組成,而應用程序邏輯實現特定于應用程序的用例。

雖然定義很清楚,但實現可能并不容易,常常無法決定哪些代碼應該放在應用層,哪些代碼應該放在領域層。本節試圖解釋這些差異。

多應用層

當你的系統很大時,DDD有助于處理復雜性問題。特別是,在一個領域中開發多個應用,那么領域邏輯與應用邏輯的分離就變得更加重要。

假設你正在構建一個有多個應用程序的系統:

?一個Web應用程序,使用 ASP .NET Core MVC,展示產品給用戶。瀏覽產品,不需要進行身份驗證;只有當用戶執行某些操作時,比如向購物車中添加產品,才會要求登陸。?一個后臺管理應用程序,使用Angular UI+ REST APIs構建。此應用由公司辦公人員做系統管理,比如:編輯產品描述。?一個移動應用程序,和 Web應用程序 相比UI更加簡單,通過REST APIs或其他技術(如:TCP/Socket)與服務器通信。

每一個應用都需要解決不同的需求,實現不同用例(應用服務方法),不同DTO,不同驗證和授權規則等等。

將所有這些邏輯混合到一個應用層中,將使你的服務包含太多的判斷條件和復雜的業務邏輯,使代碼更難開發、維護和測試,并導致潛在的Bug。

如果你有單個領域關聯多個應用程序:

?為每個應用程序或客戶端創建單獨的應用層,在這些單獨層中實現特定于應用的業務邏輯。?使用單個領域層共享核心領域邏輯

這樣的設計使得區分領域邏輯應用邏輯變得更加重要。

為了更清楚地實現,可以為每種應用程序類型創建不同的項目(.csproj)。

例如:

?后臺管理應用創建?IssueTracker.Admin.Application?和?IssueTracker.Admin.Application.Contracts?項目?WEB應用創建?IssueTracker.Public.Application?和?IssueTracker.Public.Application.Contracts?移動應用創建?IssueTracker.Mobile.Application?和?IssueTracker.Mobile.Application.Contracts

示例:正確區分應用邏輯和領域邏輯

本節包含一些應用服務和領域服務示例,討論如何決定在這些服務中放置業務邏輯。

示例:在領域服務中創建 Organization (組織)

public class OrganizationManager:DomainService {private readonly IRepository<Organization> _organizationRepository;private readonly ICurrentUser _currentUser;private readonly IAuthorizationService _authorizationService;private readonly IEmailSender _emailSender;public OrganizationManager(IRepository<Organization> organizationRepository,ICurrentUser currentUser,IAuthorizationService authorizationService,IEmailSender emailSender){_organizationRepository=organizationRepository;_currentUser=currentUser;_authorizationService=authorizationService;_emailSender=emailSender;}//創建組織public async Task<Organization> CreateAsync(string name){//檢測是否存在同名組織,存在則拋出異常。if(await _organizationRepository.AnyAsync(x=>x.Name==name)){throw new BusinessException("IssueTracking:DuplicateOrganizationName");}//檢測是否擁有創建權限await _authorizationService.CheckAsync("OrganizationCreationPermission");//記錄日志Logger.LogDebug($"Creating organization {name} by {_currentUser.UserName}");//創建組織實例var organization = new Organization();//發送提醒郵件await _emailSender.SendAsync("systemadmin@issuetracking.com","新組織","新組織名稱:"+name);//返回組織實例return organization;} }

讓我們一步一步來分析?CreateAsync?方法中的代碼是否都應該放在領域服務中:

?正確:組織名重復檢測,存在重復名稱則拋出異常。該檢測與核心領域規則相關,不允許重名。?錯誤:領域服務不應該進行權限驗證。權限驗證應該放在應用層。?錯誤:記錄日志包含當前用戶的用戶名。領域服務不應該依賴當前用戶,當前用戶(Session)應該是展示層或應用層中的相關概念。?錯誤:創建新組織發送郵件,我們仍然認為這是業務邏輯。可以能會根據用例來創建不同類型郵件。

示例:在應用層創建新組織

public class OrganizationAppService:ApplicationService {private readonly OrganizationManager _organizationManager;private readonly IPaymentService _paymentService;private readonly IEmailSender _emailSender;public OrganizaitonAppService(OrganizationManager organizationManager,IPaymentService paymentService,IEmailSender emailSender){_organizationManager=organizationManager;_paymentService=paymentService;_emailSender=emailSender;}[UnitOfWork][Authorize("OrganizationCreationPermission")]public async Task<Organization> CreateAsync(CreateOrganizationDto input){//支付組織費用await _paymentService.ChargeAsync(CurrentUser.Id,GetOrganizationPrice());//創建組織實例var organization = await _organizationManager.CreateAsync(input.Name);//保存組織到數據庫await _organizationManager.InsertAsync(organization);//發送提醒郵件await _emailSender.SendAsync("systemadmin@issuetracking.com","新組織","新組織名稱:"+name);//返回實例return organization;}private double GetOrganizationPrice(){return 42;//Gets form somewhere...} }

讓我們看看 CreateAsync 方法,一步一步討論其中的代碼是否應該放在應用服務:

?正確:應用服務方法應該是工作單元,ABP框架工作單元系統自動實現,可以不用添加[UnitOfWork]特性。?正確:權限驗證應該放在應用層,可以使用?[Authorize]?特性。?正確:在我們的業務邏輯中創建組織是付費服務,當前操作調用基礎設施服務進行支付操作。?正確:應用服務方法負責保存變更到數據庫。?正確:給系統管理員發送郵件通知。?錯誤:不能返回實體,應該返回DTO。

討論:為什么我們不應該將支付邏輯放在領域服務中?

你可能想知道為什么付款代碼不在?OrganizationManager?里面。這是一件很重要的事情,我們絕不希望付款出錯。

然而,業務的重要性并不意味著要將其視為核心業務邏輯。我們可能有其他的支付用例,在這些用例中,我們不收取費用來創建一個新的組織。

例如:

?后臺辦公系統中的管理員用戶可以創建新組織,不用考慮支付。?系統數據導入、整合、同步,也可能需要在沒有任何支付操作的情況下,創建組織。

如您所見,支付不是創建一個有效組織的必要操作。它是一個特定于用例的應用邏輯。

示例:CRUD操作

public class IssueAppService {private readonly IssueManager _issueManager;public IssueAppService(IssueManager issueManager){_issueManager=issueManager;}public async Task<IssueDto> GetAsync(Guid id){return await _issueManager.GetAsync(id);}public async Task CreateAsync(IssueCreationDto input){await _issueManager.CreateAsync(input);}public async Task UpdateAsync(UpdateIssueDto input){await _issueManager.UpdateAsync(input);}public async Task DeleteAsync(Guid id){await _issueManager.DeleteAsync(id);} }

應用服務并沒有做任何事情,而是委托給領域服務來處理。只接收DTO參數,并傳遞給?IssueManger?。

?不要創建只實現簡單 CRUD 操作的領域服務方法,而不帶任何領域邏輯。?不要傳遞 DTO 給領域服務,或領域服務方法返回 DTO。

應用服務可以直接使用倉儲,實現查詢、創建、更新或刪除數據,除非執行這些操作時需要處理領域邏輯,這種情況下,創建領域服務方法,但只針對那些真正需要的方法。

不要因為將來可能會需要這些CRUD領域服務方法,就去提前創建這些方法! 當需要時再去創建,并重構現有的代碼。由于抽象了應用層,重構領域層不會影響到UI層和其他客戶端。

學習幫助

圍繞DDDABP Framework兩個核心技術,后面還會陸續發布核心構件實現綜合案例實現系列文章,敬請關注!

ABP Framework 研習社(QQ群:726299208)?專注 ABP Framework 學習及DDD實施經驗分享;示例源碼、電子書共享,歡迎加入!

總結

以上是生活随笔為你收集整理的基于ABP落地领域驱动设计-06.正确区分领域逻辑和应用逻辑的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。