The goal of architecture is to simplify the most complex parts of your logic. Any other goal should be secondary to this. The problem is that you can’t always anticipate where the complexity of your application will accumulate, especially when confronted with ever-changing requirements. The only way to keep your code simple is to gradually evolve the architecture without adding useless complexity up front, but always looking out for opportunities to break-down and refactor towards the most simple design that solves the problem. Drawing concepts from the Domain-Driven Development mindset, this talk summarizes the most important lessons learned designing and consulting many real-world projects. Along the way, you’ll hear about Value Objects and Entities, DTOs, Dependency Inversion Principle, Facades, the Onion Architecture and many pragmatic tips and tricks immediately applicable to your day-to-day work.
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
Clean architecture - Protecting the Domain
1.
2. 2 VictorRentea.ro
a training by
= Software architecture refers to the fundamental structures of
a software system and the discipline of creating such structures and
systems. Each structure comprises software elements, relations
among them, and properties of both elements and relations.
3. 3 VictorRentea.ro
a training by
= The Stuff That's Hard to Change Later
= The Art of Drawing Lines (boundaries)
= The Stuff That Matters
6. Hi, I'm Victor Rentea
Java Champion – drinking since 2006
Trainer – 3000+ developers / 80+ companies, since 2013
Speaker – Conferences & Meetups
Hibernate
Spring Java8/FP
Java Performance Reactive Programming
Architecture Clean Code Unit Testing
Java Champion – drinking since 2006
Trainer – 3000+ developers / 80+ companies, since 2013
Speaker – Conferences & Meetups
Hibernate
Spring Java8/FP
7. $
Hibernate
Spring Java8/FP
Java Performance Reactive Programming
Architecture Clean Code Unit Testing
Masterclass
Company
Training
Video
Courses
Talks &
Channel
Join My
Communit
y
Blog
@victorrentea
VictorRentea.ro
victorrentea@gmail.com
8. 8 VictorRentea.ro
a training by
Layers
SUB-DOMAINS
Controller
Service
Repository
APIs
order Product user
customer
Client
10. 10 VictorRentea.ro
a training by
Axiom 1: Logic is simpler if implemented using data structures we control
Smaller: only the 5 required fields, not all 20
OOP: with helper methods inside
Safer: null-safe, guarding invariants, immutable?
Extract Value Objects
Split Large Entities vs BC
Keep DTOs out
14. 14 VictorRentea.ro
a training by
Decouple API from Domain Model
Delete
“canBeDeletedByCurrentUser”: false
To browsers
“dateFormatted”: "1 Iunie 2021"
DTOs are controlled by Frontend
15. 15 VictorRentea.ro
a training by
APIs
To browsers
DTOs are controlled by Frontend DTOs are negotiated
with clients
DTOs can be shared
within the same Bounded Context
Nanoservice
=XXS microservice
eg. 5 devs maintaining
20 microservices
Multiple FEs/mobile: GraphQL
To other systems
Bounded Context A
(TeamA)
Bounded Context B
(TeamB)
1
2
3
X
16. 16 VictorRentea.ro
a training by
Decoupling
DTO
Domain
Model
< >
Price: more classes + mapping
Exception:
Boundary Systems
= Huge Adapters
without own Domain
Software Ecosystem
Generated DTOs:
JSON: .yaml ➔ swagger-gen
XML: .xsd/.wsdl ➔ xjc
17. 17 VictorRentea.ro
a training by
Auto-Generated Mappers
eg. Entity DTO
as long as the field names match,
mapping happens automatically
eg MapStruct
Temptation:
Keep the models in sync
Entities and DTOs should will diverge
18. 18 VictorRentea.ro
a training by
domain
Value Object
Entity
id
Domain
Service
The code you want to protect:
stays in domain module!
Priceless Domain Logic
Domain Objects
What's specific
to your app
20. 20 VictorRentea.ro
a training by
External
Service
DTO
Adapter
Domain
Service
Domain
Service
<dependency>
domain infrastructure
Goal: Keep Your Precious Domain
isolated from external influences
may slip in
DTO
21. VictorRentea.ro
21
External
Service
DTO
IAdapter Adapter
implements
class UserApiClient
implements IUserAdapter {
public User getById(id){
<external call>
}
}
interface IUserAdapter {
User getById(id);
}
class OrderService {
@Autowired
IUserAdapter adapter;
...
adapter.getById(id);
}
express your need in
a domain interface…
and implement it in a
lower-level module…
When you need
to call outside…
so nothing foreign
enters your domain.
Domain
Service
Domain
Service
<dependency>
domain infrastructure
DTO
22. 22 VictorRentea.ro
a training by
calls
Dependency Inversion Principle
<dependency>
higher-level
module
lower-level
module
"Best of OOP"
- Uncle Bob
Abstractions should not depend on details
Low level classes
are not visible
(SOLID Principles)
Dependency Inversion
23. 23 VictorRentea.ro
a training by
calls
<dependency>
higher-level
module
lower-level
module RMI,
HTTP
GRPC..
FTP
Queue
DB
DTO
Dependency Inversion
24. 24 VictorRentea.ro
a training by
Stop Code Dependencies
Dependency Inversion
Package Dependency Checks - by static code analysis
- by compiler
@Test
public void dependencyInversionTest() {
ArchRuleDefinition
.noClasses().that().resideInAPackage("..domain")
.should().dependOnClassesThat().resideInAPackage("..infra")
.check(new ClassFileImporter().importPackages("my.corp.app"));
}
testImplementation com.tngtech.archunit:archunit-junit4:0.15.0 or NDepend (C#)
https://nx.dev/latest/angular/structure/monorepo-tags
https://github.com/MaibornWolff/ts-arch
26. 27 VictorRentea.ro
a training by
infrastructure
EXTERNAL
API
Value Object
Entity
id
Domain
Service
IAdapter
Onion Architecture
Behold, the famous
Database
domain
Repo
Dep Inv
Dep Inv
DTO
Agnostic Domain
application
DTO
Your
Client
Validation
Separate
Persistence
Model
if DB == enemy
Façade
Mapper
Controller
Adapter
Spring Data
IRepo
27. 28 VictorRentea.ro
a training by
28
DTO
Value Object
Entity
id
Domain
Service
application Database
domain
DTO
Onion Architecture
Pragmatic
Agnostic Domain
EXTERNAL
API
Your
Client
Façade
Mapper
Controller
Adapter
IAdapter
IRepo
Dep Inv
28. 29 VictorRentea.ro
a training by
Independent of Intrusive Frameworks
Testable Standalone
without a DB, UI, Web Server, etc...
https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html
Independent of UI
mobile, web, or desktop
Independent of DB
avoid PL/SQL, no vendor lock-in
Independent of External APIs
= external Bounded Contexts
Is an ORM intrusive?
Keep core logic ...
Agnostic Domain
aka Hexagonal
aka Ports-and-Adapters
aka Clean Architecture
Onion Architecture
29. 31 VictorRentea.ro
a training by
Keep Domain Object design
independent of persistence
Decompose large flat Entities with @Embeddable
Avoid useless IDs with @ElementCollection
Constructor constraints are possible, hiding default one
Question entity links. Aren't IDs enough?
Designing Expressive and Performant Persistence Models
https://www.youtube.com/watch?v=iw0tOx7Zbjc
Legacy DB Schema ➔ Separate Models
Mappers ➔ Pain
Avoid bi-directional links
30. 32 VictorRentea.ro
a training by
Axiom 1: Logic is simpler if implemented using data structures we control
Smaller: only the 5 required fields, not all 20
OOP: with helper methods inside
Safer: null-safe, guarding invariants, immutable?
Extract Value Objects
Split Large Entities vs BC
Keep DTOs out
32. 34 VictorRentea.ro
a training by
How many fields it has?
Can you make it immutable?
Tell me about that big entity ...
How do you feel about moving logic inside?
33. 35 VictorRentea.ro
a training by
How many fields it has?
Can you make it immutable?
How do you feel about moving logic inside?
Yes!
(use @Embeddable for JPA)
But, How to identify Value Objects?
Extract Value Objects from Entities:
34. 36 VictorRentea.ro
a training by
Conceptual Whole
Money {amount, currency}
Changes Together
LastModifiedBy/Time
How to identify Value Objects?
Screens
InvoicingDetails
Moves Together
PriceComputationInput
40. 42 VictorRentea.ro
a training by
Axiom 1: Logic is simpler if implemented using data structures we control
Smaller: only the 5 required fields, not all 20
OOP: with helper methods inside
Safer: null-safe, guarding invariants, immutable?
Extract Value Objects
Split Large Entities vs BC
Keep DTOs out
41. Axiom 1: Logic is simpler if implemented using data structures we control
Clean Architecture
Thank you!
victorrentea@gmail.com VictorRentea.ro @victorrentea