Hexagonal architecture - message-oriented software design (Symfony Live Berlin 2015)
matthiasnoback
2,601 views
76 slides
Oct 16, 2015
Slide 1 of 76
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
About This Presentation
Commands, events, queries - different types of messages that travel through your application. Some originate from the web, some from the command-line. Your application sends some of them to a database, or a message queue. What is the ideal infrastructure for an application to support this on-going s...
Commands, events, queries - different types of messages that travel through your application. Some originate from the web, some from the command-line. Your application sends some of them to a database, or a message queue. What is the ideal infrastructure for an application to support this on-going stream of messages? What kind of architectural design fits best? This talk provides answers to these questions: we take the *hexagonal* approach to software architecture. We look at messages, how they cross boundaries and how you can make steady communication lines between your application and other systems, like web browsers, terminals, databases and message queues. You will learn how to separate the technical aspects of these connections from the core behavior of your application by implementing design patterns like the *command bus*, and design principles like *dependency inversion*.
Size: 5.49 MB
Language: en
Added: Oct 16, 2015
Slides: 76 pages
Slide Content
HEXAGONAL ARCHITECTURE
Message oriented software design
By Matthias Noback
ARCHITECTURE
What's the problem?
Nice app
Sad app
Your brain can't handle it
M V C ?
Coupling to frameworks
and libraries
How do you start a new
project?
Pick a framework
Install a skeleton project
Remove demo stu"!
Auto-generate entities
Auto-generate CRUD controllers
Done
"It's a Symfony project!"
That's actually outside in
The boring stuff
The interesting stuff
Symfony
Doctrine
RabbitMQ
Redis
Angular
Slow tests
DB
Browser
Message
queue
Key-
value
Filesystem
Why do frameworks not solve this for us?
Because they can't ;)
public function registerPatientAction (Request $request)
{
$patient = new Patient();
$form = $this->createForm(new RegisterPatientForm(), $patient);
$form->handleRequest($request);
if ($form->isValid()) {
$em = $this->getDoctrine()->getManager();
$em->persist($patient);
$em->flush();
return $this->redirect($this->generateUrl('patient_list'));
}
return array(
'form' => $form->createView()
);
}
Request and Form are web-specific
EntityManager is ORM, i.e.
relational DB-specific
Reusability: impossible
Some
functionality
The web
The CLI
Some
functionality
Run it
Lack of intention-revealing code
data
data
data
public function updateAction(Request $request)
{
$patient = new Patient();
$form = $this->createForm(new PatientType(), $patient);
$form->handleRequest($request);
if ($form->isValid()) {
$em = $this->getDoctrine()->getManager();
$em->persist($patient);
$em->flush();
return $this->redirect($this->generateUrl('patient_list'));
}
return array(
'form' => $form->createView()
);
}
from the HTTP request
copied into an entity
then stored in the database
What exactly
changed?!
And... why?
R.A.D.
Rapid Application Development
B.A.D.
B.A.D. Application Development
In summary
Coupling to a framework
Coupling to a delivery mechanism (e.g. the web)
Slow tests
Lack of intention in the code
THE ESSENCE
of your application
The essence
Other things
The "heart"?
"The heart of software is its ability to solve
domain-related problems for its users.
–Eric Evans, Domain Driven Design
All other features, vital though they may be,
support this basic purpose."
What's essential?
Domain model
Interaction with it
Use cases
What's not essential?
“The database is an implementation detail”
–Cool software architect
The core doesn't need to
know about it
What about interaction?
The core doesn't need to
know about it
Infrastructure
The world outside
Web browser
Terminal
Database
Messaging
Filesystem
(E)mail
Mmm... layers Layers
allow you to
separate
Layers
allow you to
allocate
Layers
have
boundaries
Rules
for crossing
Rules about
communication
Actually: rules about dependencies
The dependency rule
–Robert Martin, Screaming Architecture
What about the application
boundary?
The app
Message
The world outside
How does an app allow
incoming messages at all?
By exposing input ports
Routes
Console commands
A WSDL file for a SOAP API
Ports use protocols for
communication
Each port has a language of its own
Web (HTTP)
Messaging (AMQP)
HTTP
Request
Form
Request
Controller
Entity
Value object
Web port
Translate the request
Repository
Adapters
The translators are called: adapters
"Ports and adapters"
Ports: allow for communication to happen
Adapters: translate messages from the world outside
== Hexagonal architecture
Alistair Cockburn
An example
Plain HTTP
message
$_POST,
$_GET,
$_SERVER,
Request
POST /patients/ HTTP/1.1
Host: hospital.com
name=Matthias&email=matthiasn [email protected]
Command
$command = new RegisterPatient(
$request->get('name'),
$request->get('email')
);
Command
$command = new RegisterPatient(
$request->get('name'),
$request->get('email')
);
Expresses
intention
Implies
change
Independent
of delivery
mechanism
Only the
message
class RegisterPatientHandler
{
public function handle(RegisterPatient $command)
{
$patient = Patient::register(
$command->name(),
$command->email()
);
$this->patientRepository-> add($patient);
}
}
Command
Command
handler
Command
Command
handler A
Command
bus
Command
handler B
Command
handler C
HTTP
Request
Form
Request
Controller
Patient
(entity)
Web port
PatientRepository
RegisterPatient-
Handler
RegisterPatient
(command)
Infrastructure
Application
Domain
Change
New entity
(Patient)
Entity-
Manager
UnitOf-
Work
$patient = Patient::register(
$command->name(),
$command->email()
);
$this->patientRepository
->add($patient);
Insert
query (SQL)
INSERT INTO patients SET
name='Matthias',
email='matthiasnoback@gmai
l.com';
SQL query
EntityManager
UnitOfWork
QueryBuilder
Persistence port
Prepare for persistence
PatientRepository
Core
Infrastructure
Messaging (AMQP)
Persistence (MySQL)
What often goes wrong:
we violate boundary rules...