hexagonal architecture - message-oriented software design
TRANSCRIPT
![Page 1: Hexagonal architecture - message-oriented software design](https://reader034.vdocuments.mx/reader034/viewer/2022050713/55bec2b4bb61eb0d7b8b4829/html5/thumbnails/1.jpg)
HEXAGONAL ARCHITECTURE Message oriented software design
By Matthias Noback
![Page 2: Hexagonal architecture - message-oriented software design](https://reader034.vdocuments.mx/reader034/viewer/2022050713/55bec2b4bb61eb0d7b8b4829/html5/thumbnails/2.jpg)
ARCHITECTUREWhat's the problem?
![Page 3: Hexagonal architecture - message-oriented software design](https://reader034.vdocuments.mx/reader034/viewer/2022050713/55bec2b4bb61eb0d7b8b4829/html5/thumbnails/3.jpg)
!!!
Nice app
![Page 4: Hexagonal architecture - message-oriented software design](https://reader034.vdocuments.mx/reader034/viewer/2022050713/55bec2b4bb61eb0d7b8b4829/html5/thumbnails/4.jpg)
!!!
Sad app
![Page 5: Hexagonal architecture - message-oriented software design](https://reader034.vdocuments.mx/reader034/viewer/2022050713/55bec2b4bb61eb0d7b8b4829/html5/thumbnails/5.jpg)
Your brain can't handle it
M V C ?
![Page 6: Hexagonal architecture - message-oriented software design](https://reader034.vdocuments.mx/reader034/viewer/2022050713/55bec2b4bb61eb0d7b8b4829/html5/thumbnails/6.jpg)
Coupling with frameworks and libraries
!!!
![Page 7: Hexagonal architecture - message-oriented software design](https://reader034.vdocuments.mx/reader034/viewer/2022050713/55bec2b4bb61eb0d7b8b4829/html5/thumbnails/7.jpg)
How do you start a new project?
Pick a framework
Install a skeleton project
Remove demo stuff
Auto-generate a CRUD controller
Auto-generate an entity
Done
"It's a Symfony project!"
![Page 8: Hexagonal architecture - message-oriented software design](https://reader034.vdocuments.mx/reader034/viewer/2022050713/55bec2b4bb61eb0d7b8b4829/html5/thumbnails/8.jpg)
That's actually outside inThe boring stuff
The interesting stuff
![Page 9: Hexagonal architecture - message-oriented software design](https://reader034.vdocuments.mx/reader034/viewer/2022050713/55bec2b4bb61eb0d7b8b4829/html5/thumbnails/9.jpg)
Slow tests
DB
Browser
Message queue
Key-value
![Page 10: Hexagonal architecture - message-oriented software design](https://reader034.vdocuments.mx/reader034/viewer/2022050713/55bec2b4bb61eb0d7b8b4829/html5/thumbnails/10.jpg)
Frameworks taught us about encapsulation
![Page 11: Hexagonal architecture - message-oriented software design](https://reader034.vdocuments.mx/reader034/viewer/2022050713/55bec2b4bb61eb0d7b8b4829/html5/thumbnails/11.jpg)
Low-level API
$requestContent = file_get_contents('php://input'); $contentType = $_SERVER['CONTENT_TYPE']; if ($contentType === 'application/json') { $data = json_decode($requestContent, true); } elseif ($contentType === 'application/xml') { $xml = simplexml_load_string($requestContent); ... }
![Page 12: Hexagonal architecture - message-oriented software design](https://reader034.vdocuments.mx/reader034/viewer/2022050713/55bec2b4bb61eb0d7b8b4829/html5/thumbnails/12.jpg)
Nicely hides the details
$data = $serializer->deserialize( $request->getContent(), $request->getContentType() );
![Page 13: Hexagonal architecture - message-oriented software design](https://reader034.vdocuments.mx/reader034/viewer/2022050713/55bec2b4bb61eb0d7b8b4829/html5/thumbnails/13.jpg)
Low-level API
$stmt = $db->prepare( 'SELECT * FROM Patient p WHERE p.anonymous = ?' ); $stmt->bindValue(1, true); $stmt->execute(); $result = $stmt->fetch(\PDO::FETCH_ASSOC); $patient = Patient::reconstituteFromArray($result);
![Page 14: Hexagonal architecture - message-oriented software design](https://reader034.vdocuments.mx/reader034/viewer/2022050713/55bec2b4bb61eb0d7b8b4829/html5/thumbnails/14.jpg)
Hides a lot of details
$patient = $repository->createQueryBuilder('p') ->where('p.anonymous = true') ->getQuery() ->getResult();
![Page 15: Hexagonal architecture - message-oriented software design](https://reader034.vdocuments.mx/reader034/viewer/2022050713/55bec2b4bb61eb0d7b8b4829/html5/thumbnails/15.jpg)
What about abstraction?
![Page 16: Hexagonal architecture - message-oriented software design](https://reader034.vdocuments.mx/reader034/viewer/2022050713/55bec2b4bb61eb0d7b8b4829/html5/thumbnails/16.jpg)
$patient = $repository->createQueryBuilder('p') ->where('p.anonymous = true') ->getQuery() ->getResult();
Concrete
Concrete
Concrete
![Page 17: Hexagonal architecture - message-oriented software design](https://reader034.vdocuments.mx/reader034/viewer/2022050713/55bec2b4bb61eb0d7b8b4829/html5/thumbnails/17.jpg)
$patients = $repository->anonymousPatients();
Abstract
Nice
![Page 18: Hexagonal architecture - message-oriented software design](https://reader034.vdocuments.mx/reader034/viewer/2022050713/55bec2b4bb61eb0d7b8b4829/html5/thumbnails/18.jpg)
Coupling to the delivery mechanism
![Page 19: Hexagonal architecture - message-oriented software design](https://reader034.vdocuments.mx/reader034/viewer/2022050713/55bec2b4bb61eb0d7b8b4829/html5/thumbnails/19.jpg)
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
![Page 20: Hexagonal architecture - message-oriented software design](https://reader034.vdocuments.mx/reader034/viewer/2022050713/55bec2b4bb61eb0d7b8b4829/html5/thumbnails/20.jpg)
Reusability: impossible
![Page 21: Hexagonal architecture - message-oriented software design](https://reader034.vdocuments.mx/reader034/viewer/2022050713/55bec2b4bb61eb0d7b8b4829/html5/thumbnails/21.jpg)
Some functionality
The web
The CLI
![Page 22: Hexagonal architecture - message-oriented software design](https://reader034.vdocuments.mx/reader034/viewer/2022050713/55bec2b4bb61eb0d7b8b4829/html5/thumbnails/22.jpg)
Some functionality
Run it
![Page 23: Hexagonal architecture - message-oriented software design](https://reader034.vdocuments.mx/reader034/viewer/2022050713/55bec2b4bb61eb0d7b8b4829/html5/thumbnails/23.jpg)
Lack of intention-revealing code
![Page 24: Hexagonal architecture - message-oriented software design](https://reader034.vdocuments.mx/reader034/viewer/2022050713/55bec2b4bb61eb0d7b8b4829/html5/thumbnails/24.jpg)
data
data
data
why?
why?
why?
![Page 25: Hexagonal architecture - message-oriented software design](https://reader034.vdocuments.mx/reader034/viewer/2022050713/55bec2b4bb61eb0d7b8b4829/html5/thumbnails/25.jpg)
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?
![Page 26: Hexagonal architecture - message-oriented software design](https://reader034.vdocuments.mx/reader034/viewer/2022050713/55bec2b4bb61eb0d7b8b4829/html5/thumbnails/26.jpg)
R.A.D.
Rapid Application Development
B.A.D.
B.A.D. Application Development
![Page 27: Hexagonal architecture - message-oriented software design](https://reader034.vdocuments.mx/reader034/viewer/2022050713/55bec2b4bb61eb0d7b8b4829/html5/thumbnails/27.jpg)
InconsistenciesGET /balance/ { "currency": "USD", "amount" 20 }
PUT /balance/ { "currency": "EUR", } !
![Page 28: Hexagonal architecture - message-oriented software design](https://reader034.vdocuments.mx/reader034/viewer/2022050713/55bec2b4bb61eb0d7b8b4829/html5/thumbnails/28.jpg)
Lack of maintainability
![Page 29: Hexagonal architecture - message-oriented software design](https://reader034.vdocuments.mx/reader034/viewer/2022050713/55bec2b4bb61eb0d7b8b4829/html5/thumbnails/29.jpg)
It's hard to find out what happens where
UserController"ProductController"CommentController"CategoryController"AccountController"ProfileController"..."
![Page 30: Hexagonal architecture - message-oriented software design](https://reader034.vdocuments.mx/reader034/viewer/2022050713/55bec2b4bb61eb0d7b8b4829/html5/thumbnails/30.jpg)
Web controllers are not the only actions
![Page 31: Hexagonal architecture - message-oriented software design](https://reader034.vdocuments.mx/reader034/viewer/2022050713/55bec2b4bb61eb0d7b8b4829/html5/thumbnails/31.jpg)
In summary
Coupling with a framework
Coupling with a delivery mechanism (e.g. the web)
Slow tests
Lack of intention in the code
![Page 32: Hexagonal architecture - message-oriented software design](https://reader034.vdocuments.mx/reader034/viewer/2022050713/55bec2b4bb61eb0d7b8b4829/html5/thumbnails/32.jpg)
THE ESSENCEof your application
![Page 33: Hexagonal architecture - message-oriented software design](https://reader034.vdocuments.mx/reader034/viewer/2022050713/55bec2b4bb61eb0d7b8b4829/html5/thumbnails/33.jpg)
The essence
Other things
![Page 34: Hexagonal architecture - message-oriented software design](https://reader034.vdocuments.mx/reader034/viewer/2022050713/55bec2b4bb61eb0d7b8b4829/html5/thumbnails/34.jpg)
The "heart"?
![Page 35: Hexagonal architecture - message-oriented software design](https://reader034.vdocuments.mx/reader034/viewer/2022050713/55bec2b4bb61eb0d7b8b4829/html5/thumbnails/35.jpg)
"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."
![Page 36: Hexagonal architecture - message-oriented software design](https://reader034.vdocuments.mx/reader034/viewer/2022050713/55bec2b4bb61eb0d7b8b4829/html5/thumbnails/36.jpg)
What's essential?
Domain model
Interaction with it
Use cases
![Page 37: Hexagonal architecture - message-oriented software design](https://reader034.vdocuments.mx/reader034/viewer/2022050713/55bec2b4bb61eb0d7b8b4829/html5/thumbnails/37.jpg)
What's not essential?
![Page 38: Hexagonal architecture - message-oriented software design](https://reader034.vdocuments.mx/reader034/viewer/2022050713/55bec2b4bb61eb0d7b8b4829/html5/thumbnails/38.jpg)
“The database is an implementation detail”
–Cool software architect
![Page 39: Hexagonal architecture - message-oriented software design](https://reader034.vdocuments.mx/reader034/viewer/2022050713/55bec2b4bb61eb0d7b8b4829/html5/thumbnails/39.jpg)
The core doesn't need to know about it
!!!
![Page 40: Hexagonal architecture - message-oriented software design](https://reader034.vdocuments.mx/reader034/viewer/2022050713/55bec2b4bb61eb0d7b8b4829/html5/thumbnails/40.jpg)
!!!
What about interaction?
!
![Page 41: Hexagonal architecture - message-oriented software design](https://reader034.vdocuments.mx/reader034/viewer/2022050713/55bec2b4bb61eb0d7b8b4829/html5/thumbnails/41.jpg)
The core doesn't need to know about it
!!!
![Page 42: Hexagonal architecture - message-oriented software design](https://reader034.vdocuments.mx/reader034/viewer/2022050713/55bec2b4bb61eb0d7b8b4829/html5/thumbnails/42.jpg)
Infrastructure
The world outside
!!!
Web browser
Terminal
Database
Messaging
![Page 43: Hexagonal architecture - message-oriented software design](https://reader034.vdocuments.mx/reader034/viewer/2022050713/55bec2b4bb61eb0d7b8b4829/html5/thumbnails/43.jpg)
Mmm... layers Layers allow you to
separate
Layers allow you to
allocate
Layers have
boundaries
Rules for crossing
![Page 44: Hexagonal architecture - message-oriented software design](https://reader034.vdocuments.mx/reader034/viewer/2022050713/55bec2b4bb61eb0d7b8b4829/html5/thumbnails/44.jpg)
Rules about communication
Actually: rules about dependencies
![Page 45: Hexagonal architecture - message-oriented software design](https://reader034.vdocuments.mx/reader034/viewer/2022050713/55bec2b4bb61eb0d7b8b4829/html5/thumbnails/45.jpg)
What crosses layer boundaries?
Message
![Page 46: Hexagonal architecture - message-oriented software design](https://reader034.vdocuments.mx/reader034/viewer/2022050713/55bec2b4bb61eb0d7b8b4829/html5/thumbnails/46.jpg)
MessagessomeFunctionCall( $arguments, $prepared, $for, $the, $receiver );
$command = new TypeOfMessage( $values, $for, $this, $message ); handle($command);
![Page 47: Hexagonal architecture - message-oriented software design](https://reader034.vdocuments.mx/reader034/viewer/2022050713/55bec2b4bb61eb0d7b8b4829/html5/thumbnails/47.jpg)
What about the application boundary?
The app
Messag
e
The world outside
![Page 48: Hexagonal architecture - message-oriented software design](https://reader034.vdocuments.mx/reader034/viewer/2022050713/55bec2b4bb61eb0d7b8b4829/html5/thumbnails/48.jpg)
How does an app allow incoming messages at all?
By exposing input ports
Routes Console commands
REST endpoints A WSDL file for a SOAP API
![Page 49: Hexagonal architecture - message-oriented software design](https://reader034.vdocuments.mx/reader034/viewer/2022050713/55bec2b4bb61eb0d7b8b4829/html5/thumbnails/49.jpg)
![Page 50: Hexagonal architecture - message-oriented software design](https://reader034.vdocuments.mx/reader034/viewer/2022050713/55bec2b4bb61eb0d7b8b4829/html5/thumbnails/50.jpg)
![Page 51: Hexagonal architecture - message-oriented software design](https://reader034.vdocuments.mx/reader034/viewer/2022050713/55bec2b4bb61eb0d7b8b4829/html5/thumbnails/51.jpg)
Ports use protocols for communication
Each port has a language of its own
![Page 52: Hexagonal architecture - message-oriented software design](https://reader034.vdocuments.mx/reader034/viewer/2022050713/55bec2b4bb61eb0d7b8b4829/html5/thumbnails/52.jpg)
Web (HTTP)
CLI (SAPI, STDIN, etc.)
![Page 53: Hexagonal architecture - message-oriented software design](https://reader034.vdocuments.mx/reader034/viewer/2022050713/55bec2b4bb61eb0d7b8b4829/html5/thumbnails/53.jpg)
HTTP Request
Form
Request
Controller
Entity
Value object
Web p
ort
Tran
slate
the re
quest
Repository
![Page 54: Hexagonal architecture - message-oriented software design](https://reader034.vdocuments.mx/reader034/viewer/2022050713/55bec2b4bb61eb0d7b8b4829/html5/thumbnails/54.jpg)
Adapters
The translators are called: adapters
![Page 55: Hexagonal architecture - message-oriented software design](https://reader034.vdocuments.mx/reader034/viewer/2022050713/55bec2b4bb61eb0d7b8b4829/html5/thumbnails/55.jpg)
"Ports and adapters"
Ports: allow for communication to happen
Adapters: translate messages from the world outside
== Hexagonal architecture
![Page 56: Hexagonal architecture - message-oriented software design](https://reader034.vdocuments.mx/reader034/viewer/2022050713/55bec2b4bb61eb0d7b8b4829/html5/thumbnails/56.jpg)
An example
Plain HTTP message
Request object
POST /users/ HTTP/1.1 Host: phpconference.nl !name=Matthias&[email protected]
Command
$command = new RegisterUser( $request->get('name'), $request->get('email') );
![Page 57: Hexagonal architecture - message-oriented software design](https://reader034.vdocuments.mx/reader034/viewer/2022050713/55bec2b4bb61eb0d7b8b4829/html5/thumbnails/57.jpg)
Command
$command = new RegisterUser( $request->get('name'), $request->get('email') );
Expresses intention
Implies changeStand-alone
Only the message
![Page 58: Hexagonal architecture - message-oriented software design](https://reader034.vdocuments.mx/reader034/viewer/2022050713/55bec2b4bb61eb0d7b8b4829/html5/thumbnails/58.jpg)
class RegisterUserHandler { public function handle(RegisterUser $command) { $user = User::register( $command->name(), $command->email() ); $this->userRepository->add($user); } }
CommandCommand handler
![Page 59: Hexagonal architecture - message-oriented software design](https://reader034.vdocuments.mx/reader034/viewer/2022050713/55bec2b4bb61eb0d7b8b4829/html5/thumbnails/59.jpg)
CommandCommand handler A
Command bus
Command handler B
Command handler C
![Page 60: Hexagonal architecture - message-oriented software design](https://reader034.vdocuments.mx/reader034/viewer/2022050713/55bec2b4bb61eb0d7b8b4829/html5/thumbnails/60.jpg)
Change
New entity (User)
Calculate changes (UoW)
$user = User::register( $command->name(), $command->email() ); $this->userRepository ->add($user);
Insert query (SQL)
INSERT INTO users SET name='Matthias', email='[email protected]';
![Page 61: Hexagonal architecture - message-oriented software design](https://reader034.vdocuments.mx/reader034/viewer/2022050713/55bec2b4bb61eb0d7b8b4829/html5/thumbnails/61.jpg)
SQL query
EntityManager
UnitOfWork
QueryBuilder
Persi
stenc
e port
Prepare
for p
ersist
ence
Repository
Value object
Entity
![Page 62: Hexagonal architecture - message-oriented software design](https://reader034.vdocuments.mx/reader034/viewer/2022050713/55bec2b4bb61eb0d7b8b4829/html5/thumbnails/62.jpg)
![Page 63: Hexagonal architecture - message-oriented software design](https://reader034.vdocuments.mx/reader034/viewer/2022050713/55bec2b4bb61eb0d7b8b4829/html5/thumbnails/63.jpg)
Messaging (AMQP)
Persistence (MySQL)
![Page 64: Hexagonal architecture - message-oriented software design](https://reader034.vdocuments.mx/reader034/viewer/2022050713/55bec2b4bb61eb0d7b8b4829/html5/thumbnails/64.jpg)
UserRepository (uses MySQL)
RegisterUserHandler
![Page 65: Hexagonal architecture - message-oriented software design](https://reader034.vdocuments.mx/reader034/viewer/2022050713/55bec2b4bb61eb0d7b8b4829/html5/thumbnails/65.jpg)
MySQL- UserRepository
RegisterUserHandler
Dependency inversion
UserRepository interface
![Page 66: Hexagonal architecture - message-oriented software design](https://reader034.vdocuments.mx/reader034/viewer/2022050713/55bec2b4bb61eb0d7b8b4829/html5/thumbnails/66.jpg)
MySQL- UserRepository
RegisterUserHandler
UserRepository interface
InMemory- UserRepository
Speedy alternative
![Page 67: Hexagonal architecture - message-oriented software design](https://reader034.vdocuments.mx/reader034/viewer/2022050713/55bec2b4bb61eb0d7b8b4829/html5/thumbnails/67.jpg)
"A good software architecture allows decisions [...] to be deferred and delayed."
–Robert Martin, Screaming Architecture
![Page 68: Hexagonal architecture - message-oriented software design](https://reader034.vdocuments.mx/reader034/viewer/2022050713/55bec2b4bb61eb0d7b8b4829/html5/thumbnails/68.jpg)
IN CONCLUSIONwhat did we get from all of this?
![Page 69: Hexagonal architecture - message-oriented software design](https://reader034.vdocuments.mx/reader034/viewer/2022050713/55bec2b4bb61eb0d7b8b4829/html5/thumbnails/69.jpg)
Separation of concerns
Core
Infrastructure
![Page 70: Hexagonal architecture - message-oriented software design](https://reader034.vdocuments.mx/reader034/viewer/2022050713/55bec2b4bb61eb0d7b8b4829/html5/thumbnails/70.jpg)
CommandCommand
Command handler
Command handler
Stand-alone use cases
Command
Command handler
Intention-revealing
Reusable
![Page 71: Hexagonal architecture - message-oriented software design](https://reader034.vdocuments.mx/reader034/viewer/2022050713/55bec2b4bb61eb0d7b8b4829/html5/thumbnails/71.jpg)
Infrastructure stand-ins
Regular implementation
Interface
Stand-in, fast implementation
![Page 72: Hexagonal architecture - message-oriented software design](https://reader034.vdocuments.mx/reader034/viewer/2022050713/55bec2b4bb61eb0d7b8b4829/html5/thumbnails/72.jpg)
This is all very much supportive of...
See also: Modelling by Example
DDD
TDDBDD
CQRS
![Page 73: Hexagonal architecture - message-oriented software design](https://reader034.vdocuments.mx/reader034/viewer/2022050713/55bec2b4bb61eb0d7b8b4829/html5/thumbnails/73.jpg)
QUESTIONS? FEEDBACK?joind.in/14238