SlideShare a Scribd company logo
1 of 50
Download to read offline
Fighting legacy
with hexagonal architecture
and frameworkless PHP
Author: Fabio Pellegrini
Fabio Pellegrini
Some context
● A start-up born 10 years ago
● Initial business was focused on public transportation services
● At some point the company saw a market opportunity and
started to focus on the so-called “flexible benefits”
● Business grew fast, the domain evolved
As complexity grows,
if you don’t keep it under control,
sometimes you get...
A big ball of mud
mud
What is a big ball of mud?
A Big Ball of Mud is a haphazardly
structured, sprawling, sloppy,
duct-tape-and-baling-wire, spaghetti-code
jungle. These systems show unmistakable
signs of unregulated growth, and repeated,
expedient repair.
Information is shared promiscuously
among distant elements of the system,
often to the point where nearly all the
important information becomes global or
duplicated.
How did our big ball of mud look?
● Spaghetti code
● Leaky abstractions
● A few services with lots of
responsibilities
● All services read from and
write to the same DB
● External BI tools connected
directly to the DB
Our concerns
● Legacy code is really difficult to test
● A lot of bad duplication (that leads to shotgun surgery)
● Inconsistent naming
● A single DB everyone has access to
● DB performance / slow queries
● Lots of processes not automated yet
● High maintenance cost
● ...
We had already started to extract some services
in order to separate responsibilities and keep
complexity under control...
Tech needs VS Business needs
● Improve architecture design
● Migrate old services to
Kubernetes cluster
● Cleanup code
● Find proper names to
software components
● Find better abstractions
● Add more tests
● Split the main monolith into
microservices
● ...
● Lots of things I don’t
remember well
● The e-commerce portal has
a bad UX and looks old
compared with some
competitors
Ok... let’s build this new “Portal”
A chance for a new design?
PROS:
Portal was a good starting point for refactoring:
● It included a large part of the domain
● Mainly data presentation
● Not much business operations
CONS:
● Large scope
● Timebox
How to model the domain
while dealing with legacy?
● DDD
● Hexagonal architecture
Domain Driven Design
Three core principles:
● Focus on the core domain and domain logic
● Base complex designs on models of the domain
● Constantly collaborate with domain experts, in order to
improve the application model and resolve any emerging
domain-related issues.
Hexagonal Architecture
● Dependency inversion principle: both low level and high level
modules should depend on abstractions, abstractions should
not depend on details.
● Use adapters as a translation level, so you can have a ”pure”
representation of the domain in the application core
● Keep implementation details at the borders of the
application
● Loosely coupled application components, components are
exchangeable, high testability
● As we depend on abstractions, we can change the
implementation in the future without changing the core
Hexagonal Architecture
Repositories vs Services
Why did we use repositories and not services for retrieving data
from the legacy core?
● No much logic to handle, only data extraction
● For operations with side-effects we actually used services
(e.g. purchase operation)
● We wanted to explicitly state which were our data and define
their shape
● Once we move data on the correct side, we can simply add
new repositories implementation
● The interfaces will be our contract/specification in this
migration process
Un utente usa 10 euro del suo benefit per richiedere un
servizio.
An employee takes 10 euro from his wallet and orders a
product.
Repositories and Services
Both repositories and services acted as a translation layer.
…should we use a PHP framework?
Hexagonal architecture with framework
● High coupling between DB schema and codebase
● Model with active record (Laravel)
● Entity + Repository (Symfony)
● Default dir structure organize classes by component role
(model, controller, etc)
● Global facades accessible everywhere, implicit dependencies
(you could use DI, but it’s a matter of discipline)
● Low maintainability because of large classes scope and
components coupling
Hexagonal architecture without framework
● DB schema can be decoupled from domain logic
● Dir structure organize classes by domain logic (product,
wallet, employee)
● Interfaces + value object/entities + repositories
● Explicit dependencies by enforcing DI
● Apply SOLID principles, limit classes scope, increase
maintainability
Directory structure comparison
symfony-project/
├─ assets/
├─ bin/
│ └─ console
├─ config/
├─ public/
├─ src/
│ ├─ Controller
│ │ ├─ EmployeeController.php
│ │ ├─ ProductController.php
│ │ └─ WalletController.php
│ ├─ Entity
│ │ ├─ Employee.php
│ │ ├─ Product.php
│ │ └─ Wallet.php
│ ├─ Exception
│ │ └─ ProductNotFoundException.php
│ ├─ Factory
│ ├─ Provider
│ ├─ Repository
│ │ ├─ EmployeeRepository.php
│ │ ├─ ProductRepository.php
│ │ └─ WalletRepository.php
│ └─ Security
├─ templates/
├─ tests/
├─ translations/
├─ var/
└─ vendor/
laravel-project/
├─ app/
│ ├─ Console
│ ├─ Events
│ ├─ Exceptions
│ │ └─ ProductNotFoundException.php
│ ├─ Http
│ │ └─ Controllers
│ │ ├─ EmployeeController.php
│ │ ├─ ProductController.php
│ │ └─ WalletController.php
│ ├─ Jobs
│ ├─ Listeners
│ ├─ Mail
│ ├─ Models
│ │ ├─ Employee.php
│ │ ├─ Product.php
│ │ └─ Wallet.php
│ ├─ Notifications
│ ├─ Policies
│ ├─ Providers
│ └─ Rules
├─ bootstrap/
├─ config/
├─ database/
├─ public/
├─ resources/
├─ routes/
├─ storage/
custom-project/
├─ bin/
│ └─ console
├─ db/
├─ docs/
├─ etc/
├─ public/
├─ routes/
├─ rules/
├─ src/
│ ├─ Employee
│ │ ├─ Employee.php
│ │ ├─ Controller.php
│ │ ├─ MySqlRepository.php
│ │ └─ RepositoryInterface.php
│ ├─ Product
│ │ ├─ Product.php
│ │ ├─ Controller.php
│ │ ├─ MySqlRepository.php
│ │ ├─ RepositoryInterface.php
│ │ └─ ProductNotFoundException.php
│ └─ Wallet
│ ├─ Wallet.php
│ ├─ Controller.php
│ ├─ MySqlRepository.php
│ └─ RepositoryInterface.php
├─ tests/
└─ vendor/
Directory structure comparison
├─ src/
│ ├─ Employee
│ │ ├─ Employee.php
│ │ ├─ Controller.php
│ │ ├─ MySqlRepository.php
│ │ └─ RepositoryInterface.php
│ ├─ Product
│ │ ├─ Product.php
│ │ ├─ Controller.php
│ │ ├─ MySqlRepository.php
│ │ ├─ RepositoryInterface.php
│ │ └─ ProductNotFoundException.php
│ └─ Wallet
│ ├─ Wallet.php
│ ├─ Controller.php
│ ├─ MySqlRepository.php
│ └─ RepositoryInterface.php
├─ src/
│ ├─ Domain/
│ │ ├─ Employee
│ │ │ ├─ Employee.php
│ │ │ ├─ Controller.php
│ │ │ └─ RepositoryInterface.php
│ │ ├─ Product
│ │ │ ├─ Product.php
│ │ │ ├─ Controller.php
│ │ │ ├─ RepositoryInterface.php
│ │ │ └─ ProductNotFoundException.php
│ │ └─ Wallet
│ │ ├─ Wallet.php
│ │ ├─ Controller.php
│ │ └─ RepositoryInterface.php
│ ├─ Infrastructure/
│ │ └─ MySql
│ │ ├─ EmployeeRepository.php
│ │ ├─ ProductRepository.php
│ │ └─ WalletRepository.php
│ └─ Application/
PHP without framework: how to
What we need:
● HTTP (Routing, Middlewares, ...)
● Logging
● Configuration
● Dependency Injection Container
● Error handling
HTTP (Routing,Middlewares,...)
We can use a Microframework:
● Silex (2010-2018 RIP)
● Slim
● Lumen
● Symfony MicroKernelTrait?
● ...
HTTP (Routing,Middlewares,...)
Logging
Standard de-facto:
● monolog/monolog
Logging
Configuration
Some libraries:
● vlucas/phpdotenv
● symfony/config
● hassankhan/config
● write your own...
Dependency Injection Container
Some libraries:
● php-di/php-di
● pimple/pimple
● league/container
● ...
Dependency Injection Container
Dependency Injection Container
Error handling
If something goes wrong:
● log error
● return an error response consistent with API format
Error handling
Let’s put things together
How to bootstrap:
- Create a new DI container
- Import all definitions (logger and configuration provider are
defined there)
- Create a new Slim app with the container injected
- Set the default app error handler
- Apply routes definitions
- Run app
Testing
We have:
● Enforced explicit dependency injection
● Defined interfaces for services, repositories, loggers, etc
Testing
● Mock dependencies of the class under test
● Create the class instance by injecting the mocks in the
container
● Test only the class behaviour in isolation
● In integration use in-memory implementations for faster
tests
● In the DI container make LoggerInterface resolve to a
TestLogger and test also logging
Next steps?
● Continue the refactoring of legacy core
● Define new bounded contexts following a DDD approach
● Separate responsibilities, split core monolith into different
services
● As we extract services or move data from a DB to another,
update/add repositories implementation on Portal without
changing the interfaces
What actually happened
● The company was acquired by a competitor
● The competitor had a similar portal
● They decided to maintain our legacy system while migrating
users to their systems
● “Portal” project was dismissed
What I learned
● How to build a solid foundation for a PHP application without
framework (it’s quite easy)
● Thinking “frameworkless” helps you to shape your
application starting from scratch, adding only what you need
● Hexagonal architecture is a great architectural pattern, less
coupling between application components, more
maintainability, more testability.
Thanks for your attention!
fabiopellegrini90@gmail.com
linkedin.com/in/fabiopellegrini90

More Related Content

What's hot

Spring Framework Petclinic sample application
Spring Framework Petclinic sample applicationSpring Framework Petclinic sample application
Spring Framework Petclinic sample applicationAntoine Rey
 
Developer Experience (DX) as a Fitness Function for Platform Teams
Developer Experience (DX) as a Fitness Function for Platform TeamsDeveloper Experience (DX) as a Fitness Function for Platform Teams
Developer Experience (DX) as a Fitness Function for Platform TeamsAndy Marks
 
Rest api standards and best practices
Rest api standards and best practicesRest api standards and best practices
Rest api standards and best practicesAnkita Mahajan
 
Implement Authorization in your Apps with Microsoft identity platform-June 2020
Implement Authorization in your Apps with Microsoft identity platform-June 2020Implement Authorization in your Apps with Microsoft identity platform-June 2020
Implement Authorization in your Apps with Microsoft identity platform-June 2020Microsoft 365 Developer
 
Inversion of Control and Dependency Injection
Inversion of Control and Dependency InjectionInversion of Control and Dependency Injection
Inversion of Control and Dependency InjectionDinesh Sharma
 
An Introduction to Domain Driven Design in PHP
An Introduction to Domain Driven Design in PHPAn Introduction to Domain Driven Design in PHP
An Introduction to Domain Driven Design in PHPChris Renner
 
Clean Architecture Applications in Python
Clean Architecture Applications in PythonClean Architecture Applications in Python
Clean Architecture Applications in PythonSubhash Bhushan
 
Clean architecture
Clean architectureClean architecture
Clean architectureLieven Doclo
 
Cortex: Horizontally Scalable, Highly Available Prometheus
Cortex: Horizontally Scalable, Highly Available PrometheusCortex: Horizontally Scalable, Highly Available Prometheus
Cortex: Horizontally Scalable, Highly Available PrometheusGrafana Labs
 
Spring boot - an introduction
Spring boot - an introductionSpring boot - an introduction
Spring boot - an introductionJonathan Holloway
 

What's hot (20)

Spring Framework Petclinic sample application
Spring Framework Petclinic sample applicationSpring Framework Petclinic sample application
Spring Framework Petclinic sample application
 
Developer Experience (DX) as a Fitness Function for Platform Teams
Developer Experience (DX) as a Fitness Function for Platform TeamsDeveloper Experience (DX) as a Fitness Function for Platform Teams
Developer Experience (DX) as a Fitness Function for Platform Teams
 
Rest api standards and best practices
Rest api standards and best practicesRest api standards and best practices
Rest api standards and best practices
 
Hexagonal architecture in PHP
Hexagonal architecture in PHPHexagonal architecture in PHP
Hexagonal architecture in PHP
 
Event Storming and Saga
Event Storming and SagaEvent Storming and Saga
Event Storming and Saga
 
An Introduction To REST API
An Introduction To REST APIAn Introduction To REST API
An Introduction To REST API
 
Implement Authorization in your Apps with Microsoft identity platform-June 2020
Implement Authorization in your Apps with Microsoft identity platform-June 2020Implement Authorization in your Apps with Microsoft identity platform-June 2020
Implement Authorization in your Apps with Microsoft identity platform-June 2020
 
Spring data jpa
Spring data jpaSpring data jpa
Spring data jpa
 
Inversion of Control and Dependency Injection
Inversion of Control and Dependency InjectionInversion of Control and Dependency Injection
Inversion of Control and Dependency Injection
 
Zuul @ Netflix SpringOne Platform
Zuul @ Netflix SpringOne PlatformZuul @ Netflix SpringOne Platform
Zuul @ Netflix SpringOne Platform
 
Spring boot
Spring bootSpring boot
Spring boot
 
An Introduction to Domain Driven Design in PHP
An Introduction to Domain Driven Design in PHPAn Introduction to Domain Driven Design in PHP
An Introduction to Domain Driven Design in PHP
 
Clean Architecture Applications in Python
Clean Architecture Applications in PythonClean Architecture Applications in Python
Clean Architecture Applications in Python
 
Rest API
Rest APIRest API
Rest API
 
Clean architecture
Clean architectureClean architecture
Clean architecture
 
Spring Data JPA
Spring Data JPASpring Data JPA
Spring Data JPA
 
Api presentation
Api presentationApi presentation
Api presentation
 
Cortex: Horizontally Scalable, Highly Available Prometheus
Cortex: Horizontally Scalable, Highly Available PrometheusCortex: Horizontally Scalable, Highly Available Prometheus
Cortex: Horizontally Scalable, Highly Available Prometheus
 
Spring boot - an introduction
Spring boot - an introductionSpring boot - an introduction
Spring boot - an introduction
 
Serverless Summit - Quiz
Serverless Summit - QuizServerless Summit - Quiz
Serverless Summit - Quiz
 

Similar to Fighting legacy with hexagonal architecture and frameworkless php

DevOps for TYPO3 Teams and Projects
DevOps for TYPO3 Teams and ProjectsDevOps for TYPO3 Teams and Projects
DevOps for TYPO3 Teams and ProjectsFedir RYKHTIK
 
Cloud Native Development
Cloud Native DevelopmentCloud Native Development
Cloud Native DevelopmentManuel Garcia
 
Viktor Turskyi "Effective NodeJS Application Development"
Viktor Turskyi "Effective NodeJS Application Development"Viktor Turskyi "Effective NodeJS Application Development"
Viktor Turskyi "Effective NodeJS Application Development"Fwdays
 
RedisConf17 - Dynomite - Making Non-distributed Databases Distributed
RedisConf17 - Dynomite - Making Non-distributed Databases DistributedRedisConf17 - Dynomite - Making Non-distributed Databases Distributed
RedisConf17 - Dynomite - Making Non-distributed Databases DistributedRedis Labs
 
Advantages of golang development services & 10 most used go frameworks
Advantages of golang development services & 10 most used go frameworksAdvantages of golang development services & 10 most used go frameworks
Advantages of golang development services & 10 most used go frameworksKaty Slemon
 
Strategies and Tips for Building Enterprise Drupal Applications - PNWDS 2013
Strategies and Tips for Building Enterprise Drupal Applications - PNWDS 2013Strategies and Tips for Building Enterprise Drupal Applications - PNWDS 2013
Strategies and Tips for Building Enterprise Drupal Applications - PNWDS 2013Mack Hardy
 
Dirigible powered by Orion for Cloud Development (EclipseCon EU 2015)
Dirigible powered by Orion for Cloud Development (EclipseCon EU 2015)Dirigible powered by Orion for Cloud Development (EclipseCon EU 2015)
Dirigible powered by Orion for Cloud Development (EclipseCon EU 2015)Nedelcho Delchev
 
Serverless - DevOps Lessons Learned From Production
Serverless - DevOps Lessons Learned From ProductionServerless - DevOps Lessons Learned From Production
Serverless - DevOps Lessons Learned From ProductionSteve Hogg
 
Not my problem - Delegating responsibility to infrastructure
Not my problem - Delegating responsibility to infrastructureNot my problem - Delegating responsibility to infrastructure
Not my problem - Delegating responsibility to infrastructureYshay Yaacobi
 
AngularJS in Production (CTO Forum)
AngularJS in Production (CTO Forum)AngularJS in Production (CTO Forum)
AngularJS in Production (CTO Forum)Alex Ross
 
Advanced web application architecture - Talk
Advanced web application architecture - TalkAdvanced web application architecture - Talk
Advanced web application architecture - TalkMatthias Noback
 
[Perforce] Component Based Development in Perforce
[Perforce] Component Based Development in Perforce[Perforce] Component Based Development in Perforce
[Perforce] Component Based Development in PerforcePerforce
 
EDB Postgres with Containers
EDB Postgres with ContainersEDB Postgres with Containers
EDB Postgres with ContainersEDB
 
Yotpo microservices
Yotpo microservicesYotpo microservices
Yotpo microservicesRon Barabash
 
InterCon 2016 - SLA vs Agilidade: uso de microserviços e monitoramento de cloud
InterCon 2016 - SLA vs Agilidade: uso de microserviços e monitoramento de cloudInterCon 2016 - SLA vs Agilidade: uso de microserviços e monitoramento de cloud
InterCon 2016 - SLA vs Agilidade: uso de microserviços e monitoramento de cloudiMasters
 
From class to architecture
From class to architectureFrom class to architecture
From class to architectureMarcin Hawraniak
 

Similar to Fighting legacy with hexagonal architecture and frameworkless php (20)

DevOps for TYPO3 Teams and Projects
DevOps for TYPO3 Teams and ProjectsDevOps for TYPO3 Teams and Projects
DevOps for TYPO3 Teams and Projects
 
Cloud Native Development
Cloud Native DevelopmentCloud Native Development
Cloud Native Development
 
Dynomite @ RedisConf 2017
Dynomite @ RedisConf 2017Dynomite @ RedisConf 2017
Dynomite @ RedisConf 2017
 
Viktor Turskyi "Effective NodeJS Application Development"
Viktor Turskyi "Effective NodeJS Application Development"Viktor Turskyi "Effective NodeJS Application Development"
Viktor Turskyi "Effective NodeJS Application Development"
 
Dust.js
Dust.jsDust.js
Dust.js
 
RedisConf17 - Dynomite - Making Non-distributed Databases Distributed
RedisConf17 - Dynomite - Making Non-distributed Databases DistributedRedisConf17 - Dynomite - Making Non-distributed Databases Distributed
RedisConf17 - Dynomite - Making Non-distributed Databases Distributed
 
Advantages of golang development services & 10 most used go frameworks
Advantages of golang development services & 10 most used go frameworksAdvantages of golang development services & 10 most used go frameworks
Advantages of golang development services & 10 most used go frameworks
 
Strategies and Tips for Building Enterprise Drupal Applications - PNWDS 2013
Strategies and Tips for Building Enterprise Drupal Applications - PNWDS 2013Strategies and Tips for Building Enterprise Drupal Applications - PNWDS 2013
Strategies and Tips for Building Enterprise Drupal Applications - PNWDS 2013
 
Dirigible powered by Orion for Cloud Development (EclipseCon EU 2015)
Dirigible powered by Orion for Cloud Development (EclipseCon EU 2015)Dirigible powered by Orion for Cloud Development (EclipseCon EU 2015)
Dirigible powered by Orion for Cloud Development (EclipseCon EU 2015)
 
Serverless - DevOps Lessons Learned From Production
Serverless - DevOps Lessons Learned From ProductionServerless - DevOps Lessons Learned From Production
Serverless - DevOps Lessons Learned From Production
 
Not my problem - Delegating responsibility to infrastructure
Not my problem - Delegating responsibility to infrastructureNot my problem - Delegating responsibility to infrastructure
Not my problem - Delegating responsibility to infrastructure
 
Go at uber
Go at uberGo at uber
Go at uber
 
AngularJS in Production (CTO Forum)
AngularJS in Production (CTO Forum)AngularJS in Production (CTO Forum)
AngularJS in Production (CTO Forum)
 
Advanced web application architecture - Talk
Advanced web application architecture - TalkAdvanced web application architecture - Talk
Advanced web application architecture - Talk
 
[Perforce] Component Based Development in Perforce
[Perforce] Component Based Development in Perforce[Perforce] Component Based Development in Perforce
[Perforce] Component Based Development in Perforce
 
Software Development with PHP & Laravel
Software Development  with PHP & LaravelSoftware Development  with PHP & Laravel
Software Development with PHP & Laravel
 
EDB Postgres with Containers
EDB Postgres with ContainersEDB Postgres with Containers
EDB Postgres with Containers
 
Yotpo microservices
Yotpo microservicesYotpo microservices
Yotpo microservices
 
InterCon 2016 - SLA vs Agilidade: uso de microserviços e monitoramento de cloud
InterCon 2016 - SLA vs Agilidade: uso de microserviços e monitoramento de cloudInterCon 2016 - SLA vs Agilidade: uso de microserviços e monitoramento de cloud
InterCon 2016 - SLA vs Agilidade: uso de microserviços e monitoramento de cloud
 
From class to architecture
From class to architectureFrom class to architecture
From class to architecture
 

Recently uploaded

The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...ICS
 
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...gurkirankumar98700
 
Asset Management Software - Infographic
Asset Management Software - InfographicAsset Management Software - Infographic
Asset Management Software - InfographicHr365.us smith
 
chapter--4-software-project-planning.ppt
chapter--4-software-project-planning.pptchapter--4-software-project-planning.ppt
chapter--4-software-project-planning.pptkotipi9215
 
5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdf5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdfWave PLM
 
cybersecurity notes for mca students for learning
cybersecurity notes for mca students for learningcybersecurity notes for mca students for learning
cybersecurity notes for mca students for learningVitsRangannavar
 
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...kellynguyen01
 
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed Data
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed DataAlluxio Monthly Webinar | Cloud-Native Model Training on Distributed Data
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed DataAlluxio, Inc.
 
ODSC - Batch to Stream workshop - integration of Apache Spark, Cassandra, Pos...
ODSC - Batch to Stream workshop - integration of Apache Spark, Cassandra, Pos...ODSC - Batch to Stream workshop - integration of Apache Spark, Cassandra, Pos...
ODSC - Batch to Stream workshop - integration of Apache Spark, Cassandra, Pos...Christina Lin
 
Optimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTVOptimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTVshikhaohhpro
 
HR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.comHR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.comFatema Valibhai
 
Advancing Engineering with AI through the Next Generation of Strategic Projec...
Advancing Engineering with AI through the Next Generation of Strategic Projec...Advancing Engineering with AI through the Next Generation of Strategic Projec...
Advancing Engineering with AI through the Next Generation of Strategic Projec...OnePlan Solutions
 
Call Girls in Naraina Delhi 💯Call Us 🔝8264348440🔝
Call Girls in Naraina Delhi 💯Call Us 🔝8264348440🔝Call Girls in Naraina Delhi 💯Call Us 🔝8264348440🔝
Call Girls in Naraina Delhi 💯Call Us 🔝8264348440🔝soniya singh
 
EY_Graph Database Powered Sustainability
EY_Graph Database Powered SustainabilityEY_Graph Database Powered Sustainability
EY_Graph Database Powered SustainabilityNeo4j
 
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASEBATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASEOrtus Solutions, Corp
 
Der Spagat zwischen BIAS und FAIRNESS (2024)
Der Spagat zwischen BIAS und FAIRNESS (2024)Der Spagat zwischen BIAS und FAIRNESS (2024)
Der Spagat zwischen BIAS und FAIRNESS (2024)OPEN KNOWLEDGE GmbH
 
Project Based Learning (A.I).pptx detail explanation
Project Based Learning (A.I).pptx detail explanationProject Based Learning (A.I).pptx detail explanation
Project Based Learning (A.I).pptx detail explanationkaushalgiri8080
 
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdfLearn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdfkalichargn70th171
 
What is Binary Language? Computer Number Systems
What is Binary Language?  Computer Number SystemsWhat is Binary Language?  Computer Number Systems
What is Binary Language? Computer Number SystemsJheuzeDellosa
 
Adobe Marketo Engage Deep Dives: Using Webhooks to Transfer Data
Adobe Marketo Engage Deep Dives: Using Webhooks to Transfer DataAdobe Marketo Engage Deep Dives: Using Webhooks to Transfer Data
Adobe Marketo Engage Deep Dives: Using Webhooks to Transfer DataBradBedford3
 

Recently uploaded (20)

The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
 
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
 
Asset Management Software - Infographic
Asset Management Software - InfographicAsset Management Software - Infographic
Asset Management Software - Infographic
 
chapter--4-software-project-planning.ppt
chapter--4-software-project-planning.pptchapter--4-software-project-planning.ppt
chapter--4-software-project-planning.ppt
 
5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdf5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdf
 
cybersecurity notes for mca students for learning
cybersecurity notes for mca students for learningcybersecurity notes for mca students for learning
cybersecurity notes for mca students for learning
 
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
 
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed Data
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed DataAlluxio Monthly Webinar | Cloud-Native Model Training on Distributed Data
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed Data
 
ODSC - Batch to Stream workshop - integration of Apache Spark, Cassandra, Pos...
ODSC - Batch to Stream workshop - integration of Apache Spark, Cassandra, Pos...ODSC - Batch to Stream workshop - integration of Apache Spark, Cassandra, Pos...
ODSC - Batch to Stream workshop - integration of Apache Spark, Cassandra, Pos...
 
Optimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTVOptimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTV
 
HR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.comHR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.com
 
Advancing Engineering with AI through the Next Generation of Strategic Projec...
Advancing Engineering with AI through the Next Generation of Strategic Projec...Advancing Engineering with AI through the Next Generation of Strategic Projec...
Advancing Engineering with AI through the Next Generation of Strategic Projec...
 
Call Girls in Naraina Delhi 💯Call Us 🔝8264348440🔝
Call Girls in Naraina Delhi 💯Call Us 🔝8264348440🔝Call Girls in Naraina Delhi 💯Call Us 🔝8264348440🔝
Call Girls in Naraina Delhi 💯Call Us 🔝8264348440🔝
 
EY_Graph Database Powered Sustainability
EY_Graph Database Powered SustainabilityEY_Graph Database Powered Sustainability
EY_Graph Database Powered Sustainability
 
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASEBATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
 
Der Spagat zwischen BIAS und FAIRNESS (2024)
Der Spagat zwischen BIAS und FAIRNESS (2024)Der Spagat zwischen BIAS und FAIRNESS (2024)
Der Spagat zwischen BIAS und FAIRNESS (2024)
 
Project Based Learning (A.I).pptx detail explanation
Project Based Learning (A.I).pptx detail explanationProject Based Learning (A.I).pptx detail explanation
Project Based Learning (A.I).pptx detail explanation
 
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdfLearn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
 
What is Binary Language? Computer Number Systems
What is Binary Language?  Computer Number SystemsWhat is Binary Language?  Computer Number Systems
What is Binary Language? Computer Number Systems
 
Adobe Marketo Engage Deep Dives: Using Webhooks to Transfer Data
Adobe Marketo Engage Deep Dives: Using Webhooks to Transfer DataAdobe Marketo Engage Deep Dives: Using Webhooks to Transfer Data
Adobe Marketo Engage Deep Dives: Using Webhooks to Transfer Data
 

Fighting legacy with hexagonal architecture and frameworkless php

  • 1. Fighting legacy with hexagonal architecture and frameworkless PHP Author: Fabio Pellegrini
  • 3. Some context ● A start-up born 10 years ago ● Initial business was focused on public transportation services ● At some point the company saw a market opportunity and started to focus on the so-called “flexible benefits” ● Business grew fast, the domain evolved
  • 4. As complexity grows, if you don’t keep it under control, sometimes you get...
  • 5. A big ball of mud mud
  • 6. What is a big ball of mud?
  • 7. A Big Ball of Mud is a haphazardly structured, sprawling, sloppy, duct-tape-and-baling-wire, spaghetti-code jungle. These systems show unmistakable signs of unregulated growth, and repeated, expedient repair. Information is shared promiscuously among distant elements of the system, often to the point where nearly all the important information becomes global or duplicated.
  • 8. How did our big ball of mud look?
  • 9. ● Spaghetti code ● Leaky abstractions ● A few services with lots of responsibilities ● All services read from and write to the same DB ● External BI tools connected directly to the DB
  • 10. Our concerns ● Legacy code is really difficult to test ● A lot of bad duplication (that leads to shotgun surgery) ● Inconsistent naming ● A single DB everyone has access to ● DB performance / slow queries ● Lots of processes not automated yet ● High maintenance cost ● ...
  • 11. We had already started to extract some services in order to separate responsibilities and keep complexity under control...
  • 12.
  • 13. Tech needs VS Business needs ● Improve architecture design ● Migrate old services to Kubernetes cluster ● Cleanup code ● Find proper names to software components ● Find better abstractions ● Add more tests ● Split the main monolith into microservices ● ... ● Lots of things I don’t remember well ● The e-commerce portal has a bad UX and looks old compared with some competitors
  • 14. Ok... let’s build this new “Portal”
  • 15. A chance for a new design? PROS: Portal was a good starting point for refactoring: ● It included a large part of the domain ● Mainly data presentation ● Not much business operations CONS: ● Large scope ● Timebox
  • 16.
  • 17. How to model the domain while dealing with legacy? ● DDD ● Hexagonal architecture
  • 18. Domain Driven Design Three core principles: ● Focus on the core domain and domain logic ● Base complex designs on models of the domain ● Constantly collaborate with domain experts, in order to improve the application model and resolve any emerging domain-related issues.
  • 19. Hexagonal Architecture ● Dependency inversion principle: both low level and high level modules should depend on abstractions, abstractions should not depend on details. ● Use adapters as a translation level, so you can have a ”pure” representation of the domain in the application core ● Keep implementation details at the borders of the application ● Loosely coupled application components, components are exchangeable, high testability ● As we depend on abstractions, we can change the implementation in the future without changing the core
  • 21.
  • 22.
  • 23. Repositories vs Services Why did we use repositories and not services for retrieving data from the legacy core? ● No much logic to handle, only data extraction ● For operations with side-effects we actually used services (e.g. purchase operation) ● We wanted to explicitly state which were our data and define their shape ● Once we move data on the correct side, we can simply add new repositories implementation ● The interfaces will be our contract/specification in this migration process
  • 24. Un utente usa 10 euro del suo benefit per richiedere un servizio. An employee takes 10 euro from his wallet and orders a product.
  • 25. Repositories and Services Both repositories and services acted as a translation layer.
  • 26.
  • 27.
  • 28. …should we use a PHP framework?
  • 29. Hexagonal architecture with framework ● High coupling between DB schema and codebase ● Model with active record (Laravel) ● Entity + Repository (Symfony) ● Default dir structure organize classes by component role (model, controller, etc) ● Global facades accessible everywhere, implicit dependencies (you could use DI, but it’s a matter of discipline) ● Low maintainability because of large classes scope and components coupling
  • 30. Hexagonal architecture without framework ● DB schema can be decoupled from domain logic ● Dir structure organize classes by domain logic (product, wallet, employee) ● Interfaces + value object/entities + repositories ● Explicit dependencies by enforcing DI ● Apply SOLID principles, limit classes scope, increase maintainability
  • 31. Directory structure comparison symfony-project/ ├─ assets/ ├─ bin/ │ └─ console ├─ config/ ├─ public/ ├─ src/ │ ├─ Controller │ │ ├─ EmployeeController.php │ │ ├─ ProductController.php │ │ └─ WalletController.php │ ├─ Entity │ │ ├─ Employee.php │ │ ├─ Product.php │ │ └─ Wallet.php │ ├─ Exception │ │ └─ ProductNotFoundException.php │ ├─ Factory │ ├─ Provider │ ├─ Repository │ │ ├─ EmployeeRepository.php │ │ ├─ ProductRepository.php │ │ └─ WalletRepository.php │ └─ Security ├─ templates/ ├─ tests/ ├─ translations/ ├─ var/ └─ vendor/ laravel-project/ ├─ app/ │ ├─ Console │ ├─ Events │ ├─ Exceptions │ │ └─ ProductNotFoundException.php │ ├─ Http │ │ └─ Controllers │ │ ├─ EmployeeController.php │ │ ├─ ProductController.php │ │ └─ WalletController.php │ ├─ Jobs │ ├─ Listeners │ ├─ Mail │ ├─ Models │ │ ├─ Employee.php │ │ ├─ Product.php │ │ └─ Wallet.php │ ├─ Notifications │ ├─ Policies │ ├─ Providers │ └─ Rules ├─ bootstrap/ ├─ config/ ├─ database/ ├─ public/ ├─ resources/ ├─ routes/ ├─ storage/ custom-project/ ├─ bin/ │ └─ console ├─ db/ ├─ docs/ ├─ etc/ ├─ public/ ├─ routes/ ├─ rules/ ├─ src/ │ ├─ Employee │ │ ├─ Employee.php │ │ ├─ Controller.php │ │ ├─ MySqlRepository.php │ │ └─ RepositoryInterface.php │ ├─ Product │ │ ├─ Product.php │ │ ├─ Controller.php │ │ ├─ MySqlRepository.php │ │ ├─ RepositoryInterface.php │ │ └─ ProductNotFoundException.php │ └─ Wallet │ ├─ Wallet.php │ ├─ Controller.php │ ├─ MySqlRepository.php │ └─ RepositoryInterface.php ├─ tests/ └─ vendor/
  • 32. Directory structure comparison ├─ src/ │ ├─ Employee │ │ ├─ Employee.php │ │ ├─ Controller.php │ │ ├─ MySqlRepository.php │ │ └─ RepositoryInterface.php │ ├─ Product │ │ ├─ Product.php │ │ ├─ Controller.php │ │ ├─ MySqlRepository.php │ │ ├─ RepositoryInterface.php │ │ └─ ProductNotFoundException.php │ └─ Wallet │ ├─ Wallet.php │ ├─ Controller.php │ ├─ MySqlRepository.php │ └─ RepositoryInterface.php ├─ src/ │ ├─ Domain/ │ │ ├─ Employee │ │ │ ├─ Employee.php │ │ │ ├─ Controller.php │ │ │ └─ RepositoryInterface.php │ │ ├─ Product │ │ │ ├─ Product.php │ │ │ ├─ Controller.php │ │ │ ├─ RepositoryInterface.php │ │ │ └─ ProductNotFoundException.php │ │ └─ Wallet │ │ ├─ Wallet.php │ │ ├─ Controller.php │ │ └─ RepositoryInterface.php │ ├─ Infrastructure/ │ │ └─ MySql │ │ ├─ EmployeeRepository.php │ │ ├─ ProductRepository.php │ │ └─ WalletRepository.php │ └─ Application/
  • 33. PHP without framework: how to What we need: ● HTTP (Routing, Middlewares, ...) ● Logging ● Configuration ● Dependency Injection Container ● Error handling
  • 34. HTTP (Routing,Middlewares,...) We can use a Microframework: ● Silex (2010-2018 RIP) ● Slim ● Lumen ● Symfony MicroKernelTrait? ● ...
  • 38. Configuration Some libraries: ● vlucas/phpdotenv ● symfony/config ● hassankhan/config ● write your own...
  • 39. Dependency Injection Container Some libraries: ● php-di/php-di ● pimple/pimple ● league/container ● ...
  • 42. Error handling If something goes wrong: ● log error ● return an error response consistent with API format
  • 44. Let’s put things together How to bootstrap: - Create a new DI container - Import all definitions (logger and configuration provider are defined there) - Create a new Slim app with the container injected - Set the default app error handler - Apply routes definitions - Run app
  • 45. Testing We have: ● Enforced explicit dependency injection ● Defined interfaces for services, repositories, loggers, etc
  • 46. Testing ● Mock dependencies of the class under test ● Create the class instance by injecting the mocks in the container ● Test only the class behaviour in isolation ● In integration use in-memory implementations for faster tests ● In the DI container make LoggerInterface resolve to a TestLogger and test also logging
  • 47. Next steps? ● Continue the refactoring of legacy core ● Define new bounded contexts following a DDD approach ● Separate responsibilities, split core monolith into different services ● As we extract services or move data from a DB to another, update/add repositories implementation on Portal without changing the interfaces
  • 48. What actually happened ● The company was acquired by a competitor ● The competitor had a similar portal ● They decided to maintain our legacy system while migrating users to their systems ● “Portal” project was dismissed
  • 49. What I learned ● How to build a solid foundation for a PHP application without framework (it’s quite easy) ● Thinking “frameworkless” helps you to shape your application starting from scratch, adding only what you need ● Hexagonal architecture is a great architectural pattern, less coupling between application components, more maintainability, more testability.
  • 50. Thanks for your attention! fabiopellegrini90@gmail.com linkedin.com/in/fabiopellegrini90