mirror of https://github.com/abpframework/abp.git
committed by
GitHub
1 changed files with 63 additions and 2 deletions
@ -1,7 +1,68 @@ |
|||||
## Domain Services Best Practices & Conventions |
## Domain Services Best Practices & Conventions |
||||
|
|
||||
> **This document is not ready yet. Please see the [Domain Services](../Domain-Services.md) document.** |
|
||||
|
|
||||
|
### Domain Service |
||||
|
|
||||
|
- **Do** define domain services in the **domain layer**. |
||||
|
- **Do not** create interfaces for the domain services **unless** you have a good reason to (like mock and test different implementations). |
||||
|
- **Do** name your domain service with `Manager` suffix. |
||||
|
|
||||
|
For the example of a domain service: |
||||
|
```cs |
||||
|
public class IssueManager : DomainService |
||||
|
{ |
||||
|
//... |
||||
|
} |
||||
|
``` |
||||
|
|
||||
|
### Domain Service Methods |
||||
|
|
||||
|
- **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. |
||||
|
|
||||
|
```cs |
||||
|
public async Task AssignToAsync(Issue issue, IdentityUser user) |
||||
|
{ |
||||
|
//... |
||||
|
} |
||||
|
``` |
||||
|
|
||||
|
- **Do** throw `BusinessException` or custom business exception if a validation fails. |
||||
|
|
||||
|
- **Do** use domain error codes with unique code-namespace for exception localization. |
||||
|
|
||||
|
```cs |
||||
|
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; |
||||
|
} |
||||
|
``` |
||||
|
|
||||
|
- **Do not** return `DTO`. Return only domain objects when you need. |
||||
|
- **Do not** involve authenticated user logic. Instead, define extra parameter and send the related data of ` CurrentUser` from the Application Service layer. |
||||
|
|
||||
|
|
||||
|
|
||||
## See Also |
## See Also |
||||
|
|
||||
* [Video tutorial](https://abp.io/video-courses/essentials/domain-services) |
* [Video tutorial](https://abp.io/video-courses/essentials/domain-services) |
||||
|
* [Domain Services](../Domain-Services.md) |
||||
|
* [Exception Handling](../Exception-Handling.md) |
||||
Loading…
Reference in new issue