Real Life Clean Architecture

Mattia Battiston
Mattia BattistonPassionate Agile Developer & Craftsman
REAL 
LIFE
CLEAN ARCHITECTURE
@BattistonMattia
ABOUT ME
●  from Verona, Italy
●  software dev & continuous improvement
●  Kanban, Lean, Agile “helper”
●  Sky Network Services

Mattia Battiston
@BattistonMattia
mattia.battiston@gmail.com
mattia-battiston
DISCLAIMER #1
MICROSERVICES
“Normal” apps
DISCLAIMER #2
THE ONE WAY
Our experience
(pragmatism, tradeoffs)
Infrequent
deploys
COMMON PROBLEMS
Decisions
taken
too early
Hard to
change
Centered
around
database
Centered
around
frameworks
Business
logic is
spread
everywhere
Focused
on
technical
aspects
Slow, heavy
tests
Hard to
find things
“
The center of your application
is not the database. Nor is it
one or more of the frameworks
you may be using. 
The center of your application
is the use cases of your
application
Unclebob
Source: NODB
CLEAN ARCHITECTURE
Source: The Clean Architecture
THANK YOU!
THE END
Just Kidding,
The fun is about to
start :-)
EXAMPLE PROJECT
https://github.com/mattia-battiston/clean-architecture-example
EXAMPLE DOMAIN: ISP
Entity:
Telephone 
Exchange
Entity:
Broadband 
Access Device
Use case: 
Get Capacity
“Have we got space for
more customers? Can
we sell more
broadband?”

Use case: 
Reconcile
“Has any physical
device changed?
(e.g. new serial
number)”

Use case: 
Get Details
“Details of a
particular
device?”
OUR CLEAN ARCHITECTURE
ENTITIES
USE CASES
REST APIs
JOBS
DATABASE
FILE SYSTEM
NETWORK
DEVICES
DB
I
...
...
CONFIGURATION
coreentrypoints dataproviders
A.k.a (unclebob’s style)
Entities
Use Cases
Configuration
+
 Core: business logic
Entrypoints: access
to the application
Data Providers:
retrieve and store
information
...
Configuration: wires
everything together
* arrows represent dependency
PROJECT STRUCTURE
ENTITY
ENTITIES
USE CASES
REST APIs
JOBS
DATABASE
FILE SYSTEM
NETWORK
DEVICES
DB
I
...
...
CONFIGURATION
coreentrypoints dataproviderscore
ENTITIES
ENTITY
ENTITY
public class Exchange {

private final String code;
private final String name;
private final String postCode;

public Exchange(String code, String name, String postCode) {
this.code = code;
this.name = name;
this.postCode = postCode;
}

// … getters

@Override
public String toString() {
return ...;
}

}
ENTITY
public class BroadbandAccessDevice {

private Exchange exchange;

private String hostname;
private String serialNumber;
private DeviceType type;
private int availablePorts;

public BroadbandAccessDevice(String hostname, ...) {
this.hostname = hostname;
this.serialNumber = serialNumber;
this.type = type;
}

// … (getters, some setters)

@Override
public String toString() {
return ...;
}
}
ENTITY
●  Domain objects
e.g. “Exchange”, “Broadband Access Device”
●  Entity-specific business rules
e.g. hostname format
●  Tiny Types are useful
e.g. Hostname instead of String
●  No Frameworks
USE CASE
ENTITIES
USE CASES
REST APIs
JOBS
DATABASE
FILE SYSTEM
NETWORK
DEVICES
DB
I
...
...
CONFIGURATION
coreentrypoints dataproviders
USE CASES
I
core
USE CASE
USE CASE
public class GetCapacityForExchangeUseCase {

private DoesExchangeExist dataProvider1; 
private GetAvailablePortsOfAllDevicesInExchange dataProvider2;

// … 

public Capacity getCapacity(String exchangeCode) {
failIfExchangeDoesNotExist(exchangeCode);
List<BroadbandAccessDevice> devices = 
dataProvider2
.getAvailablePortsOfAllDevicesInExchange(exchangeCode);
boolean hasAdslCapacity = hasCapacityFor(devices, DeviceType.ADSL);
boolean hasFibreCapacity = hasCapacityFor(devices, DeviceType.FIBRE);
return new Capacity(hasAdslCapacity, hasFibreCapacity);
}

// …

private void failIfExchangeDoesNotExist(String exchangeCode) {
boolean exchangeExists = dataProvider1.doesExchangeExist(exchangeCode);
if(!exchangeExists) throw new ExchangeNotFoundException();
}
}
USE CASE
public interface DoesExchangeExist {
boolean doesExchangeExist(String exchange);
}

public interface GetAvailablePortsOfAllDevicesInExchange {
List<BroadbandAccessDevice> 
getAvailablePortsOfAllDevicesInExchange(String exchangeCode);
}

public class ExchangeNotFoundException extends RuntimeException {
}
USE CASE
●  Pure business logic
e.g. algorithm to calculate capacity
●  Defines Interfaces for the data that it requires
e.g. getAvailablePorts
●  Uses entities and dataproviders
●  Throws business-specific exceptions
●  Not affected by changes in database or presentation
●  Plain Java (no frameworks)
●  We like single-method interfaces 
A.k.a. Interface Segregation
DATA PROVIDER
ENTITIES
USE CASES
REST APIs
JOBS
DATABASE
FILE SYSTEM
NETWORK
DEVICES
DB
I
...
...
CONFIGURATION
coreentrypoints dataproviders
DATABASE
FILE SYSTEM
NETWORK
DEVICES
DB
...
dataproviders
DATA PROVIDER
DATA PROVIDER
public class BroadbandAccessDeviceDatabaseDataProvider 
implements GetAllDeviceHostnames, GetSerialNumberFromModel, ... {

private JdbcTemplate jdbcTemplate;

@Override
public List<String> getAllDeviceHostnames() {
return jdbcTemplate.queryForList(
"SELECT hostname FROM clean_architecture.bb_access_device", 
String.class);
}

@Override
public String getSerialNumber(String hostname) {
try {
return jdbcTemplate.queryForObject(

"SELECT serial_number FROM
clean_architecture.bb_access_device 
WHERE hostname = ?", 

String.class, hostname);
} catch (IncorrectResultSizeDataAccessException e) {
return null;
}
}

// …
DATA PROVIDER
public class BroadbandAccessDeviceNetworkDataProvider 
implements GetSerialNumberFromReality {

private DeviceClient deviceClient;

// …

@Override
public String getSerialNumber(String hostname) {
try {
return deviceClient.getSerialNumber(hostname);
} catch (DeviceConnectionTimeoutException e) {
return null;
}
}

}
DATA PROVIDER
●  Implements Interfaces defined by use case
e.g. retrieving serial number of a device
●  Hides all details about where the data is from
●  Could have multiple implementations
e.g. from DB or from File System
●  Uses whatever framework/library is appropriate
e.g. spring-jdbc, hibernate, snmp4j, etc.
●  If using ORM, you’d have a new set of entities
A.k.a. decoupled from business entities
ENTRYPOINT
ENTITIES
USE CASES
REST APIs
JOBS
DATABASE
FILE SYSTEM
NETWORK
DEVICES
DB
I
...
...
CONFIGURATION
coreentrypoints dataproviders
REST APIs
JOBS
...
entrypoints
ENTRYPOINT
ENTRYPOINT
@RestController
public class GetCapacityForExchangeEndpoint {

public static final String API_PATH = "/exchange/{exchangeCode}/capacity";

private GetCapacityForExchangeUseCase getCapacityForExchangeUseCase;

// …

@RequestMapping(value = API_PATH, method = GET)
public CapacityDto getCapacity(@PathVariable String exchangeCode) {
try {
Capacity capacity = 
getCapacityForExchangeUseCase.getCapacity(exchangeCode);
return toDto(capacity);
} catch (ExchangeNotFoundException e) {
LOGGER.info("Exchange not found: {}", exchangeCode);
throw new NotFoundException();
}
}

private CapacityDto toDto(Capacity capacity) {
return new CapacityDto(
capacity.hasAdslCapacity(), capacity.hasFibreCapacity());
}
}
ENTRYPOINT
public class ReconcileBroadbandAccessDeviceJob implements ScheduledJob {

private ReconcileBroadbandAccessDevicesUseCase useCase;
private final JobResults jobResults;

// …

@Override public String getName() { return "..."; }

@Override public long getInitialDelay() { return 0; }

@Override public long getPeriod() { return 5; }

@Override public TimeUnit getTimeUnit() { return TimeUnit.SECONDS; }

@Override
public void run() {
LOGGER.info("Job Starting: {}...", getName());
JobResultsCount jobResultsCount = jobResults.createJobResultsCount();
OnSuccess success = jobResultsCount::success;
OnFailure failure = jobResultsCount::failure;
reconcileBroadbandAccessDevicesUseCase.reconcile(success, failure);
jobResults.recordJobResults(this, jobResultsCount);
LOGGER.info("Job Completed: {}", getName());
}
}
ENTRYPOINT
●  Fires up a use case
●  Has no business logic
●  Has conversion logic 
e.g. uses DTOs to return result to WEB
●  Hides all details about delivery mechanism
●  GUI would be an entrypoint
e.g. controllers would start use cases
●  Uses whatever framework/library is appropriate
e.g. spring-mvc, jersey, quartz, etc.
CONFIGURATION
ENTITIES
USE CASES
REST APIs
JOBS
DATABASE
FILE SYSTEM
NETWORK
DEVICES
DB
I
...
...
CONFIGURATION
coreentrypoints dataproviders
CONFIGURATION
CONFIGURATION
CONFIGURATION
@Configuration
@EnableAutoConfiguration
@ComponentScan(basePackages = "com.clean.example.configuration")
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}


@Configuration
public class EndpointConfiguration {
@Bean
public GetBroadbandAccessDeviceEndpoint getBroadbandAccessDeviceEndpoint() {
return new GetBroadbandAccessDeviceEndpoint(...);
}
// …other endpoints… 
}


@Configuration
public class WebServerConfiguration {
// …wires web server with framework… 
}
CONFIGURATION
●  Wires everything together
e.g. using Spring or simply initialising objects
●  Isolates and hides frameworks
e.g. Spring is only here
●  Has the “dirty” details to make things work
e.g. initialise datasource, setup web server, etc.
EXAMPLE: GET CAPACITY
Rest 
Entrypoint
Client
Use 
Case
Data 
Provider
GET /exchange/CHELSEA/capacity
useCase.getCapacity(“CHELSEA”);
dataProvider 
.getAvailablePortsOfAllDevicesInExchange
(”CHELSEA”);
SELECT … WHERE code = “CHELSEA”
return broadbandAccessDevices;
countAvailablePortsOfEachType();
decideIfThereIsCapacity();
return capacity;
convertToDto(capacity);
return dto;
Status Code: 200 OK
{"hasADSLCapacity":true,
"hasFibreCapacity":true}
EXAMPLE: RECONCILE DEVICES
Use Case
Job
Entrypoint
Data Provider:
DB
Data Provider:
Network Device
useCase.reconcile(...);
getAllDeviceHostnames()
 "SELECT hostname...”
// For each device:
getSerialNumberFromModel(hostname)
getSerialNumberFromReality(hostname)
"SELECT serial_number...”
SNMPGET … 
if(serialNumberIsDifferent()) {
updateSerialNumber();
success();
}
auditResults();
Coverage
TESTING STRATEGY
Unit Tests - TDD
Acceptance Tests - BDD
Integration Tests
End-to-end Tests
Manual Exploratory
Tests
Cost
UNIT TESTS
ENTITIES
USE CASES
REST APIs
JOBS
DATABASE
FILE SYSTEM
NETWORK
DEVICES
DB
I
...
...
CONFIGURATION
coreentrypoints dataproviders
UNIT TESTs
UNIT TESTs
UNIT TESTs
UNIT TESTs
UNIT TESTs
UNIT TESTs
UNIT TESTS
// …

GetCapacityForExchangeEndpoint endpoint = // class under test
GetCapacityForExchangeUseCase useCase = // mock

@Test
public void returnsTheCapacityForAnExchange() throws Exception {
givenThereIsCapacityForAnExchange();

CapacityDto capacity = endpoint.getCapacity(EXCHANGE_CODE);

assertThat(capacity.getHasADSLCapacity()).isTrue();
assertThat(capacity.getHasFibreCapacity()).isTrue();
}

private void givenThereIsCapacityForAnExchange() {
when(useCase.getCapacity(EXCHANGE_CODE))
.thenReturn(new Capacity(true, true));
}

// …
UNIT TESTS
●  TDD
A.k.a. Tests first, to drive design
●  Cover every little detail
A.k.a. Aim for 100% coverage
●  “Dev to dev” documentation
A.k.a. What should this class do?
●  Test individual classes in isolation, very fast
ACCEPTANCE TESTS
ENTITIES
USE CASES
REST APIs
JOBS
DATABASE
FILE SYSTEM
NETWORK
DEVICES
DB
I
...
...
CONFIGURATION
coreentrypoints dataproviders
ACC. TESTs
(BUS. REQ.)
ACCEPTANCE TESTS
@Notes("Calculates the remaining capacity in an exchange...")
@LinkingNote(message = "End to End test: %s", links =
{GetCapacityForExchangeEndToEndTest.class})
public class GetCapacityForExchangeAcceptanceTest extends YatspecTest {

// …mock the dependencies of the use case… 

GetCapacityForExchangeUseCase useCase = // …my use case

@Test
public void
hasAdslCapacityWhenThereAreAtLeast5AdslPortsAvailableAcrossAllDevices() {
givenSomeAdslDevicesInTheExchangeWithMoreThan5AdslPortsAvailable();

whenTheCapacityForTheExchangeIsRequested();

thenThereIsAdslCapacity();
}

// … 
}
ACCEPTANCE TESTS
ACCEPTANCE TESTS
●  BDD
A.k.a. Conversations with the business
●  Demonstrate business requirements
A.k.a. Aim to cover business scenarios
●  “Business” documentation
A.k.a. What does the system do? 
●  Test use case in isolation, very fast
A.k.a. No GUI, no DB, etc.
●  Use your favourite BDD framework
We use Yatspec
http
INTEGRATION TESTS
ENTITIES
USE CASES
REST APIs
JOBS
DATABASE
FILE SYSTEM
NETWORK
DEVICES
DB
I
...
...
CONFIGURATION
coreentrypoints dataproviders
INTEGRATION
TESTs
INTEGRATION
TESTs
INTEGRATION TESTS
●  Test integration with slow parts
e.g. Http, database
●  “Dev” documentation
A.k.a. Does this work as expected? 
●  Test one layer in isolation
e.g. only rest endpoint, or only data provider
●  Use whatever library makes it easy
e.g. Spring MockMVC; in-memory db
END-TO-END TESTS
ENTITIES
USE CASES
REST APIs
JOBS
DATABASE
FILE SYSTEM
NETWORK
DEVICES
DB
I
...
...
CONFIGURATION
coreentrypoints dataproviders
http
END-TO-END
TESTs
END-TO-END TESTS
●  Test only the critical journeys
e.g. most common happy path
●  Demonstrate “business” end-to-end requirement
●  Start the whole app, very slow
A.k.a. keep these to a minimum
PRO: TESTING STRATEGY
EFFECTIVE
TESTING STRATEGY
Infrequent
deploys
PROBLEMS? FIX!
Decisions
taken
too early
Hard to
change
Centered
around
database
Centered
around
frameworks
Business
logic is
spread
everywhere
Focused
on
technical
aspects
Slow, heavy
tests
Hard to
find things
Effective
Testing
Pyramid
PRO: FRAMEWORKS
FRAMEWORKS ARE
ISOLATED
easy(er) to
change our mind
PRO: FRAMEWORKS
ENTITIES
USE CASES
REST APIs
JOBS
DATABASE
FILE SYSTEM
NETWORK
DEVICES
DB
I
...
...
CONFIGURATION
coreentrypoints dataproviders
Spring WEB
Spring boot
Spring jdbc
snmp4j
quartz
Infrequent
deploys
PROBLEMS? FIX!
Decisions
taken
too early
Hard to
change
Centered
around
database
Centered
around
frameworks
Business
logic is
spread
everywhere
Focused
on
technical
aspects
Slow, heavy
tests
Hard to
find things
Effective
Testing
Pyramid
frameworks
are
Isolated
PRO: DATABASE
INDEPENDENT
FROM DATABASE
PRO: DATABASE
●  No CRUD!
●  RESTful style for reading information
GET /exchange/{exchangeCode}
GET /exchange/{exchangeCode}/capacity
GET /broadbandAccessDevice/{hostname}
●  Custom endpoints for business actions
POST /broadbandAccessDevice/{hostname}/makeLive
PUT /exchange/{exchangeCode}/increaseCapacity
Infrequent
deploys
PROBLEMS? FIX!
Decisions
taken
too early
Hard to
change
Centered
around
database
Centered
around
frameworks
Business
logic is
spread
everywhere
Focused
on
technical
aspects
Slow, heavy
tests
Hard to
find things
Effective
Testing
Pyramid
Independent
from
Database
frameworks
are
Isolated
PRO: SCREAMING ARCHITECTURE
SCREAMS THE
INTENDED USAGE
PRO: SCREAMING ARCHITECTURE
Infrequent
deploys
PROBLEMS? FIX!
Decisions
taken
too early
Hard to
change
Centered
around
database
Centered
around
frameworks
Business
logic is
spread
everywhere
Focused
on
technical
aspects
Slow, heavy
tests
Hard to
find things
Effective
Testing
Pyramid
Independent
from
Database
Screaming
Architecture
frameworks
are
Isolated
PRO: EASY TO FIND THINGS
ALL BUSINESS
LOGIC IS IN 
USE CASE
Infrequent
deploys
PROBLEMS? FIX!
Decisions
taken
too early
Hard to
change
Centered
around
database
Centered
around
frameworks
Business
logic is
spread
everywhere
Focused
on
technical
aspects
Slow, heavy
tests
Hard to
find things
Effective
Testing
Pyramid
Independent
from
Database
Screaming
ArchitectureAll business
logic in
use cases
frameworks
are
Isolated
PRO: MODULES
HARD TO DO THE
WRONG THING
Infrequent
deploys
PROBLEMS? FIX!
Decisions
taken
too early
Hard to
change
Centered
around
database
Centered
around
frameworks
Business
logic is
spread
everywhere
Focused
on
technical
aspects
Slow, heavy
tests
Hard to
find things
Effective
Testing
Pyramid
Independent
from
Database
Screaming
ArchitectureAll business
logic in
use cases
Modules
isolate
changes
frameworks
are
Isolated
PRO: ALWAYS READY
ALWAYS READY TO
DEPLOY
real continuous
integration
Infrequent
deploys
PROBLEMS? FIX!
Decisions
taken
too early
Hard to
change
Centered
around
database
Centered
around
frameworks
Business
logic is
spread
everywhere
Focused
on
technical
aspects
Slow, heavy
tests
Hard to
find things
Effective
Testing
Pyramid
Independent
from
Database
Screaming
ArchitectureAll business
logic in
use cases
Modules
isolate
changes
Always
Ready
frameworks
are
Isolated
PRO: SWARMING
PARALLELISE
WORK
multiple pairs on
the same story
Infrequent
deploys
PROBLEMS? FIX!
Decisions
taken
too early
Hard to
change
Centered
around
database
Centered
around
frameworks
Business
logic is
spread
everywhere
Focused
on
technical
aspects
Slow, heavy
tests
Hard to
find things
Effective
Testing
Pyramid
Independent
from
Database
Screaming
ArchitectureAll business
logic in
use cases
Modules
isolate
changes
Always
Ready
Swarming
frameworks
are
Isolated
PRO: NICE MONOLITH
GOOD MONOLITH 
TO START WITH
clear boundaries
to break on
Infrequent
deploys
PROBLEMS? FIX!
Decisions
taken
too early
Hard to
change
Centered
around
database
Centered
around
frameworks
Business
logic is
spread
everywhere
Focused
on
technical
aspects
Slow, heavy
tests
Hard to
find things
Effective
Testing
Pyramid
Independent
from
Database
Screaming
ArchitectureAll business
logic in
use cases
Modules
isolate
changes
Always
Ready
Swarming
frameworks
are
Isolated
Nice
Monolith
CON: DUPLICATION
PERCEIVED
DUPLICATION OF
CODE
be pragmatic
Infrequent
deploys
PROBLEMS? FIX!
Decisions
taken
too early
Hard to
change
Centered
around
database
Centered
around
frameworks
Business
logic is
spread
everywhere
Focused
on
technical
aspects
Slow, heavy
tests
Hard to
find things
Effective
Testing
Pyramid
Independent
from
Database
Screaming
ArchitectureAll business
logic in
use cases
Modules
isolate
changes
Always
Ready
Swarming
frameworks
are
Isolated
Nice
Monolith
Duplication
CON: IT NEEDS LOGIC
YOU NEED
INTERESTING
BUSINESS LOGIC
CON: IT NEEDS LOGIC
ENDPOINT
// … 
@RequestMapping(value = API_PATH, method = GET)
public BroadbandAccessDeviceDto getDetails(@PathVariable String hostname) {
try {
BroadbandAccessDevice deviceDetails = 
useCase.getDeviceDetails(hostname);
return toDto(deviceDetails);
} catch (DeviceNotFoundException e) {
throw new NotFoundException();
}
}
// … 

USE CASE
// … 
public BroadbandAccessDevice getDeviceDetails(String hostname) {
BroadbandAccessDevice device = dataProvider.getDetails(hostname);
return device;
}
// … 


DATA PROVIDER
// … 
return "SELECT ...";
Infrequent
deploys
Always
Ready
PROBLEMS? FIX!
Decisions
taken
too early
Hard to
change
Centered
around
database
Centered
around
frameworks
Business
logic is
spread
everywhere
Focused
on
technical
aspects
Slow, heavy
tests
Hard to
find things
Effective
Testing
Pyramid
frameworks
are
Isolated
Independent
from
Database
Screaming
ArchitectureAll business
logic in
use cases
Modules
isolate
changes
Nice
Monolith Swarming
Duplication
Needs
Interesting
Logic
KEY TAKEAWAY
“
The center of your application is the
use cases of your application
Unclebob
RESOURCES
Example Project (with all code shown in the presentation)
●  Clean Architecture Example 
https://github.com/mattia-battiston/clean-architecture-example 

Blogs & Articles
●  The Clean Architecture 
https://blog.8thlight.com/uncle-bob/2012/08/13/the-clean-architecture.html
●  Screaming Architecture
http://blog.8thlight.com/uncle-bob/2011/09/30/Screaming-Architecture.html
●  NODB 
https://blog.8thlight.com/uncle-bob/2012/05/15/NODB.html
●  Hexagonal Architecture 
http://alistair.cockburn.us/Hexagonal+architecture

Videos & Presentations
●  Clean Coders ep. 7: Architecture, Use Cases, and High Level Design
https://cleancoders.com/episode/clean-code-episode-7/show 
●  Robert C. Martin - Clean Architecture 
https://vimeo.com/43612849
●  Robert C. Martin - Clean Architecture and Design
https://www.youtube.com/watch?v=Nsjsiz2A9mg
really, really appreciated! Help me improve
@BattistonMattia 
mattia.battiston@gmail.com
mattia-battiston
THANK YOU!
1 of 80

Recommended

Clean Architecture by
Clean ArchitectureClean Architecture
Clean ArchitectureBadoo
3.3K views61 slides
Introducing Clean Architecture by
Introducing Clean ArchitectureIntroducing Clean Architecture
Introducing Clean ArchitectureRoc Boronat
3K views41 slides
Anatomy of a Spring Boot App with Clean Architecture - Spring I/O 2023 by
Anatomy of a Spring Boot App with Clean Architecture - Spring I/O 2023Anatomy of a Spring Boot App with Clean Architecture - Spring I/O 2023
Anatomy of a Spring Boot App with Clean Architecture - Spring I/O 2023Steve Pember
1.9K views73 slides
SOLID Principles and The Clean Architecture by
SOLID Principles and The Clean ArchitectureSOLID Principles and The Clean Architecture
SOLID Principles and The Clean ArchitectureMohamed Galal
669 views36 slides
Clean architecture by
Clean architectureClean architecture
Clean architectureandbed
10.7K views28 slides
A Separation of Concerns: Clean Architecture on Android by
A Separation of Concerns: Clean Architecture on AndroidA Separation of Concerns: Clean Architecture on Android
A Separation of Concerns: Clean Architecture on AndroidOutware Mobile
5.5K views85 slides

More Related Content

What's hot

Clean architecture by
Clean architectureClean architecture
Clean architecture.NET Crowd
3.5K views56 slides
Example Mapping in the Wild by
Example Mapping in the WildExample Mapping in the Wild
Example Mapping in the WildCeri Shaw
457 views31 slides
Domain Driven Design 101 by
Domain Driven Design 101Domain Driven Design 101
Domain Driven Design 101Richard Dingwall
39.6K views55 slides
Domain Driven Design (DDD) by
Domain Driven Design (DDD)Domain Driven Design (DDD)
Domain Driven Design (DDD)Tom Kocjan
13.2K views41 slides
Domain Driven Design by
Domain Driven DesignDomain Driven Design
Domain Driven DesignRyan Riley
9.8K views32 slides
Clean architecture - Protecting the Domain by
Clean architecture - Protecting the DomainClean architecture - Protecting the Domain
Clean architecture - Protecting the DomainVictor Rentea
652 views41 slides

What's hot(20)

Clean architecture by .NET Crowd
Clean architectureClean architecture
Clean architecture
.NET Crowd3.5K views
Example Mapping in the Wild by Ceri Shaw
Example Mapping in the WildExample Mapping in the Wild
Example Mapping in the Wild
Ceri Shaw457 views
Domain Driven Design (DDD) by Tom Kocjan
Domain Driven Design (DDD)Domain Driven Design (DDD)
Domain Driven Design (DDD)
Tom Kocjan13.2K views
Domain Driven Design by Ryan Riley
Domain Driven DesignDomain Driven Design
Domain Driven Design
Ryan Riley9.8K views
Clean architecture - Protecting the Domain by Victor Rentea
Clean architecture - Protecting the DomainClean architecture - Protecting the Domain
Clean architecture - Protecting the Domain
Victor Rentea652 views
clean code book summary - uncle bob - English version by saber tabatabaee
clean code book summary - uncle bob - English versionclean code book summary - uncle bob - English version
clean code book summary - uncle bob - English version
saber tabatabaee770 views
Finally, easy integration testing with Testcontainers by Rudy De Busscher
Finally, easy integration testing with TestcontainersFinally, easy integration testing with Testcontainers
Finally, easy integration testing with Testcontainers
Rudy De Busscher987 views
Refactoring for Domain Driven Design by David Berliner
Refactoring for Domain Driven DesignRefactoring for Domain Driven Design
Refactoring for Domain Driven Design
David Berliner9.1K views
The aggregate is dead! Long live the aggregate! - SpringIO.pdf by Sara Pellegrini
The aggregate is dead! Long live the aggregate! - SpringIO.pdfThe aggregate is dead! Long live the aggregate! - SpringIO.pdf
The aggregate is dead! Long live the aggregate! - SpringIO.pdf
Sara Pellegrini160 views
Testing with JUnit 5 and Spring by VMware Tanzu
Testing with JUnit 5 and SpringTesting with JUnit 5 and Spring
Testing with JUnit 5 and Spring
VMware Tanzu1.8K views
Hexagonal architecture with Spring Boot by Mikalai Alimenkou
Hexagonal architecture with Spring BootHexagonal architecture with Spring Boot
Hexagonal architecture with Spring Boot
Mikalai Alimenkou8.8K views
Mockito a simple, intuitive mocking framework by Phat VU
Mockito   a simple, intuitive mocking frameworkMockito   a simple, intuitive mocking framework
Mockito a simple, intuitive mocking framework
Phat VU1.6K views
Applied Domain-Driven Design Blueprints for Jakarta EE by Jakarta_EE
Applied Domain-Driven Design Blueprints for Jakarta EEApplied Domain-Driven Design Blueprints for Jakarta EE
Applied Domain-Driven Design Blueprints for Jakarta EE
Jakarta_EE834 views
Java 8 Lambda Built-in Functional Interfaces by Ganesh Samarthyam
Java 8 Lambda Built-in Functional InterfacesJava 8 Lambda Built-in Functional Interfaces
Java 8 Lambda Built-in Functional Interfaces
Ganesh Samarthyam3.2K views
Domain Driven Design and Hexagonal Architecture with Rails by Declan Whelan
Domain Driven Design and Hexagonal Architecture with RailsDomain Driven Design and Hexagonal Architecture with Rails
Domain Driven Design and Hexagonal Architecture with Rails
Declan Whelan8.7K views

Similar to Real Life Clean Architecture

Arquitecturas de microservicios - Medianet Software by
Arquitecturas de microservicios   -  Medianet SoftwareArquitecturas de microservicios   -  Medianet Software
Arquitecturas de microservicios - Medianet SoftwareErnesto Hernández Rodríguez
1.8K views54 slides
From Legacy to Hexagonal (An Unexpected Android Journey) by
From Legacy to Hexagonal (An Unexpected Android Journey)From Legacy to Hexagonal (An Unexpected Android Journey)
From Legacy to Hexagonal (An Unexpected Android Journey)Jose Manuel Pereira Garcia
3.8K views87 slides
Powerful persistence layer with Google Guice & MyBatis by
Powerful persistence layer with Google Guice & MyBatisPowerful persistence layer with Google Guice & MyBatis
Powerful persistence layer with Google Guice & MyBatissimonetripodi
3.9K views16 slides
Don't Make Android Bad... Again by
Don't Make Android Bad... AgainDon't Make Android Bad... Again
Don't Make Android Bad... AgainPedro Vicente
936 views101 slides
比XML更好用的Java Annotation by
比XML更好用的Java Annotation比XML更好用的Java Annotation
比XML更好用的Java Annotationjavatwo2011
1K views45 slides

Similar to Real Life Clean Architecture(20)

Powerful persistence layer with Google Guice & MyBatis by simonetripodi
Powerful persistence layer with Google Guice & MyBatisPowerful persistence layer with Google Guice & MyBatis
Powerful persistence layer with Google Guice & MyBatis
simonetripodi3.9K views
Don't Make Android Bad... Again by Pedro Vicente
Don't Make Android Bad... AgainDon't Make Android Bad... Again
Don't Make Android Bad... Again
Pedro Vicente936 views
比XML更好用的Java Annotation by javatwo2011
比XML更好用的Java Annotation比XML更好用的Java Annotation
比XML更好用的Java Annotation
javatwo20111K views
Overview of Android Infrastructure by Alexey Buzdin
Overview of Android InfrastructureOverview of Android Infrastructure
Overview of Android Infrastructure
Alexey Buzdin5.5K views
Overview of Android Infrastructure by C.T.Co
Overview of Android InfrastructureOverview of Android Infrastructure
Overview of Android Infrastructure
C.T.Co424 views
Testing in android by jtrindade
Testing in androidTesting in android
Testing in android
jtrindade301 views
NET Systems Programming Learned the Hard Way.pptx by petabridge
NET Systems Programming Learned the Hard Way.pptxNET Systems Programming Learned the Hard Way.pptx
NET Systems Programming Learned the Hard Way.pptx
petabridge283 views
Proxy Deep Dive JUG Saxony Day 2015-10-02 by Sven Ruppert
Proxy Deep Dive JUG Saxony Day 2015-10-02Proxy Deep Dive JUG Saxony Day 2015-10-02
Proxy Deep Dive JUG Saxony Day 2015-10-02
Sven Ruppert4.2K views
Bring the fun back to java by ciklum_ods
Bring the fun back to javaBring the fun back to java
Bring the fun back to java
ciklum_ods640 views
Networking and Data Access with Eqela by jobandesther
Networking and Data Access with EqelaNetworking and Data Access with Eqela
Networking and Data Access with Eqela
jobandesther1.7K views
A portlet-API based approach for application integration by whabicht
A portlet-API based approach for application integrationA portlet-API based approach for application integration
A portlet-API based approach for application integration
whabicht1.3K views
My way to clean android - Android day salamanca edition by Christian Panadero
My way to clean android - Android day salamanca editionMy way to clean android - Android day salamanca edition
My way to clean android - Android day salamanca edition
Christian Panadero5.2K views
T2 reading 20101126 by Go Tanaka
T2 reading 20101126T2 reading 20101126
T2 reading 20101126
Go Tanaka558 views
An introduction to Test Driven Development on MapReduce by Ananth PackkilDurai
An introduction to Test Driven Development on MapReduceAn introduction to Test Driven Development on MapReduce
An introduction to Test Driven Development on MapReduce

More from Mattia Battiston

Agile metrics for predicting the future [2021] by
Agile metrics for predicting the future [2021]Agile metrics for predicting the future [2021]
Agile metrics for predicting the future [2021]Mattia Battiston
281 views60 slides
Unlocking your team's potential with pair programming (workshop) by
Unlocking your team's potential with pair programming (workshop)Unlocking your team's potential with pair programming (workshop)
Unlocking your team's potential with pair programming (workshop)Mattia Battiston
382 views12 slides
Agile metrics for predicting the future by
Agile metrics for predicting the futureAgile metrics for predicting the future
Agile metrics for predicting the futureMattia Battiston
2.4K views80 slides
The Science of Happiness by
The Science of HappinessThe Science of Happiness
The Science of HappinessMattia Battiston
4K views31 slides
Super chickens are not safe by
Super chickens are not safeSuper chickens are not safe
Super chickens are not safeMattia Battiston
754 views17 slides
The Science of Happiness [OLD VERSION] by
The Science of Happiness [OLD VERSION]The Science of Happiness [OLD VERSION]
The Science of Happiness [OLD VERSION]Mattia Battiston
808 views31 slides

More from Mattia Battiston(9)

Agile metrics for predicting the future [2021] by Mattia Battiston
Agile metrics for predicting the future [2021]Agile metrics for predicting the future [2021]
Agile metrics for predicting the future [2021]
Mattia Battiston281 views
Unlocking your team's potential with pair programming (workshop) by Mattia Battiston
Unlocking your team's potential with pair programming (workshop)Unlocking your team's potential with pair programming (workshop)
Unlocking your team's potential with pair programming (workshop)
Mattia Battiston382 views
Agile metrics for predicting the future by Mattia Battiston
Agile metrics for predicting the futureAgile metrics for predicting the future
Agile metrics for predicting the future
Mattia Battiston2.4K views
The Science of Happiness [OLD VERSION] by Mattia Battiston
The Science of Happiness [OLD VERSION]The Science of Happiness [OLD VERSION]
The Science of Happiness [OLD VERSION]
Mattia Battiston808 views
Kanban Metrics in practice for leading Continuous Improvement by Mattia Battiston
Kanban Metrics in practice for leading Continuous ImprovementKanban Metrics in practice for leading Continuous Improvement
Kanban Metrics in practice for leading Continuous Improvement
Mattia Battiston4.3K views
Metriche Kanban in pratica a Sky UK [ITA] by Mattia Battiston
Metriche Kanban in pratica a Sky UK [ITA]Metriche Kanban in pratica a Sky UK [ITA]
Metriche Kanban in pratica a Sky UK [ITA]
Mattia Battiston3.8K views
Kanban Metrics in practice at Sky Network Services by Mattia Battiston
Kanban Metrics in practice at Sky Network ServicesKanban Metrics in practice at Sky Network Services
Kanban Metrics in practice at Sky Network Services
Mattia Battiston7.3K views

Recently uploaded

Consulting for Data Monetization Maximizing the Profit Potential of Your Data... by
Consulting for Data Monetization Maximizing the Profit Potential of Your Data...Consulting for Data Monetization Maximizing the Profit Potential of Your Data...
Consulting for Data Monetization Maximizing the Profit Potential of Your Data...Flexsin
15 views10 slides
Tridens DevOps by
Tridens DevOpsTridens DevOps
Tridens DevOpsTridens
9 views28 slides
DSD-INT 2023 Dam break simulation in Derna (Libya) using HydroMT_SFINCS - Prida by
DSD-INT 2023 Dam break simulation in Derna (Libya) using HydroMT_SFINCS - PridaDSD-INT 2023 Dam break simulation in Derna (Libya) using HydroMT_SFINCS - Prida
DSD-INT 2023 Dam break simulation in Derna (Libya) using HydroMT_SFINCS - PridaDeltares
18 views9 slides
SAP FOR TYRE INDUSTRY.pdf by
SAP FOR TYRE INDUSTRY.pdfSAP FOR TYRE INDUSTRY.pdf
SAP FOR TYRE INDUSTRY.pdfVirendra Rai, PMP
23 views3 slides
Unleash The Monkeys by
Unleash The MonkeysUnleash The Monkeys
Unleash The MonkeysJacob Duijzer
7 views28 slides
El Arte de lo Possible by
El Arte de lo PossibleEl Arte de lo Possible
El Arte de lo PossibleNeo4j
38 views35 slides

Recently uploaded(20)

Consulting for Data Monetization Maximizing the Profit Potential of Your Data... by Flexsin
Consulting for Data Monetization Maximizing the Profit Potential of Your Data...Consulting for Data Monetization Maximizing the Profit Potential of Your Data...
Consulting for Data Monetization Maximizing the Profit Potential of Your Data...
Flexsin 15 views
Tridens DevOps by Tridens
Tridens DevOpsTridens DevOps
Tridens DevOps
Tridens9 views
DSD-INT 2023 Dam break simulation in Derna (Libya) using HydroMT_SFINCS - Prida by Deltares
DSD-INT 2023 Dam break simulation in Derna (Libya) using HydroMT_SFINCS - PridaDSD-INT 2023 Dam break simulation in Derna (Libya) using HydroMT_SFINCS - Prida
DSD-INT 2023 Dam break simulation in Derna (Libya) using HydroMT_SFINCS - Prida
Deltares18 views
El Arte de lo Possible by Neo4j
El Arte de lo PossibleEl Arte de lo Possible
El Arte de lo Possible
Neo4j38 views
DSD-INT 2023 3D hydrodynamic modelling of microplastic transport in lakes - J... by Deltares
DSD-INT 2023 3D hydrodynamic modelling of microplastic transport in lakes - J...DSD-INT 2023 3D hydrodynamic modelling of microplastic transport in lakes - J...
DSD-INT 2023 3D hydrodynamic modelling of microplastic transport in lakes - J...
Deltares9 views
DSD-INT 2023 Baseline studies for Strategic Coastal protection for Long Islan... by Deltares
DSD-INT 2023 Baseline studies for Strategic Coastal protection for Long Islan...DSD-INT 2023 Baseline studies for Strategic Coastal protection for Long Islan...
DSD-INT 2023 Baseline studies for Strategic Coastal protection for Long Islan...
Deltares11 views
Geospatial Synergy: Amplifying Efficiency with FME & Esri ft. Peak Guest Spea... by Safe Software
Geospatial Synergy: Amplifying Efficiency with FME & Esri ft. Peak Guest Spea...Geospatial Synergy: Amplifying Efficiency with FME & Esri ft. Peak Guest Spea...
Geospatial Synergy: Amplifying Efficiency with FME & Esri ft. Peak Guest Spea...
Safe Software412 views
DSD-INT 2023 Delft3D FM Suite 2024.01 1D2D - Beta testing programme - Geertsema by Deltares
DSD-INT 2023 Delft3D FM Suite 2024.01 1D2D - Beta testing programme - GeertsemaDSD-INT 2023 Delft3D FM Suite 2024.01 1D2D - Beta testing programme - Geertsema
DSD-INT 2023 Delft3D FM Suite 2024.01 1D2D - Beta testing programme - Geertsema
Deltares17 views
A first look at MariaDB 11.x features and ideas on how to use them by Federico Razzoli
A first look at MariaDB 11.x features and ideas on how to use themA first look at MariaDB 11.x features and ideas on how to use them
A first look at MariaDB 11.x features and ideas on how to use them
Federico Razzoli45 views
Fleet Management Software in India by Fleetable
Fleet Management Software in India Fleet Management Software in India
Fleet Management Software in India
Fleetable11 views
DSD-INT 2023 Wave-Current Interaction at Montrose Tidal Inlet System and Its ... by Deltares
DSD-INT 2023 Wave-Current Interaction at Montrose Tidal Inlet System and Its ...DSD-INT 2023 Wave-Current Interaction at Montrose Tidal Inlet System and Its ...
DSD-INT 2023 Wave-Current Interaction at Montrose Tidal Inlet System and Its ...
Deltares9 views
Neo4j y GenAI by Neo4j
Neo4j y GenAI Neo4j y GenAI
Neo4j y GenAI
Neo4j42 views
Citi TechTalk Session 2: Kafka Deep Dive by confluent
Citi TechTalk Session 2: Kafka Deep DiveCiti TechTalk Session 2: Kafka Deep Dive
Citi TechTalk Session 2: Kafka Deep Dive
confluent17 views
DSD-INT 2023 Next-Generation Flood Inundation Mapping for Taiwan - Delft3D FM... by Deltares
DSD-INT 2023 Next-Generation Flood Inundation Mapping for Taiwan - Delft3D FM...DSD-INT 2023 Next-Generation Flood Inundation Mapping for Taiwan - Delft3D FM...
DSD-INT 2023 Next-Generation Flood Inundation Mapping for Taiwan - Delft3D FM...
Deltares7 views
DSD-INT 2023 SFINCS Modelling in the U.S. Pacific Northwest - Parker by Deltares
DSD-INT 2023 SFINCS Modelling in the U.S. Pacific Northwest - ParkerDSD-INT 2023 SFINCS Modelling in the U.S. Pacific Northwest - Parker
DSD-INT 2023 SFINCS Modelling in the U.S. Pacific Northwest - Parker
Deltares9 views

Real Life Clean Architecture

  • 2. ABOUT ME ●  from Verona, Italy ●  software dev & continuous improvement ●  Kanban, Lean, Agile “helper” ●  Sky Network Services Mattia Battiston @BattistonMattia mattia.battiston@gmail.com mattia-battiston
  • 4. DISCLAIMER #2 THE ONE WAY Our experience (pragmatism, tradeoffs)
  • 5. Infrequent deploys COMMON PROBLEMS Decisions taken too early Hard to change Centered around database Centered around frameworks Business logic is spread everywhere Focused on technical aspects Slow, heavy tests Hard to find things
  • 6. “ The center of your application is not the database. Nor is it one or more of the frameworks you may be using. The center of your application is the use cases of your application Unclebob Source: NODB
  • 7. CLEAN ARCHITECTURE Source: The Clean Architecture
  • 8. THANK YOU! THE END Just Kidding, The fun is about to start :-)
  • 10. EXAMPLE DOMAIN: ISP Entity: Telephone Exchange Entity: Broadband Access Device Use case: Get Capacity “Have we got space for more customers? Can we sell more broadband?” Use case: Reconcile “Has any physical device changed? (e.g. new serial number)” Use case: Get Details “Details of a particular device?”
  • 11. OUR CLEAN ARCHITECTURE ENTITIES USE CASES REST APIs JOBS DATABASE FILE SYSTEM NETWORK DEVICES DB I ... ... CONFIGURATION coreentrypoints dataproviders
  • 12. A.k.a (unclebob’s style) Entities Use Cases Configuration + Core: business logic Entrypoints: access to the application Data Providers: retrieve and store information ... Configuration: wires everything together * arrows represent dependency
  • 14. ENTITY ENTITIES USE CASES REST APIs JOBS DATABASE FILE SYSTEM NETWORK DEVICES DB I ... ... CONFIGURATION coreentrypoints dataproviderscore ENTITIES
  • 16. ENTITY public class Exchange { private final String code; private final String name; private final String postCode; public Exchange(String code, String name, String postCode) { this.code = code; this.name = name; this.postCode = postCode; } // … getters @Override public String toString() { return ...; } }
  • 17. ENTITY public class BroadbandAccessDevice { private Exchange exchange; private String hostname; private String serialNumber; private DeviceType type; private int availablePorts; public BroadbandAccessDevice(String hostname, ...) { this.hostname = hostname; this.serialNumber = serialNumber; this.type = type; } // … (getters, some setters) @Override public String toString() { return ...; } }
  • 18. ENTITY ●  Domain objects e.g. “Exchange”, “Broadband Access Device” ●  Entity-specific business rules e.g. hostname format ●  Tiny Types are useful e.g. Hostname instead of String ●  No Frameworks
  • 19. USE CASE ENTITIES USE CASES REST APIs JOBS DATABASE FILE SYSTEM NETWORK DEVICES DB I ... ... CONFIGURATION coreentrypoints dataproviders USE CASES I core
  • 21. USE CASE public class GetCapacityForExchangeUseCase { private DoesExchangeExist dataProvider1; private GetAvailablePortsOfAllDevicesInExchange dataProvider2; // … public Capacity getCapacity(String exchangeCode) { failIfExchangeDoesNotExist(exchangeCode); List<BroadbandAccessDevice> devices = dataProvider2 .getAvailablePortsOfAllDevicesInExchange(exchangeCode); boolean hasAdslCapacity = hasCapacityFor(devices, DeviceType.ADSL); boolean hasFibreCapacity = hasCapacityFor(devices, DeviceType.FIBRE); return new Capacity(hasAdslCapacity, hasFibreCapacity); } // … private void failIfExchangeDoesNotExist(String exchangeCode) { boolean exchangeExists = dataProvider1.doesExchangeExist(exchangeCode); if(!exchangeExists) throw new ExchangeNotFoundException(); } }
  • 22. USE CASE public interface DoesExchangeExist { boolean doesExchangeExist(String exchange); } public interface GetAvailablePortsOfAllDevicesInExchange { List<BroadbandAccessDevice> getAvailablePortsOfAllDevicesInExchange(String exchangeCode); } public class ExchangeNotFoundException extends RuntimeException { }
  • 23. USE CASE ●  Pure business logic e.g. algorithm to calculate capacity ●  Defines Interfaces for the data that it requires e.g. getAvailablePorts ●  Uses entities and dataproviders ●  Throws business-specific exceptions ●  Not affected by changes in database or presentation ●  Plain Java (no frameworks) ●  We like single-method interfaces A.k.a. Interface Segregation
  • 24. DATA PROVIDER ENTITIES USE CASES REST APIs JOBS DATABASE FILE SYSTEM NETWORK DEVICES DB I ... ... CONFIGURATION coreentrypoints dataproviders DATABASE FILE SYSTEM NETWORK DEVICES DB ... dataproviders
  • 26. DATA PROVIDER public class BroadbandAccessDeviceDatabaseDataProvider implements GetAllDeviceHostnames, GetSerialNumberFromModel, ... { private JdbcTemplate jdbcTemplate; @Override public List<String> getAllDeviceHostnames() { return jdbcTemplate.queryForList( "SELECT hostname FROM clean_architecture.bb_access_device", String.class); } @Override public String getSerialNumber(String hostname) { try { return jdbcTemplate.queryForObject( "SELECT serial_number FROM clean_architecture.bb_access_device WHERE hostname = ?", String.class, hostname); } catch (IncorrectResultSizeDataAccessException e) { return null; } } // …
  • 27. DATA PROVIDER public class BroadbandAccessDeviceNetworkDataProvider implements GetSerialNumberFromReality { private DeviceClient deviceClient; // … @Override public String getSerialNumber(String hostname) { try { return deviceClient.getSerialNumber(hostname); } catch (DeviceConnectionTimeoutException e) { return null; } } }
  • 28. DATA PROVIDER ●  Implements Interfaces defined by use case e.g. retrieving serial number of a device ●  Hides all details about where the data is from ●  Could have multiple implementations e.g. from DB or from File System ●  Uses whatever framework/library is appropriate e.g. spring-jdbc, hibernate, snmp4j, etc. ●  If using ORM, you’d have a new set of entities A.k.a. decoupled from business entities
  • 29. ENTRYPOINT ENTITIES USE CASES REST APIs JOBS DATABASE FILE SYSTEM NETWORK DEVICES DB I ... ... CONFIGURATION coreentrypoints dataproviders REST APIs JOBS ... entrypoints
  • 31. ENTRYPOINT @RestController public class GetCapacityForExchangeEndpoint { public static final String API_PATH = "/exchange/{exchangeCode}/capacity"; private GetCapacityForExchangeUseCase getCapacityForExchangeUseCase; // … @RequestMapping(value = API_PATH, method = GET) public CapacityDto getCapacity(@PathVariable String exchangeCode) { try { Capacity capacity = getCapacityForExchangeUseCase.getCapacity(exchangeCode); return toDto(capacity); } catch (ExchangeNotFoundException e) { LOGGER.info("Exchange not found: {}", exchangeCode); throw new NotFoundException(); } } private CapacityDto toDto(Capacity capacity) { return new CapacityDto( capacity.hasAdslCapacity(), capacity.hasFibreCapacity()); } }
  • 32. ENTRYPOINT public class ReconcileBroadbandAccessDeviceJob implements ScheduledJob { private ReconcileBroadbandAccessDevicesUseCase useCase; private final JobResults jobResults; // … @Override public String getName() { return "..."; } @Override public long getInitialDelay() { return 0; } @Override public long getPeriod() { return 5; } @Override public TimeUnit getTimeUnit() { return TimeUnit.SECONDS; } @Override public void run() { LOGGER.info("Job Starting: {}...", getName()); JobResultsCount jobResultsCount = jobResults.createJobResultsCount(); OnSuccess success = jobResultsCount::success; OnFailure failure = jobResultsCount::failure; reconcileBroadbandAccessDevicesUseCase.reconcile(success, failure); jobResults.recordJobResults(this, jobResultsCount); LOGGER.info("Job Completed: {}", getName()); } }
  • 33. ENTRYPOINT ●  Fires up a use case ●  Has no business logic ●  Has conversion logic e.g. uses DTOs to return result to WEB ●  Hides all details about delivery mechanism ●  GUI would be an entrypoint e.g. controllers would start use cases ●  Uses whatever framework/library is appropriate e.g. spring-mvc, jersey, quartz, etc.
  • 34. CONFIGURATION ENTITIES USE CASES REST APIs JOBS DATABASE FILE SYSTEM NETWORK DEVICES DB I ... ... CONFIGURATION coreentrypoints dataproviders CONFIGURATION
  • 36. CONFIGURATION @Configuration @EnableAutoConfiguration @ComponentScan(basePackages = "com.clean.example.configuration") public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } } @Configuration public class EndpointConfiguration { @Bean public GetBroadbandAccessDeviceEndpoint getBroadbandAccessDeviceEndpoint() { return new GetBroadbandAccessDeviceEndpoint(...); } // …other endpoints… } @Configuration public class WebServerConfiguration { // …wires web server with framework… }
  • 37. CONFIGURATION ●  Wires everything together e.g. using Spring or simply initialising objects ●  Isolates and hides frameworks e.g. Spring is only here ●  Has the “dirty” details to make things work e.g. initialise datasource, setup web server, etc.
  • 38. EXAMPLE: GET CAPACITY Rest Entrypoint Client Use Case Data Provider GET /exchange/CHELSEA/capacity useCase.getCapacity(“CHELSEA”); dataProvider .getAvailablePortsOfAllDevicesInExchange (”CHELSEA”); SELECT … WHERE code = “CHELSEA” return broadbandAccessDevices; countAvailablePortsOfEachType(); decideIfThereIsCapacity(); return capacity; convertToDto(capacity); return dto; Status Code: 200 OK {"hasADSLCapacity":true, "hasFibreCapacity":true}
  • 39. EXAMPLE: RECONCILE DEVICES Use Case Job Entrypoint Data Provider: DB Data Provider: Network Device useCase.reconcile(...); getAllDeviceHostnames() "SELECT hostname...” // For each device: getSerialNumberFromModel(hostname) getSerialNumberFromReality(hostname) "SELECT serial_number...” SNMPGET … if(serialNumberIsDifferent()) { updateSerialNumber(); success(); } auditResults();
  • 40. Coverage TESTING STRATEGY Unit Tests - TDD Acceptance Tests - BDD Integration Tests End-to-end Tests Manual Exploratory Tests Cost
  • 41. UNIT TESTS ENTITIES USE CASES REST APIs JOBS DATABASE FILE SYSTEM NETWORK DEVICES DB I ... ... CONFIGURATION coreentrypoints dataproviders UNIT TESTs UNIT TESTs UNIT TESTs UNIT TESTs UNIT TESTs UNIT TESTs
  • 42. UNIT TESTS // … GetCapacityForExchangeEndpoint endpoint = // class under test GetCapacityForExchangeUseCase useCase = // mock @Test public void returnsTheCapacityForAnExchange() throws Exception { givenThereIsCapacityForAnExchange(); CapacityDto capacity = endpoint.getCapacity(EXCHANGE_CODE); assertThat(capacity.getHasADSLCapacity()).isTrue(); assertThat(capacity.getHasFibreCapacity()).isTrue(); } private void givenThereIsCapacityForAnExchange() { when(useCase.getCapacity(EXCHANGE_CODE)) .thenReturn(new Capacity(true, true)); } // …
  • 43. UNIT TESTS ●  TDD A.k.a. Tests first, to drive design ●  Cover every little detail A.k.a. Aim for 100% coverage ●  “Dev to dev” documentation A.k.a. What should this class do? ●  Test individual classes in isolation, very fast
  • 44. ACCEPTANCE TESTS ENTITIES USE CASES REST APIs JOBS DATABASE FILE SYSTEM NETWORK DEVICES DB I ... ... CONFIGURATION coreentrypoints dataproviders ACC. TESTs (BUS. REQ.)
  • 45. ACCEPTANCE TESTS @Notes("Calculates the remaining capacity in an exchange...") @LinkingNote(message = "End to End test: %s", links = {GetCapacityForExchangeEndToEndTest.class}) public class GetCapacityForExchangeAcceptanceTest extends YatspecTest { // …mock the dependencies of the use case… GetCapacityForExchangeUseCase useCase = // …my use case @Test public void hasAdslCapacityWhenThereAreAtLeast5AdslPortsAvailableAcrossAllDevices() { givenSomeAdslDevicesInTheExchangeWithMoreThan5AdslPortsAvailable(); whenTheCapacityForTheExchangeIsRequested(); thenThereIsAdslCapacity(); } // … }
  • 47. ACCEPTANCE TESTS ●  BDD A.k.a. Conversations with the business ●  Demonstrate business requirements A.k.a. Aim to cover business scenarios ●  “Business” documentation A.k.a. What does the system do? ●  Test use case in isolation, very fast A.k.a. No GUI, no DB, etc. ●  Use your favourite BDD framework We use Yatspec
  • 48. http INTEGRATION TESTS ENTITIES USE CASES REST APIs JOBS DATABASE FILE SYSTEM NETWORK DEVICES DB I ... ... CONFIGURATION coreentrypoints dataproviders INTEGRATION TESTs INTEGRATION TESTs
  • 49. INTEGRATION TESTS ●  Test integration with slow parts e.g. Http, database ●  “Dev” documentation A.k.a. Does this work as expected? ●  Test one layer in isolation e.g. only rest endpoint, or only data provider ●  Use whatever library makes it easy e.g. Spring MockMVC; in-memory db
  • 50. END-TO-END TESTS ENTITIES USE CASES REST APIs JOBS DATABASE FILE SYSTEM NETWORK DEVICES DB I ... ... CONFIGURATION coreentrypoints dataproviders http END-TO-END TESTs
  • 51. END-TO-END TESTS ●  Test only the critical journeys e.g. most common happy path ●  Demonstrate “business” end-to-end requirement ●  Start the whole app, very slow A.k.a. keep these to a minimum
  • 53. Infrequent deploys PROBLEMS? FIX! Decisions taken too early Hard to change Centered around database Centered around frameworks Business logic is spread everywhere Focused on technical aspects Slow, heavy tests Hard to find things Effective Testing Pyramid
  • 55. PRO: FRAMEWORKS ENTITIES USE CASES REST APIs JOBS DATABASE FILE SYSTEM NETWORK DEVICES DB I ... ... CONFIGURATION coreentrypoints dataproviders Spring WEB Spring boot Spring jdbc snmp4j quartz
  • 56. Infrequent deploys PROBLEMS? FIX! Decisions taken too early Hard to change Centered around database Centered around frameworks Business logic is spread everywhere Focused on technical aspects Slow, heavy tests Hard to find things Effective Testing Pyramid frameworks are Isolated
  • 58. PRO: DATABASE ●  No CRUD! ●  RESTful style for reading information GET /exchange/{exchangeCode} GET /exchange/{exchangeCode}/capacity GET /broadbandAccessDevice/{hostname} ●  Custom endpoints for business actions POST /broadbandAccessDevice/{hostname}/makeLive PUT /exchange/{exchangeCode}/increaseCapacity
  • 59. Infrequent deploys PROBLEMS? FIX! Decisions taken too early Hard to change Centered around database Centered around frameworks Business logic is spread everywhere Focused on technical aspects Slow, heavy tests Hard to find things Effective Testing Pyramid Independent from Database frameworks are Isolated
  • 62. Infrequent deploys PROBLEMS? FIX! Decisions taken too early Hard to change Centered around database Centered around frameworks Business logic is spread everywhere Focused on technical aspects Slow, heavy tests Hard to find things Effective Testing Pyramid Independent from Database Screaming Architecture frameworks are Isolated
  • 63. PRO: EASY TO FIND THINGS ALL BUSINESS LOGIC IS IN USE CASE
  • 64. Infrequent deploys PROBLEMS? FIX! Decisions taken too early Hard to change Centered around database Centered around frameworks Business logic is spread everywhere Focused on technical aspects Slow, heavy tests Hard to find things Effective Testing Pyramid Independent from Database Screaming ArchitectureAll business logic in use cases frameworks are Isolated
  • 65. PRO: MODULES HARD TO DO THE WRONG THING
  • 66. Infrequent deploys PROBLEMS? FIX! Decisions taken too early Hard to change Centered around database Centered around frameworks Business logic is spread everywhere Focused on technical aspects Slow, heavy tests Hard to find things Effective Testing Pyramid Independent from Database Screaming ArchitectureAll business logic in use cases Modules isolate changes frameworks are Isolated
  • 67. PRO: ALWAYS READY ALWAYS READY TO DEPLOY real continuous integration
  • 68. Infrequent deploys PROBLEMS? FIX! Decisions taken too early Hard to change Centered around database Centered around frameworks Business logic is spread everywhere Focused on technical aspects Slow, heavy tests Hard to find things Effective Testing Pyramid Independent from Database Screaming ArchitectureAll business logic in use cases Modules isolate changes Always Ready frameworks are Isolated
  • 70. Infrequent deploys PROBLEMS? FIX! Decisions taken too early Hard to change Centered around database Centered around frameworks Business logic is spread everywhere Focused on technical aspects Slow, heavy tests Hard to find things Effective Testing Pyramid Independent from Database Screaming ArchitectureAll business logic in use cases Modules isolate changes Always Ready Swarming frameworks are Isolated
  • 71. PRO: NICE MONOLITH GOOD MONOLITH TO START WITH clear boundaries to break on
  • 72. Infrequent deploys PROBLEMS? FIX! Decisions taken too early Hard to change Centered around database Centered around frameworks Business logic is spread everywhere Focused on technical aspects Slow, heavy tests Hard to find things Effective Testing Pyramid Independent from Database Screaming ArchitectureAll business logic in use cases Modules isolate changes Always Ready Swarming frameworks are Isolated Nice Monolith
  • 74. Infrequent deploys PROBLEMS? FIX! Decisions taken too early Hard to change Centered around database Centered around frameworks Business logic is spread everywhere Focused on technical aspects Slow, heavy tests Hard to find things Effective Testing Pyramid Independent from Database Screaming ArchitectureAll business logic in use cases Modules isolate changes Always Ready Swarming frameworks are Isolated Nice Monolith Duplication
  • 75. CON: IT NEEDS LOGIC YOU NEED INTERESTING BUSINESS LOGIC
  • 76. CON: IT NEEDS LOGIC ENDPOINT // … @RequestMapping(value = API_PATH, method = GET) public BroadbandAccessDeviceDto getDetails(@PathVariable String hostname) { try { BroadbandAccessDevice deviceDetails = useCase.getDeviceDetails(hostname); return toDto(deviceDetails); } catch (DeviceNotFoundException e) { throw new NotFoundException(); } } // … USE CASE // … public BroadbandAccessDevice getDeviceDetails(String hostname) { BroadbandAccessDevice device = dataProvider.getDetails(hostname); return device; } // … DATA PROVIDER // … return "SELECT ...";
  • 77. Infrequent deploys Always Ready PROBLEMS? FIX! Decisions taken too early Hard to change Centered around database Centered around frameworks Business logic is spread everywhere Focused on technical aspects Slow, heavy tests Hard to find things Effective Testing Pyramid frameworks are Isolated Independent from Database Screaming ArchitectureAll business logic in use cases Modules isolate changes Nice Monolith Swarming Duplication Needs Interesting Logic
  • 78. KEY TAKEAWAY “ The center of your application is the use cases of your application Unclebob
  • 79. RESOURCES Example Project (with all code shown in the presentation) ●  Clean Architecture Example https://github.com/mattia-battiston/clean-architecture-example Blogs & Articles ●  The Clean Architecture https://blog.8thlight.com/uncle-bob/2012/08/13/the-clean-architecture.html ●  Screaming Architecture http://blog.8thlight.com/uncle-bob/2011/09/30/Screaming-Architecture.html ●  NODB https://blog.8thlight.com/uncle-bob/2012/05/15/NODB.html ●  Hexagonal Architecture http://alistair.cockburn.us/Hexagonal+architecture Videos & Presentations ●  Clean Coders ep. 7: Architecture, Use Cases, and High Level Design https://cleancoders.com/episode/clean-code-episode-7/show ●  Robert C. Martin - Clean Architecture https://vimeo.com/43612849 ●  Robert C. Martin - Clean Architecture and Design https://www.youtube.com/watch?v=Nsjsiz2A9mg
  • 80. really, really appreciated! Help me improve @BattistonMattia mattia.battiston@gmail.com mattia-battiston THANK YOU!