When something is painful
but you can't avoid doing it…
postpone it
When something is painful
but you can't avoid doing it…
delegate it
When something is painful
but you can't avoid doing it…
Do It More Often!
"Bring The Pain Forward!"
Continuous Integration
Pair Programming
Continuous Refactoring
TDD
eXtreme
Programming
"Bring The Pain Forward!"
Are You Agile?
Software Craftsmanship
Victor Rentea
Clean Code Evangelist
VictorRentea.ro
30+ talks, 12 meetups
.NET
Lead Architect
Tech Team Lead and Consultant
Software Craftsman
XP: Pair Programming, Refactoring, TDD
Java Champion
VictorRentea.ro @victorrentea victor.rentea@gmail.com
Independent
Technical Trainer & Coach
HibernateSpring Java 8
Architecture, DDDDesign Patterns
Clean Code Unit Testing, TDD
Java Performance and much more…Scala
180+ days1300 devs6 years
VictorRentea.rovictor.rentea@gmail.com
30 companies
Posting daily on
28
The most important principle
in programming?
29
Single Responsibility Principle
EmployeeManager
-read/persist
-compute pay-roll
-generate PDF report
-manage projects
vs
30
Coupling
vs
31
Don’t Repeat Yourself
32
Keep It Short & Simple
Premature encapsulation is the root of all evilOverengineering
– Adam Bien
33
Keep It Short & Simple
Premature encapsulation is the root of all evilOverengineering
Simpler code Developer Happiness
34
Invisible Magic to reduce effort and risk
Protect the Developers
...
Avoid building an intrusive
Custom Framework
(bugs to learn)

Developer
Comfort
35
Request/Thread Scope
@Autowired
private MyRequestContext requestContext;
... {
entity.setModifiedBy(requestContext.getCurrentUser());
}
@Component
@Scope(value = "request", proxyMode = TARGET_CLASS)
class MyRequestContext { ... }
Request
Metadata
Fear Kills Creativity Simplify Unit Testing
- Strong regression defense
Protect the Developers
36
Developer
Safety
Always Think
Regular Brainstorming
37
Continuous Refactoring
There are NO boring tasks
automate them
38
41
No?
Then Keep Struggling for a
Can you predict the future ?
What features will evolve
super-complex in time?
Simple Design
At all times!
42
- Kent Beck
https://martinfowler.com/bliki/BeckDesignRules.html
2. Reveals Intention
3. No Duplication
4. Fewest Elements
1. Passes the Tests
Rules of Simple Design
43
A Simple Architecture
that Evolves
to Match
the Growing Complexity
This talk is about…
44
Core Principles
Modeling Data
Organizing Logic
The Onion Architecture
Tests. Fear.
Agenda
VictorRentea.ro
You control them!
Entities = your persistent data
45
Entity
They simplify your logic
46
Put small bits of
highly reusable
domain logic in your
Domain Entities
public class Customer {
[...]
public String getFullName() {
return firstName + " " + lastName;
}
public void activate(User user) {
if (status != Status.DRAFT) {
throw new IllegalStateException();
}
status = Status.ACTIVE;
activatedBy = user;
activatedDate = new Date();
}
public boolean isActive() {
return status == Status.ACTIVE;
}
public boolean canPlaceOrders() {
return status == Status.ACTIVE && !isBann
}
47
activatedBy = user;
activatedDate = new Date();
}
public boolean isActive() {
return status == Status.ACTIVE;
}
public boolean canPlaceOrders() {
return status == Status.ACTIVE && !isBann
}
public void addAddress(Address address) {
address.setCustomer(this);
addresses.add(address);
}
public List<Address> getAddresses() {
return Collections.unmodifiableList(
addresses);
}
}
public String toExportString() {
return String.format("%s;%s;%d",
firstName, lastName, isActive()?1:0);
}
BlOAt dAnGeR
Fit
Put small bits of
highly reusable
domain logic in your
Domain Entities
Entityid
48
Small
Immutable
Lombok?
No persistent ID
unlike an Entity
Equal by value
of all fields
Embeddable
In larger entities
Value Object: a grouping of domain data
VO
public class Money {
private final Currency currency;
private final BigDecimal amount;
public Money(Currency currency,
BigDecimal amount) {
this.currency = currency;
this.amount = amount;
}
public Currency getCurrency() {
return currency;
}
public BigDecimal getAmount() {
return amount;
}
public boolean equals(Object other)
{ ... }
}
validate();
Then, you start exposing data to UI
(SPA, WS, JSF, desktop)
UI has different goals
They want data structures to match their screens.
Never expose your Entities in your API
49
isDeletable: true
(to show the Delete button)
I like dumb DTOs
(you'll see soon why)
public fields ?! ! !..
VOEntityid
Logic
public class CustomerDto {
private String fullName;
private String phoneNumber;
private Date birthDate;
public final String getFullName
return fullName;
}
public final void setFullName(S
this.fullName = fullName;
}
public final String getPhoneNum
return phoneNumber;
}
public final void setPhoneNumbe
this.phoneNumber = phoneNumbe
}
public final Date getBirthDate(
return birthDate;
}
public final void setBirthDate(
this.birthDate = birthDate;
}
}
50
Form/Request
View/Response
DTO
SearchCriteria/SearchResult
Data Transfer Objects
DTO
Instead, expose in your API
public class CustomerDto {
public String fullName;
public String phoneNumber;
public Date birthDate;
}
dto.fullName = customer.getFullName();
51
Core Principles
Modeling Data
Organizing Logic
The Onion Architecture
Tests. Fear.
Agenda
52
Complex Conversion?
Extract Mappers
VOEntityid
DTO
Mapper
Logic
API Domain
CustomerDto dto = new CustomerDto();
dto.fullName = customer.getFullName();
dto.birthDate = customer.getBirthDate();
dto.phoneNumber = customer.getPhoneNumber();
CustomerDto dto = new CustomerDto(customer);
63
Start implementing all domain logic in a
Facade
Mapper VOEntityid
DTO
Facade
Facade Domain
Service
Domain
Service
Domain Services
This approach is detailed in Java EE Patterns - Rethinking Best Practices, by Adam Bien
Then extract logic into
-To hide complexity: SRP
-For Reuse: DRY
▪ (across Facades or Services)
≈ Application Service
[DDD]
65
Keep DTOs out!
(parameters and return types)
Mapper VOEntityid
DTO
Facade
Facade Domain
Service
Domain
Service
Domain Services
speak your Domain Model
Convert them to your Domain Objects ASAP
DTOs are fragile
(under enemy control)
* I like them dumb (no methods)
Fç
Validate Data
Façade
Convert Data
Implement Logic
Aspects
- Transactions
- Logging
- Exception Handling*
- Access Control*
66
Facade Roles
DTO
Validator
Mapper
Domain
Service
VOEntityid
67
What do you mean ?
When a class
gets too big
(>~200 lines?)
➔ break it
Extract when it Grows
How?
Find a good class name
to summarize some of
its methods
If I find a good name,
I extract? That’s it?
Exactly!
Piece a cake!
A Good
Name
He-he!☺
“There are only two things
hard in programming:
Cache Invalidation and
Naming Things”
68
SRP
applied to reduce complexity
69
CustomerFacade
saveCustomer()
getCustomer()
searchCustomer()
saveCustomerPreferences()
getCustomerPreferences()
validateAddress()
resetPassword()
checkPassworStrength()
CustomerPreferecesFacade
saveCustomerPreferences()
getCustomerPreferences()
validateAddress()
resetPassword()
checkPassworStrength()
CustomerFacade
saveCustomer()
getCustomer()
searchCustomer()
Controller
Extract when it Grows
at the same level of abstraction
Horizontal Splitting
> 300 lines
AlertService
CompositeOrder
Service
70
Separation by Layers of Abstraction
OrderService DeliveryService
Extract when it Grows
Vertical Extraction
more abstract,
more higher-level
72
Duplication
Pair Programming
Imposed
validate in JS/TS and in Java
Rush/Lazy
Inadvertent
you forget and implement it again
Inter-developer
you didn't knew that was already implemented (Δt=5-10s)
bus factor =2
Practice
Pair Programming
74
Developer Comfort
is essential for
Emerging Architectures
77
78
Core Principles
Modeling Data
Organizing Logic
The Onion Architecture
Tests. Fear.
Agenda
VictorRentea.ro
79
VOEntityid
Domain
Service
Domain
Service
What code would you protect?
Put it in the domain module
Priceless
Domain Logic
Domain Objects
domain
Façade
DTO
Validator
Mapper
F
application
80
domain
depends on domain
VOEntityid
Domain
Service
Domain
Service
81
External
Service
DTO
Domain
Service
Domain
Service
domain
82
External
Service
DTO
Adapter
Domain
Service
Domain
Service
<dependency>domain infrastructure
A huge Adapter® Pattern
- Hide their ugly API
- Handle their Exceptions
- Decouple their DTOs  your Entities
- Validate their evil data
83
External
Service
DTO
IAdapter Adapterimplements
class OrderRepository
implements IOrderRepo {
public Order getById(id){
...
}
}
interface IOrderRepo {
Order getById(id);
}
class OrderService {
@Autowired
IOrderRepository repo;
... {
repo.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
84
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
86
calls
<dependency>
higher-level
module
lower-level
module
HTTP, RMI, …
FTP
JMS
DB
DTO
89
90
VOEntityid
Domain
Service
Domain
Service
IExtSrv
Adapter
IRepo
What code would you protect?
Put it in the domain module
Interfaces for
External Services
you consume
Interfaces for
Repositories
Priceless Domain Logic
Domain Objects
infra
ExtSrv
Adapter
Repo
implem
91
Façade
DTO
Validator
Mapper
VOEntityid
Domain
Service
Domain
Service
IExtSrv
Adapter
IRepo
F
application
The Onion Architecture
Behold,
a.k.a. Hexagonal, Ports-and-Adapters
102
Façade
DTO
Validator
Mapper
VOEntityid
Domain
Service
Domain
Service
IRepo
Repo
implem
F
application
infra
IExtSrv
Adapter
Adapter
WS
Interface
DTO
103
Façade
DTO
Validator
Mapper
VOEntityid
Domain
Service
Domain
Service
IRepo
Repo
implem
F
application
IExtSrv
Adapter
Adapter
WS
Interface
DTO
domain
Pragmatic
for decent apps, 2 modules are enough
104
facade
domain
(+repo)
infrastructure
com.myorg.myapp.
.order. …
.product. …
This grew too big!
I need to
restructure it.
Use-case Optimal Query
105
CALLS
DEPENDS
Breaking a Monolith
DTO
Facade
Infra
.order. …
.product. …
EVENT
TX
FK?
SELECT
MICRO…
"Light CQRS"
com.myorg.myapp.
consistency
😱
"Clean Architecture"
Replicate?
106
archunit.org
ArchRule rule =
classes().that().resideInAPackage("..service..")
.should().onlyBeAccessed()
.byAnyPackage("..controller..", "..service..");
108
109
tardigrade
110
fitness function
111
coupling
performance
scalability
fitness function
security
source code size
114
Core Principles
Modeling Data
Organizing Logic
The Onion Architecture
Tests. Fear.
Agenda
115
Lots of Unit Tests are Good !
A sense of confidence
Developer Courage
Continuous Refactoring
(It’s still a single )
116
As you fight to write Unit Tests,
the Production code gets simpler
118
First couple of unit tests : The most valuable
Test no.
difficulty
Maintainable Tests
Pure Functions
No side effects. No dependencies.
Mock-based
In-memory Emulation
or JPQL tests on H2/* db
Fragile data fixtures
On Real Systems
Eg: Connecting to a real DB
119
𝑓 𝑥, 𝑦 = 𝑥2 + 𝑦2
infrastructure
domain
side effects
122
pure logic
Unit Testing
Like a Pro
(the circle of purity)
▪ 7 Virtutes of a Good Object
▪ NULL – the worst mistake in IT
- https://dzone.com/articles/the-worst-mistake-of-computer-science-1
▪ The Clean Architecture:
- http://blog.8thlight.com/uncle-bob/2012/08/13/the-clean-architecture.html
▪ Some ☺ Programming Jargon
- http://blog.codinghorror.com/new-programming-jargon/
▪ Code quality: WTFs/minute
- http://commadot.com/wtf-per-minute/
▪ SOLID is WRONG
- https://speakerdeck.com/tastapod/why-every-element-of-solid-is-wrong
▪ Good software is written 3 times
- http://www.javaworld.com/article/2072651/becoming-a-great-programmer--
use-your-trash-can.html
▪ Prezi-like effect in PowerPoint 2016: “Morph”
▪ Value Objects vs Entity
- http://enterprisecraftsmanship.com/2016/01/11/entity-vs-value-object-the-
ultimate-list-of-differences/
▪ Extends is bad
- http://www.yegor256.com/2016/09/13/inheritance-is-procedural.html
▪ “Measure Don’t Ask” is TM of Kirk Pepperdine
Further Reading
127
128
Agenda
VictorRentea.ro
Core Principles
Modeling Data
Organizing Logic
The Onion Architecture
Tests. Fear.
129
Core Principles
VictorRentea.ro
Modeling Data
Organizing Logic
The Onion Architecture
Tests. Fear.
AgendaTakeaways
130 VictorRentea.ro
Tests. Fear.
Organizing Logic
The Onion Architecture
Modeling Data
KISS: Avoid overengineering
Magic to protect your Developers
Takeaways
131 VictorRentea.ro
Tests. Fear.
Organizing Logic
The Onion Architecture
Enemy data
KISS: Avoid overengineering
Magic to protect your Developers
in your DTOs: keep them out
Takeaways
132 VictorRentea.ro
Tests. Fear.
Extract when it Grows
The Onion Architecture
KISS: Avoid overengineering
Magic to protect your Developers
: for SRP or DRY
Enemy data in your DTOs: keep them out
Takeaways
133 VictorRentea.ro
Extract when it Grows
The Onion
KISS: Avoid overengineering
Magic to protect your Developers
: for SRP or DRY
Enemy data in your DTOs: keep them out
, DIP: domain agnostic to externals
Tests. Fear.
Takeaways
(Adapt® them)
134 VictorRentea.ro
Extract when it Grows
The Onion
KISS: Avoid overengineering
Magic to protect your Developers
: for SRP or DRY
Enemy data in your DTOs: keep them out
, DIP: domain agnostic to externals
Tests: let them smash your design
Takeaways
(Adapt® them)
135
KISS
136
Keep It simple
142
Put Passion In
All That You Do!!
Thank You!!

Evolving a Clean, Pragmatic Architecture at JBCNConf 2019