How to:
- Design a clean domain model
- Model your application's use cases as application services
- Connect those well-designed layers to the world outside
Protecting your high quality domain model can be accomplished by applying a so-called ports & adapters or hexagonal architecture.
Some of the keywords for this talk: aggregate design, domain events, application services, commands, queries and events, layered architecture, ports & adapters, hexagonal architecture.
13. Thin controllers, fat models
● "Only briefly visit your
controller, go to your model
as fast as you can."
● In practice: we build services,
lots of them, and large ones
too.
14.
15. The effects of a framework-
driven architecture
● Implicit use case scenarios
● Implicit connections to actors
● Coupling to the framework
16. Why bad?
● Scenarios are interrelated
(legacy spaghetti)
● Domain logic is mixed with
infrastructure logic
● Impossible to switch
frameworks
17. What do we want?
● The ability to focus on domain
logic without thinking about
storage, web service, web
requests, etc.
● The ability to switch to a
different database, framework,
message queue, filesystem, etc.
18. We need to make a split between:
Infrastructure and Domain logic
The intention and the implementation of
communication
19. First: what is domain
logic/infrastructure
1. Saving an uploaded file to a cloud file storage
2. Instantiating an entity by calling its constructor
3. Storing an entity in the database
4. Calculating the total amount for an invoice
5. Making sure that an order has at least one line
6. Publishing a domain event to a message queue
20. Heuristic
● Try describing what the
system does without
mentioning any technology.
● Split the implementation
along these lines.
21.
22. Example: Fixer
We convert the invoice line and total
amounts of the invoice currency by
sending a GET request to Fixer's
/api/latest API endpoint, providing
the invoice currency as the base currency
and EUR as the target currency.
23. Applying the heuristic
"We need to convert the invoice
line and total amounts of the
invoice currency. In order to do
this, we need to find out the
current exchange rate between
the invoice currency and our
standard currency (EUR)."
ExchangeRateProvider
24. Applying the heuristic
"We do this by sending a GET
request to Fixer's /api/latest API
endpoint, providing the invoice
currency as the base currency and
EUR as the target currency. The
result will be a JSON string which we
decode. We'll return a Rate value
object based on the data we receive."
FixerExchangeRateProvider implements
ExchangeRateProvider
27. Split the code in two parts
● One part which shows what
you're trying to accomplish.
● Another part which fills in the
low-level details.
28. What about...
A web controller action?
1. In the controller, only take out the
necessary data from the Request.
2. Call a service that knows nothing about
the web.
29. What about...
Saving an entity to the database?
1. Recognize the need for persistence,
and define an interface for it (e.g. a
repository interface).
2. Provide an implementation that knows
how to talk to your particular database.
31. So far
● We've separated domain logic
from infrastructure
● We can replace the
infrastructure "layer"; domain
logic is independent of it
● We can test complete use case
scenarios without invoking
infrastructure code
34. Hexagonal architecture, or:
Ports & adapters
Port: an intention of a dialog
Adapter: supporting implementation for
the dialog
Hexagon: the application without its
adapters
35. Hexagonal architecture, or:
Ports & adapters
Port: "For saving entities" (represented by
a repository interface with a save()
method)
Adapter: "Save entities by sending SQL
insert/update statements to a MySQL
database" (implemented in a repository
class).
52. Why do developers not
write tests?
Because it involves a learning process on
top of the process of learning to write
code.
53. Why do developers not
write tests?
Because it seems to be possible to skip
the extra effort needed to write tests and
do something easier: write production
code.
54. Why do developers not
write tests?
The feedback loop is very slow: you'll only
learn later that having a test suite is
absolutely required to keep the software
in a presentable state in the long run.
55. So please write your tests
Start learning today;
Reduce the extra effort it takes
And finally: enjoy the increase
in development speed