ABP - IO Implementing - Domain - Driven - Design
ABP - IO Implementing - Domain - Driven - Design
Implementing
Domain Driven Design
A practical guide for implementing the Domain
Driven Design with the ABP Framework
CONTENTS
Introduction ………………………………………………………………………………………………….. 4
Goal …………………………………………………………………………………………………………….….…….........…...... 5
2
Implementing Domain Driven Design
CONTENTS
Aggregates ………………………………..……………….…….…………………………….…….………….………....... 29
Repositories …….……………………………………………………………………………………..……….……..…….... 52
Specifications …………………………………………………….……….………………………….……….…….…....... 57
Examples ……………………………………………………..……………………….………….…….……….……..……….... 98
3
Implementing Domain Driven Design
INTRODUCTION
4
Implementing Domain Driven Design
Goal
5
Implementing Domain Driven Design
Simple Code!
If you follow the rules and best practices, your code base will
be simpler and easier to maintain. Your application reacts to
changes faster.
6
Implementing Domain Driven Design
7
Implementing Domain Driven Design
Business Logic places into two layers, the Domain layer and
the Application Layer, while they contain different kinds of
business logic;
8
Implementing Domain Driven Design
9
Implementing Domain Driven Design
11
Implementing Domain Driven Design
12
Implementing Domain Driven Design
13
Implementing Domain Driven Design
14
Implementing Domain Driven Design
15
Implementing Domain Driven Design
Most of the time, API Controllers are just wrappers around the
Application Services to expose them to the remote clients. Since
ABP Framework's Automatic API Controller System
automatically configures and exposes your Application
Services as API Controllers, you typically don't create
Controllers in this project. However, the startup solution includes
it for the cases you need to manually create API controllers.
16
Implementing Domain Driven Design
● IssueTracking.EntityFrameworkCore.DbMigrations is a
special project to manage the Code First database
migrations. There is a separate DbContext in this project
to track the migrations. You typically don't touch this
project much except you need to create a new database
migration or add an application module that has some
database tables and naturally requires to create a new
database migration.
17
Implementing Domain Driven Design
You may wonder why there are two projects for the EF Core. It is
mostly related to modularity. Each module has its own
independent DbContext and your application has also one
DbContext. DbMigrations project contains a union of the
modules to track and apply a single migration path. While
most of the time you don't need to know it, you can see the EF
Core migrations document for more information.
Other Projects
18
Implementing Domain Driven Design
19
Implementing Domain Driven Design
20
Implementing Domain Driven Design
Dashed Dependencies
When you investigate the solution, you will see two more
dependencies shown with the dashed lines in the figure above.
Web project depends on the Application and
EntityFrameworkCore projects which theoretically should not
be like that but actually it is.
This is because the Web is the final project that runs and hosts
the application and the application needs the
implementations of the Application Services and the
Repositories while running.
21
Implementing Domain Driven Design
22
Implementing Domain Driven Design
Common Principles
Before going into details, let's see some overall DDD principles;
23
Implementing Domain Driven Design
24
Implementing Domain Driven Design
Examples;
If you think such features are important for you and you will
never stray from the EF Core, we believe that it is worth
stretching this principle. We still suggest to use the repository
pattern to hide the infrastructure details. But you can assume
that you are using EF Core while designing your entity relations
and writing your application code. You can even reference to the
EF Core NuGet Package from your application layer to be able to
directly use the asynchronous LINQ extension methods, like
ToListAsync() (see the IQueryable & Async Operations section in
the Repositories document for more info).
25
Implementing Domain Driven Design
26
Implementing Domain Driven Design
27
Implementing Domain Driven Design
The examples will use some concepts those are used by GitHub,
like Issue, Repository, Label and User, you are already familiar
with. The figure below shows some of the aggregates,
aggregate roots, entities, value object and the relations
between them:
28
Implementing Domain Driven Design
Aggregates
29
Implementing Domain Driven Design
Business Rules
Single Unit
30
Implementing Domain Driven Design
On the other hand, MongoDB developers will find this rule very
natural. In MongoDB, an aggregate object (with
sub-collections) is saved in a single collection in the database
(while it is distributed into several tables in a relational
database). So, when you get an aggregate, all the
sub-collections are already retrieved as a part of the query,
without any additional configuration.
31
Implementing Domain Driven Design
32
Implementing Domain Driven Design
33
Implementing Domain Driven Design
Transaction Boundary
However, in real life, you may need to change more than one
aggregate instances in a single use case and you need to use
database transactions to ensure atomic update and data
consistency. Because of that, ABP Framework uses an explicit
database transaction for a use case (an application service
method boundary). See the Unit Of Work documentation for
more info.
Serializability
34
Implementing Domain Driven Design
35
Implementing Domain Driven Design
36
Implementing Domain Driven Design
37
Implementing Domain Driven Design
On the other hand, User may have such a Roles collection since
a user doesn't have much roles in practical and it can be useful
to have a list of roles while you are working with a User
Aggregate.
If you think carefully, there is one more problem when Role and
User both have the list of relation when use a non-relational
database, like MongoDB. In this case, the same information is
duplicated in different collections and it will be hard to
maintain data consistency (whenever you add an item to
User.Roles, you need to add it to Role.Users too).
In practical;
38
Implementing Domain Driven Design
For example, see the Aggregate root and the Entity below:
39
Implementing Domain Driven Design
40
Implementing Domain Driven Design
● Initializes sub-collections.
41
Implementing Domain Driven Design
42
Implementing Domain Driven Design
43
Implementing Domain Driven Design
44
Implementing Domain Driven Design
45
Implementing Domain Driven Design
Example:
46
Implementing Domain Driven Design
47
Implementing Domain Driven Design
48
Implementing Domain Driven Design
49
Implementing Domain Driven Design
Domain Services will be explained later. But, now let's see how
it can be implemented in the entity class.
50
Implementing Domain Driven Design
51
Implementing Domain Driven Design
● It makes hard to use the entity. The code that uses the
entity now needs to inject IUserIssueService and pass to
the AssignToAsync method.
Repositories
52
Implementing Domain Driven Design
53
Implementing Domain Driven Design
(the code shows only the properties we need for this example)
The rule says the repository shouldn't know the business rules.
The question here is "What is an inactive issue? Is it a business
rule definition?"
54
Implementing Domain Driven Design
55
Implementing Domain Driven Design
56
Implementing Domain Driven Design
Specifications
57
Implementing Domain Driven Design
58
Implementing Domain Driven Design
59
Implementing Domain Driven Design
60
Implementing Domain Driven Design
61
Implementing Domain Driven Design
62
Implementing Domain Driven Design
63
Implementing Domain Driven Design
Domain Services
64
Implementing Domain Driven Design
65
Implementing Domain Driven Design
66
Implementing Domain Driven Design
We prefer and suggest to use the Manager suffix for the Domain
Services.
67
Implementing Domain Driven Design
Application Services
68
Implementing Domain Driven Design
69
Implementing Domain Driven Design
70
Implementing Domain Driven Design
71
Implementing Domain Driven Design
Define only the properties needed for the use case! Otherwise,
it will be confusing for the clients to use the Application
Service method. You can surely define optional properties, but
they should effect how the use case is working, when the client
provides them.
72
Implementing Domain Driven Design
73
Implementing Domain Driven Design
74
Implementing Domain Driven Design
75
Implementing Domain Driven Design
76
Implementing Domain Driven Design
The example code above returns different DTO types for each
method. As you can guess, there will be a lot of code
duplications for querying data, mapping entities to DTOs.
78
Implementing Domain Driven Design
79
Implementing Domain Driven Design
Discussion
80
Implementing Domain Driven Design
There are some reasons why you should not use input DTO to
Entity auto mapping;
81
Implementing Domain Driven Design
Entity Creation
82
Implementing Domain Driven Design
● If you need to change the Title later, you need to use the
SetTitle method which continues to keep Title in a valid
state.
84
Implementing Domain Driven Design
CreateAsync method;
85
Implementing Domain Driven Design
86
Implementing Domain Driven Design
87
Implementing Domain Driven Design
88
Implementing Domain Driven Design
You may ask "Why didn't IssueManager save the Issue to the
database?". We think it is the responsibility of the Application
Service.
89
Implementing Domain Driven Design
91
Implementing Domain Driven Design
92
Implementing Domain Driven Design
93
Implementing Domain Driven Design
94
Implementing Domain Driven Design
95
Implementing Domain Driven Design
96
Implementing Domain Driven Design
Mixing all these logics into a single application layer makes your
services contain too many if conditions with complicated
business logic makes your code harder to develop, maintain
and test and leads to potential bugs.
97
Implementing Domain Driven Design
● IssueTracker.Admin.Application &
IssueTracker.Admin.Application.Contracts projects for the
Back Office (admin) Application.
● IssueTracker.Public.Application &
IssueTracker.Public.Application.Contracts projects for the
Public Web Application.
● IssueTracker.Mobile.Application &
IssueTracker.Mobile.Application.Contracts projects for the
Mobile Application.
Examples
98
Implementing Domain Driven Design
99
Implementing Domain Driven Design
100
Implementing Domain Driven Design
101
Implementing Domain Driven Design
102
Implementing Domain Driven Design
You may wonder why the payment code is not inside the
OrganizationManager. It is an important thing and we never
want to miss the payment.
● A background-working data
import/integration/synchronization system may also need
to create organizations without any payment operation.
103
Implementing Domain Driven Design
104
Implementing Domain Driven Design
105
Implementing Domain Driven Design
Reference Books
106
www.abp.io