docs/en/framework/architecture/best-practices/domain-services.md
//[doc-seo]
{
"Description": "Learn best practices for implementing Domain Services in your applications, guided by Domain-Driven Design principles."
}
This document offers best practices for implementing Domain Service classes in your modules and applications based on Domain-Driven-Design principles.
Ensure you've read the Domain Services document first.
Manager suffix.For the example of a domain service:
public class IssueManager : DomainService
{
//...
}
Do not define GET methods. GET methods do not change the state of an entity. Hence, use the repository directly in the Application Service instead of Domain Service method.
Do define methods that only mutates data; changes the state of an entity or an aggregate root.
Do not define methods with generic names (like UpdateIssueAsync).
Do define methods with self explanatory names (like AssignToAsync) that implements the specific domain logic.
Do accept valid domain objects as parameters.
public async Task AssignToAsync(Issue issue, IdentityUser user)
{
//...
}
Do throw BusinessException or custom business exception if a validation fails.
public async Task AssignToAsync(Issue issue, IdentityUser user)
{
var openIssueCount = await _issueRepository.GetCountAsync(
i => i.AssignedUserId == user.Id && !i.IsClosed
);
if (openIssueCount >= 3)
{
throw new BusinessException("IssueTracking:ConcurrentOpenIssueLimit");
}
issue.AssignedUserId = user.Id;
}
DTO. Return only domain objects when you need. CurrentUser from the Application Service layer.