From 015d527fef3a13bd87926aa2329f85d2257d3712 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Halil=20=C4=B0brahim=20Kalkan?= Date: Thu, 26 Nov 2020 16:27:09 +0300 Subject: [PATCH] DDD guide: Application Services --- ...main-Driven-Design-Implementation-Guide.md | 74 +++++++++++++++++++ 1 file changed, 74 insertions(+) diff --git a/docs/en/Domain-Driven-Design-Implementation-Guide.md b/docs/en/Domain-Driven-Design-Implementation-Guide.md index 6c4844b299..230288cb28 100644 --- a/docs/en/Domain-Driven-Design-Implementation-Guide.md +++ b/docs/en/Domain-Driven-Design-Implementation-Guide.md @@ -1105,4 +1105,78 @@ While there is a tradeoff between two approaches, we prefer to create Domain Ser ### Application Services +An [Application Service](Application-Services.md) is a stateless service that implements **use cases** of the application. An application service typically **gets and returns DTOs**. It is used by the Presentation Layer. It **uses and coordinates the domain objects** (entities, repositories, etc.) to implement use cases. + +Common principles of an application service are; + +* Implement the **application logic** that is specific to the current use case. Do not implement the core domain logic inside the application services. We will come back to differences between Application Domain logics. +* **Never get or return entities** for an application service method. This breaks the encapsulation of the Domain Layer. Always get and return DTOs. + +**Example: Assign an Issue to a User** + +````csharp +using System; +using System.Threading.Tasks; +using IssueTracking.Users; +using Microsoft.AspNetCore.Authorization; +using Volo.Abp.Application.Services; +using Volo.Abp.Domain.Repositories; + +namespace IssueTracking.Issues +{ + public class IssueAppService : ApplicationService, IIssueAppService + { + private readonly IssueManager _issueManager; + private readonly IRepository _issueRepository; + private readonly IRepository _userRepository; + + public IssueAppService( + IssueManager issueManager, + IRepository issueRepository, + IRepository userRepository) + { + _issueManager = issueManager; + _issueRepository = issueRepository; + _userRepository = userRepository; + } + + [Authorize] + public async Task AssignAsync(IssueAssignDto input) + { + var issue = await _issueRepository.GetAsync(input.IssueId); + var user = await _userRepository.GetAsync(input.UserId); + + await _issueManager.AssignToAsync(issue, user); + + await _issueRepository.UpdateAsync(issue); + } + } +} +```` + +An application service method typically has three steps those are implemented here; + +1. Get the related domain objects from database to implement the use case. +2. Use domain objects (domain services, entities, etc.) to perform the actual operation. +3. Update the changed entities in the database. + +> The last *Update* is not necessary if your are using EF Core since it has a Change Tracking system. If you want to take advantage of this EF Core feature, please see the *Discussion About the Database Independence Principle* section above. + +`IssueAssignDto` in this example is a simple DTO class: + +````csharp +using System; + +namespace IssueTracking.Issues +{ + public class IssueAssignDto + { + public Guid IssueId { get; set; } + public Guid UserId { get; set; } + } +} +```` + +### Data Transfer Objects + TODO \ No newline at end of file