SlideShare a Scribd company logo
SOLID: the core principles of success
of the Symfony web framework
and of your applications
Software Engineering Conference Russia 2018
October 12-13
Moscow
RIABCHENKO Vladyslav
https://vria.eu
contact@vria.eu
https://twitter.com/RiaVlad
RIABCHENKO Vladyslav
5+ years full stack web-developer
Symfony certified developer and contributor
Technical architect at Webnet (France)
Symfony 3
1. Symfony
2. SOLID
3. Single responsibility principle
4. Open/closed principle
5. Liskov substitution principle
6. Interface segregation principle
7. Dependency inversion principle
Plan
Symfony framework
Symfony 5
2. PHP framework for web projects
1. Set of reusable PHP components
MVC Pattern
Model View
HTTP Request Routing Controller HTTP Response
Symfony 6
HttpKernel
DependencyInjection
HttpFoundation
Routing
EventDispatcher
Heart of framework that manages HTTP request-response cycle
Object-oriented layer for request, response, session, etc.
Maps requests to variables (controller, path parameters)
Mediator that allows decoupled components to communicate by
dispatching events
Service container that instantiates service objects out of
configuration and injects their dependencies
and 45 others including Security, Form, Console, Cache, Asset, Validator, Serializer, etc.
Symfony 7
FrameworkBundle
Configures Symfony components and glues them in web app. It
registers services and event listeners.
Bundles are reusable plugins that provide services, routes, controllers, templates, etc.
Your code
Provides routes, controllers, services, business logic, templates
for your purpose.
doctrine/orm DBAL and ORM libraries to communicate with databases.
twig/twig Template engine.
SOLID principles
SOLID 9
– Single Responsibility Principle
– Open/Closed Principle
– Liskov Substitution Principle
– Interface Segregation Principle
– Dependency Inversion Principle
Reusable
Flexible
Maintainable
Understandable
Fragile
Duplicated
Viscose
Unreasonably complex
SOLID helps to design a system that is … and avoid a system that is
S
O
L
I
D
Single responsibility principle
Single responsibility principle 11
class ReportService
{
public function createReport($data)
{
// working with report manager at domain layer
}
public function getLastThreeReportsByAuthor($author)
{
// working with database at ORM or DBAL layer
}
public function searchBy($criteria)
{
// working with database at ORM or DBAL layer
}
public function export(Report $report)
{
// working with filesystem at by means of PHP functions
}
}
A class should have only a single responsibility. Responsibility is a reason to change.
Single responsibility principle
// working with report manager at domain layer (business logic)
class ReportManager
{
public function createReport($data)
{ ... }
}
// working with filesystem and pdf, excel, csv, etc.
class ReportExporter
{
public function export(Report $report)
{ ... }
}
// working with database at ORM and/or DBAL layer
class ReportRepository
{
public function getLastThreeReportsByAuthor($author)
{ ... }
public function searchBy($criteria)
{ ... }
}
Manager
Exporter
Repository
12
Single responsibility principle 13
Feature : Store users in database
Feature : Store orders in database
Feature : Authenticate users against database (login form, HTTP auth, whatever…)
Feature : On creation of order assign a currentrly connected user to it.
Store user credentials in session and authenticate users at latter requests
Single responsibility principle 14
SecurityContext
Stores a user token setToken($token), getToken()
Checks if a current user authorization isGranted('attr', $sub)
AuthenticationProvider Authenticates a token
UserProvider Retrieves or refreshes user from database
EntityManager All interaction with database at ORM and DBAL levels
OrderListener Your listener that modifies order before it gets inserted
Injecting SecurityContext service in any EntityManager’s listener
created a circular dependency.
Single responsibility principle 15
Solution is splitting SecurityContext into AuthorizationChecker and TokenStorage
AuthorizationChecker
AuthenticationProvider
UserProvider
EntityManager
OrderListener
TokenStorage
getToken()
setToken($token)
isGranted('attr', $sub)
Open/closed principle
Open/closed principle
Entities should be open for extension, but closed for modification.
17
Open for extension:
• Alter or add behavior
• Extend an entity with new properties
Closed for modification:
• Adapt entity without modifying its source code
• Provide an entity with clear and stable interface
Open/closed principle 18
Techniques to stay in compliance with the open/closed principle:
• Abstraction / Inheritance / Polymorphism
• Dependency injection
• Single responsibility principle
• Design patterns. For example, those of GoF:
• Abstract Factory, Factory Method, Builder, Prototype,
• Bridge, Decorator, Proxy,
• Command, Mediator, Memento, Observer, State, Strategy, Template Method, Visitor.
SymfonyComponentHttpKernel
App
Open/closed principle 19
// public/index.php
use AppKernel;
use SymfonyComponentHttpFoundationRequest;
$kernel = new Kernel($env, $debug);
$request = Request::createFromGlobals();
$response = $kernel->handle($request);
$response->send();
HttpKernel
- dispatcher
+ handle($request): Response
- container
- httpKernel
Kernel
+ handle($request)
+ registerBundles()
+ configureRoutes()
Kernel
+ registerBundles()
+ configureRoutes()
All HTTP requests are treated by front controller.
Open/closed principle 20
Request-Response cycle is open for extension thanks to events dispatched at every step.
Request
Response
resolve
controller
REQUEST
resolve
arguments
call
controller
CONTROLLER CONTROLLER_ARGUMENTS
Response
RESPONSE FINISH_REQUEST
Response
exists
TERMINATE
VIEW
Exception EXCEPTION
Liskov substitution principle
Liskov substitution principle
Objects should be replaceable with instances of their subtypes
without altering the correctness of the program.
22
LSP describes behavioral subtyping –
semantic rather than merely syntactic relation.
Liskov substitution principle 23
Rectangle
Square is a regular rectangle with four equal sides.
- width
- height
+ setWidth($width)
+ setHeight($height)
+ getArea()
+ setWidth($width)
+ setHeight($height)
Square
function client(Rectangle $rect)
{
$rect->setHeight(8);
$rect->setWidth(3);
assert($rect->area() == 24);
}
Client will fail when you pass Square object
class Square extends Rectangle
{
public function setWidth($width)
{
$this->width = $width;
$this->height = $width;
}
public function setHeight($height)
{
$this->height = $height;
$this->width = $height;
}
}
Liskov substitution principle 24
• Preconditions cannot be strengthened in a subtype
• Postconditions cannot be weakened in a subtype
• Invariants of the supertype must be preserved in a subtype
LSP suggests behavioral conditions resembling those of design by contract methodology:
Rectangle Precondition: width is integer > 0
Postcondition: $this->width equals $width
Invariant: $this->height remains unchanged
Precondition: width is integer > 0
Postcondition: $this->width equals $width
Invariant: $this->height remains unchanged
Invariant: $this->width equals $this->height
- width
- height
+ setWidth($width)
+ setHeight($height)
+ getArea()
+ setWidth($width)
+ setHeight($height)
Square
Liskov substitution principle 25
Authorization – verifying access rights/privileges of currently authenticated user.
In Symfony authorization is based on:
• Token: the user’s authentication information (roles, etc.),
• Attributes: rights/privileges to verify the access to,
• Object: Any object for which access control needs to be checked.
$authorizationChecker->isGranted('ROLE_ADMIN');
$authorizationChecker->isGranted('EDIT’, $comment);
$authorizationChecker->isGranted(['VIEW', 'MANAGE'], $order);
Liskov substitution principle 26
- voters : VoterInterface[]
+ decide($token, $attributes, $object)
AuthorizationChecker
- tokenStorage
- accessDecisionManager
+ isGranted($attributes, $object)
AccessDecisionManager
+ vote($token, $subject, $attributes)
VoterInterface
isGranted returns true/false. It delegates
decision to AccessDecisionManager::decide.
decide asks all voters to vote and returns
final decision.
vote must return one of these values :
ACCESS_GRANTED, ACCESS_ABSTAIN or ACCESS_DENIED.
DoctrineORM
Liskov substitution principle 27
Doctrine is several PHP libraries focused on database storage and object mapping.
Instance of Article
id: 17
author: Author(id=3, name=Marie)
createdAt: DateTime(2018-10-01)
text: "Hi Secrus! Today we…"
Instance of Author
id: 3
name: Marie
articles: [Article(id=17, …)]
article
id author_id created_at text
16 2 2018-05-21 In thi…
17 17 2018-10-01 Hi sec…
…
author
id name
2 Albert
3 Marie
4 Isaac
…
Liskov substitution principle 28
Doctrine triggers a bunch of events during the life-time of stored entities:
prePersist and postPersist, preUpdate and postUpdate, preRemove and postRemove.
use DoctrineORMEventLifecycleEventArgs;
use DoctrineORMMapping as ORM;
class Article
{
private $createdAt;
private $updatedAt;
private $createdBy;
private $updatedBy;
/** @ORMPrePersist() */
public function prePersist(LifecycleEventArgs $event)
{
$this->createdAt = new DateTime();
}
/** @ORMPreUpdate() */
public function preUpdate(LifecycleEventArgs $event)
{
$article = $event->getEntity();
$article->setUpdatedAt(new DateTime());
}
}
Precondition: $event->getEntity()
is an instance of Article
use AppEntityArticle;
use DoctrineORMEventLifecycleEventArgs;
class ArticleLifecycleListener
{
/** @var AppEntity|Author */
private $user;
public function prePersist(LifecycleEventArgs $event)
{
$article = $event->getEntity();
if ($article instanceof Article) {
$article->setCreatedBy($this->user);
}
}
public function preUpdate(LifecycleEventArgs $event)
{
$article = $event->getEntity();
if ($article instanceof Article) {
$article->setUpdatedBy($this->user);
}
}
}
Liskov substitution principle 29
Precondition: $event->getEntity()
is an instance of any entity
Doctrine listeners as services have access to other services via dependency injection :
Interface segregation principle
Interface segregation principle 31
Many client-specific interfaces are better than one general-purpose interface.
No client should be forced to depend on methods it does not use.
Interface segregation principle 32
Service container
Configuraion:
yaml, xml, php
For each service:
- id
- class name
- dependencies
- …
- Instantiate service object on demand
- Instantiate its dependencies
- Inject dependencies into service
- Store and return the service
- Return the same instance on
consecutive demands
“Compilation”
Container manages services which are any useful objects.
PsrContainer
Interface segregation principle 33
Fetch services ContainerInterface
+ get($id): mixed
+ has($id): bool
SymfonyComponentDependencyInjection
ContainerInterface
+ set($id, $service)
+ initialized($id): bool
+ getParameter($name): mixed
Container
- services
- parameterBag
- aliases
+ compile()
Configure services, parameters
Compile container (init, cache)
(Any client code)
(Extensions)
(Kernel)
Interface segregation principle 34
Routes configuration
Url matcher
'_route’ => string 'blog_list'
'_controller' => string 'AppControllerBlog::list'
'page’ => string '2'
'category’ => string 'secr-conference'
Url generator
'/blog/secr-conference'
'/blog/secr/2'
$matcher->match('/blog/secr-conference/2');
$generator->generate('blog_list', ['category' => 'secr-conference']);
$generator->generate('blog_list', ['category' => 'secr', 'page' => 2]);
# config/routes.yaml
blog_list: # route name
path: /blog/{category}/{page} # path pattern
controller: AppControllerBlog::list # controller to execute
requirements: # param constraints
category: '[a-z0-9-_]+'
page: 'd+'
defaults: # param default values
page: 1
SymfonyComponentRouting
Interface segregation principle 35
UrlMatcherInterface
+ match($pathinfo): array
UrlGeneratorInterface
+ generate
($name, $parameters, $referenceType): string
RouterInterface
+ getRouteCollection(): RouteCollection
Router
- collection: RouteCollection
- options: array
- context
Contains the configuration
of all known routes.
Dependency inversion principle
Dependency inversion principle 37
High-level modules should not depend on low-level modules.
Both should depend on abstractions.
Abstractions should not depend on details.
Details should depend on abstractions.
Framework
Dependency inversion principle 38
namespace Monolog;
class Logger
{
public function log($message)
{
echo $message;
}
}
namespace Framework;
use MonologLogger;
class Kernel
{
private $logger;
public function __construct(Logger $logger)
{
$this->logger = $logger;
}
public function handle()
{
$this->logger->log('...');
// ...
}
}
Monolog
Kernel Logger
Dependency inversion principle 39
namespace Framework;
class Kernel
{
private $logger;
public function __construct(LoggerInterface $logger)
{
$this->logger = $logger;
}
}
namespace Monolog;
use FrameworkLoggerInterface;
class Logger implements LoggerInterface
{
public function log($message)
{
echo $message;
}
}
namespace Framework;
interface LoggerInterface
{
public function log($message);
}
Framework Monolog
Kernel LoggerLoggerInterface
AbstractLogger
Dependency inversion principle 40
More flexible solution
Framework
Monolog
Kernel
Logger
LoggerInterface
Dependency inversion principle 41
PsrLog
SymfonyHTTPKernel
Monolog
Kernel
Logger
LoggerInterface
PSR – PHP Standards Recommendations by
FIG – Framework Interoperability Group
SymfonyRouting
Router
SymfonySecurity
Handlers ...
...
...
Dependency inversion principle 42
Symfony uses interfaces and dependency injection everywhere.
SymfonyForm
SymfonyValidator
ACMEValidator
FormInterface
Form
ExtensionValidator
ValidatorExtension
ValidatorInterface
Validator
Validator
- validator: ValidatorInterface
FormExtensionInterface
Thank you!
https://vria.eu
contact@vria.eu
https://twitter.com/RiaVlad
https://webnet.fr

More Related Content

What's hot

What's hot (20)

BPF - in-kernel virtual machine
BPF - in-kernel virtual machineBPF - in-kernel virtual machine
BPF - in-kernel virtual machine
 
[143] Modern C++ 무조건 써야 해?
[143] Modern C++ 무조건 써야 해?[143] Modern C++ 무조건 써야 해?
[143] Modern C++ 무조건 써야 해?
 
HashiCorp's Vault - The Examples
HashiCorp's Vault - The ExamplesHashiCorp's Vault - The Examples
HashiCorp's Vault - The Examples
 
Wso2 api manager 특징 slide share
Wso2 api manager 특징   slide shareWso2 api manager 특징   slide share
Wso2 api manager 특징 slide share
 
Securing AEM webapps by hacking them
Securing AEM webapps by hacking themSecuring AEM webapps by hacking them
Securing AEM webapps by hacking them
 
Introducing Vault
Introducing VaultIntroducing Vault
Introducing Vault
 
How to steal and modify data using Business Logic flaws - Insecure Direct Obj...
How to steal and modify data using Business Logic flaws - Insecure Direct Obj...How to steal and modify data using Business Logic flaws - Insecure Direct Obj...
How to steal and modify data using Business Logic flaws - Insecure Direct Obj...
 
The Secret Life of a Bug Bounty Hunter – Frans Rosén @ Security Fest 2016
The Secret Life of a Bug Bounty Hunter – Frans Rosén @ Security Fest 2016The Secret Life of a Bug Bounty Hunter – Frans Rosén @ Security Fest 2016
The Secret Life of a Bug Bounty Hunter – Frans Rosén @ Security Fest 2016
 
SpecterOps Webinar Week - Kerberoasting Revisisted
SpecterOps Webinar Week - Kerberoasting RevisistedSpecterOps Webinar Week - Kerberoasting Revisisted
SpecterOps Webinar Week - Kerberoasting Revisisted
 
SSRF exploit the trust relationship
SSRF exploit the trust relationshipSSRF exploit the trust relationship
SSRF exploit the trust relationship
 
A Hacker's perspective on AEM applications security
A Hacker's perspective on AEM applications securityA Hacker's perspective on AEM applications security
A Hacker's perspective on AEM applications security
 
How to Schedule Automated Tasks in Drupal with Cron?
How to Schedule Automated Tasks in Drupal with Cron?How to Schedule Automated Tasks in Drupal with Cron?
How to Schedule Automated Tasks in Drupal with Cron?
 
aclpwn - Active Directory ACL exploitation with BloodHound
aclpwn - Active Directory ACL exploitation with BloodHoundaclpwn - Active Directory ACL exploitation with BloodHound
aclpwn - Active Directory ACL exploitation with BloodHound
 
Troopers 19 - I am AD FS and So Can You
Troopers 19 - I am AD FS and So Can YouTroopers 19 - I am AD FS and So Can You
Troopers 19 - I am AD FS and So Can You
 
HTTP Request Smuggling via higher HTTP versions
HTTP Request Smuggling via higher HTTP versionsHTTP Request Smuggling via higher HTTP versions
HTTP Request Smuggling via higher HTTP versions
 
Operationalizing Multi Cluster Istio_ Lessons Learned and Developing Ambient ...
Operationalizing Multi Cluster Istio_ Lessons Learned and Developing Ambient ...Operationalizing Multi Cluster Istio_ Lessons Learned and Developing Ambient ...
Operationalizing Multi Cluster Istio_ Lessons Learned and Developing Ambient ...
 
Data Types In PHP
Data Types In PHPData Types In PHP
Data Types In PHP
 
Attacking ADFS Endpoints - DerbyCon
Attacking ADFS Endpoints - DerbyConAttacking ADFS Endpoints - DerbyCon
Attacking ADFS Endpoints - DerbyCon
 
What’s wrong with WebSocket APIs? Unveiling vulnerabilities in WebSocket APIs.
What’s wrong with WebSocket APIs? Unveiling vulnerabilities in WebSocket APIs.What’s wrong with WebSocket APIs? Unveiling vulnerabilities in WebSocket APIs.
What’s wrong with WebSocket APIs? Unveiling vulnerabilities in WebSocket APIs.
 
Same origin policy
Same origin policySame origin policy
Same origin policy
 

Similar to SOLID: the core principles of success of the Symfony web framework and of your applications

Phpne august-2012-symfony-components-friends
Phpne august-2012-symfony-components-friendsPhpne august-2012-symfony-components-friends
Phpne august-2012-symfony-components-friends
Michael Peacock
 
symfony on action - WebTech 207
symfony on action - WebTech 207symfony on action - WebTech 207
symfony on action - WebTech 207
patter
 
How to disassemble one monster app into an ecosystem of 30
How to disassemble one monster app into an ecosystem of 30How to disassemble one monster app into an ecosystem of 30
How to disassemble one monster app into an ecosystem of 30
fiyuer
 
Developing your first application using FI-WARE
Developing your first application using FI-WAREDeveloping your first application using FI-WARE
Developing your first application using FI-WARE
Fermin Galan
 

Similar to SOLID: the core principles of success of the Symfony web framework and of your applications (20)

Build powerfull and smart web applications with Symfony2
Build powerfull and smart web applications with Symfony2Build powerfull and smart web applications with Symfony2
Build powerfull and smart web applications with Symfony2
 
Phpne august-2012-symfony-components-friends
Phpne august-2012-symfony-components-friendsPhpne august-2012-symfony-components-friends
Phpne august-2012-symfony-components-friends
 
symfony on action - WebTech 207
symfony on action - WebTech 207symfony on action - WebTech 207
symfony on action - WebTech 207
 
Creating your own framework on top of Symfony2 Components
Creating your own framework on top of Symfony2 ComponentsCreating your own framework on top of Symfony2 Components
Creating your own framework on top of Symfony2 Components
 
Laravel for Web Artisans
Laravel for Web ArtisansLaravel for Web Artisans
Laravel for Web Artisans
 
Symfony2 - from the trenches
Symfony2 - from the trenchesSymfony2 - from the trenches
Symfony2 - from the trenches
 
SymfonyCon Berlin 2016 - Symfony Plugin for PhpStorm - 3 years later
SymfonyCon Berlin 2016 - Symfony Plugin for PhpStorm - 3 years laterSymfonyCon Berlin 2016 - Symfony Plugin for PhpStorm - 3 years later
SymfonyCon Berlin 2016 - Symfony Plugin for PhpStorm - 3 years later
 
Hexagonal architecture
Hexagonal architectureHexagonal architecture
Hexagonal architecture
 
Osiąganie mądrej architektury z Symfony2
Osiąganie mądrej architektury z Symfony2 Osiąganie mądrej architektury z Symfony2
Osiąganie mądrej architektury z Symfony2
 
How to disassemble one monster app into an ecosystem of 30
How to disassemble one monster app into an ecosystem of 30How to disassemble one monster app into an ecosystem of 30
How to disassemble one monster app into an ecosystem of 30
 
Symfony2 revealed
Symfony2 revealedSymfony2 revealed
Symfony2 revealed
 
Hexagonal architecture in PHP
Hexagonal architecture in PHPHexagonal architecture in PHP
Hexagonal architecture in PHP
 
Simplify your professional web development with symfony
Simplify your professional web development with symfonySimplify your professional web development with symfony
Simplify your professional web development with symfony
 
Developing your first application using FI-WARE
Developing your first application using FI-WAREDeveloping your first application using FI-WARE
Developing your first application using FI-WARE
 
Introduction to Research Automation with Globus
Introduction to Research Automation with GlobusIntroduction to Research Automation with Globus
Introduction to Research Automation with Globus
 
What's New In Laravel 5
What's New In Laravel 5What's New In Laravel 5
What's New In Laravel 5
 
Introduction to CodeIgniter
Introduction to CodeIgniterIntroduction to CodeIgniter
Introduction to CodeIgniter
 
Spark IT 2011 - Simplified Web Development using Java Server Faces 2.0
Spark IT 2011 - Simplified Web Development using Java Server Faces 2.0Spark IT 2011 - Simplified Web Development using Java Server Faces 2.0
Spark IT 2011 - Simplified Web Development using Java Server Faces 2.0
 
Domain Driven Design using Laravel
Domain Driven Design using LaravelDomain Driven Design using Laravel
Domain Driven Design using Laravel
 
Grâce aux tags Varnish, j'ai switché ma prod sur Raspberry Pi
Grâce aux tags Varnish, j'ai switché ma prod sur Raspberry PiGrâce aux tags Varnish, j'ai switché ma prod sur Raspberry Pi
Grâce aux tags Varnish, j'ai switché ma prod sur Raspberry Pi
 

More from Vladyslav Riabchenko

More from Vladyslav Riabchenko (8)

Modèle de domaine riche dans une application métier complexe un exemple pratique
Modèle de domaine riche dans une application métier complexe un exemple pratiqueModèle de domaine riche dans une application métier complexe un exemple pratique
Modèle de domaine riche dans une application métier complexe un exemple pratique
 
SOLID : les principes à l’origine du succès de Symfony et de vos applications
SOLID : les principes à l’origine du succès de Symfony et de vos applicationsSOLID : les principes à l’origine du succès de Symfony et de vos applications
SOLID : les principes à l’origine du succès de Symfony et de vos applications
 
Sécurisation de vos applications web à l’aide du composant Security de Symfony
Sécurisation de vos applications web  à l’aide du composant Security de SymfonySécurisation de vos applications web  à l’aide du composant Security de Symfony
Sécurisation de vos applications web à l’aide du composant Security de Symfony
 
Sécurisation de vos applications web à l’aide du composant Security de Symfony
Sécurisation de vos applications web à l’aide du composant Security de SymfonySécurisation de vos applications web à l’aide du composant Security de Symfony
Sécurisation de vos applications web à l’aide du composant Security de Symfony
 
Git
GitGit
Git
 
Versionning sémantique et Composer
Versionning sémantique et ComposerVersionning sémantique et Composer
Versionning sémantique et Composer
 
Injection de dépendances dans Symfony >= 3.3
Injection de dépendances dans Symfony >= 3.3Injection de dépendances dans Symfony >= 3.3
Injection de dépendances dans Symfony >= 3.3
 
Les patrons de conception du composant Form
Les patrons de conception du composant FormLes patrons de conception du composant Form
Les patrons de conception du composant Form
 

Recently uploaded

Prosigns: Transforming Business with Tailored Technology Solutions
Prosigns: Transforming Business with Tailored Technology SolutionsProsigns: Transforming Business with Tailored Technology Solutions
Prosigns: Transforming Business with Tailored Technology Solutions
Prosigns
 
Mastering Windows 7 A Comprehensive Guide for Power Users .pdf
Mastering Windows 7 A Comprehensive Guide for Power Users .pdfMastering Windows 7 A Comprehensive Guide for Power Users .pdf
Mastering Windows 7 A Comprehensive Guide for Power Users .pdf
mbmh111980
 

Recently uploaded (20)

WSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital Transformation
WSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital TransformationWSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital Transformation
WSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital Transformation
 
Using IESVE for Room Loads Analysis - Australia & New Zealand
Using IESVE for Room Loads Analysis - Australia & New ZealandUsing IESVE for Room Loads Analysis - Australia & New Zealand
Using IESVE for Room Loads Analysis - Australia & New Zealand
 
How Does XfilesPro Ensure Security While Sharing Documents in Salesforce?
How Does XfilesPro Ensure Security While Sharing Documents in Salesforce?How Does XfilesPro Ensure Security While Sharing Documents in Salesforce?
How Does XfilesPro Ensure Security While Sharing Documents in Salesforce?
 
Gamify Your Mind; The Secret Sauce to Delivering Success, Continuously Improv...
Gamify Your Mind; The Secret Sauce to Delivering Success, Continuously Improv...Gamify Your Mind; The Secret Sauce to Delivering Success, Continuously Improv...
Gamify Your Mind; The Secret Sauce to Delivering Success, Continuously Improv...
 
Paketo Buildpacks : la meilleure façon de construire des images OCI? DevopsDa...
Paketo Buildpacks : la meilleure façon de construire des images OCI? DevopsDa...Paketo Buildpacks : la meilleure façon de construire des images OCI? DevopsDa...
Paketo Buildpacks : la meilleure façon de construire des images OCI? DevopsDa...
 
Advanced Flow Concepts Every Developer Should Know
Advanced Flow Concepts Every Developer Should KnowAdvanced Flow Concepts Every Developer Should Know
Advanced Flow Concepts Every Developer Should Know
 
AI/ML Infra Meetup | Perspective on Deep Learning Framework
AI/ML Infra Meetup | Perspective on Deep Learning FrameworkAI/ML Infra Meetup | Perspective on Deep Learning Framework
AI/ML Infra Meetup | Perspective on Deep Learning Framework
 
OpenFOAM solver for Helmholtz equation, helmholtzFoam / helmholtzBubbleFoam
OpenFOAM solver for Helmholtz equation, helmholtzFoam / helmholtzBubbleFoamOpenFOAM solver for Helmholtz equation, helmholtzFoam / helmholtzBubbleFoam
OpenFOAM solver for Helmholtz equation, helmholtzFoam / helmholtzBubbleFoam
 
Into the Box 2024 - Keynote Day 2 Slides.pdf
Into the Box 2024 - Keynote Day 2 Slides.pdfInto the Box 2024 - Keynote Day 2 Slides.pdf
Into the Box 2024 - Keynote Day 2 Slides.pdf
 
AI/ML Infra Meetup | Reducing Prefill for LLM Serving in RAG
AI/ML Infra Meetup | Reducing Prefill for LLM Serving in RAGAI/ML Infra Meetup | Reducing Prefill for LLM Serving in RAG
AI/ML Infra Meetup | Reducing Prefill for LLM Serving in RAG
 
A Python-based approach to data loading in TM1 - Using Airflow as an ETL for TM1
A Python-based approach to data loading in TM1 - Using Airflow as an ETL for TM1A Python-based approach to data loading in TM1 - Using Airflow as an ETL for TM1
A Python-based approach to data loading in TM1 - Using Airflow as an ETL for TM1
 
Prosigns: Transforming Business with Tailored Technology Solutions
Prosigns: Transforming Business with Tailored Technology SolutionsProsigns: Transforming Business with Tailored Technology Solutions
Prosigns: Transforming Business with Tailored Technology Solutions
 
GraphAware - Transforming policing with graph-based intelligence analysis
GraphAware - Transforming policing with graph-based intelligence analysisGraphAware - Transforming policing with graph-based intelligence analysis
GraphAware - Transforming policing with graph-based intelligence analysis
 
Top Mobile App Development Companies 2024
Top Mobile App Development Companies 2024Top Mobile App Development Companies 2024
Top Mobile App Development Companies 2024
 
A Comprehensive Appium Guide for Hybrid App Automation Testing.pdf
A Comprehensive Appium Guide for Hybrid App Automation Testing.pdfA Comprehensive Appium Guide for Hybrid App Automation Testing.pdf
A Comprehensive Appium Guide for Hybrid App Automation Testing.pdf
 
Field Employee Tracking System| MiTrack App| Best Employee Tracking Solution|...
Field Employee Tracking System| MiTrack App| Best Employee Tracking Solution|...Field Employee Tracking System| MiTrack App| Best Employee Tracking Solution|...
Field Employee Tracking System| MiTrack App| Best Employee Tracking Solution|...
 
Accelerate Enterprise Software Engineering with Platformless
Accelerate Enterprise Software Engineering with PlatformlessAccelerate Enterprise Software Engineering with Platformless
Accelerate Enterprise Software Engineering with Platformless
 
TROUBLESHOOTING 9 TYPES OF OUTOFMEMORYERROR
TROUBLESHOOTING 9 TYPES OF OUTOFMEMORYERRORTROUBLESHOOTING 9 TYPES OF OUTOFMEMORYERROR
TROUBLESHOOTING 9 TYPES OF OUTOFMEMORYERROR
 
Mastering Windows 7 A Comprehensive Guide for Power Users .pdf
Mastering Windows 7 A Comprehensive Guide for Power Users .pdfMastering Windows 7 A Comprehensive Guide for Power Users .pdf
Mastering Windows 7 A Comprehensive Guide for Power Users .pdf
 
Cyaniclab : Software Development Agency Portfolio.pdf
Cyaniclab : Software Development Agency Portfolio.pdfCyaniclab : Software Development Agency Portfolio.pdf
Cyaniclab : Software Development Agency Portfolio.pdf
 

SOLID: the core principles of success of the Symfony web framework and of your applications

  • 1. SOLID: the core principles of success of the Symfony web framework and of your applications Software Engineering Conference Russia 2018 October 12-13 Moscow RIABCHENKO Vladyslav
  • 2. https://vria.eu contact@vria.eu https://twitter.com/RiaVlad RIABCHENKO Vladyslav 5+ years full stack web-developer Symfony certified developer and contributor Technical architect at Webnet (France)
  • 3. Symfony 3 1. Symfony 2. SOLID 3. Single responsibility principle 4. Open/closed principle 5. Liskov substitution principle 6. Interface segregation principle 7. Dependency inversion principle Plan
  • 5. Symfony 5 2. PHP framework for web projects 1. Set of reusable PHP components MVC Pattern Model View HTTP Request Routing Controller HTTP Response
  • 6. Symfony 6 HttpKernel DependencyInjection HttpFoundation Routing EventDispatcher Heart of framework that manages HTTP request-response cycle Object-oriented layer for request, response, session, etc. Maps requests to variables (controller, path parameters) Mediator that allows decoupled components to communicate by dispatching events Service container that instantiates service objects out of configuration and injects their dependencies and 45 others including Security, Form, Console, Cache, Asset, Validator, Serializer, etc.
  • 7. Symfony 7 FrameworkBundle Configures Symfony components and glues them in web app. It registers services and event listeners. Bundles are reusable plugins that provide services, routes, controllers, templates, etc. Your code Provides routes, controllers, services, business logic, templates for your purpose. doctrine/orm DBAL and ORM libraries to communicate with databases. twig/twig Template engine.
  • 9. SOLID 9 – Single Responsibility Principle – Open/Closed Principle – Liskov Substitution Principle – Interface Segregation Principle – Dependency Inversion Principle Reusable Flexible Maintainable Understandable Fragile Duplicated Viscose Unreasonably complex SOLID helps to design a system that is … and avoid a system that is S O L I D
  • 11. Single responsibility principle 11 class ReportService { public function createReport($data) { // working with report manager at domain layer } public function getLastThreeReportsByAuthor($author) { // working with database at ORM or DBAL layer } public function searchBy($criteria) { // working with database at ORM or DBAL layer } public function export(Report $report) { // working with filesystem at by means of PHP functions } } A class should have only a single responsibility. Responsibility is a reason to change.
  • 12. Single responsibility principle // working with report manager at domain layer (business logic) class ReportManager { public function createReport($data) { ... } } // working with filesystem and pdf, excel, csv, etc. class ReportExporter { public function export(Report $report) { ... } } // working with database at ORM and/or DBAL layer class ReportRepository { public function getLastThreeReportsByAuthor($author) { ... } public function searchBy($criteria) { ... } } Manager Exporter Repository 12
  • 13. Single responsibility principle 13 Feature : Store users in database Feature : Store orders in database Feature : Authenticate users against database (login form, HTTP auth, whatever…) Feature : On creation of order assign a currentrly connected user to it. Store user credentials in session and authenticate users at latter requests
  • 14. Single responsibility principle 14 SecurityContext Stores a user token setToken($token), getToken() Checks if a current user authorization isGranted('attr', $sub) AuthenticationProvider Authenticates a token UserProvider Retrieves or refreshes user from database EntityManager All interaction with database at ORM and DBAL levels OrderListener Your listener that modifies order before it gets inserted Injecting SecurityContext service in any EntityManager’s listener created a circular dependency.
  • 15. Single responsibility principle 15 Solution is splitting SecurityContext into AuthorizationChecker and TokenStorage AuthorizationChecker AuthenticationProvider UserProvider EntityManager OrderListener TokenStorage getToken() setToken($token) isGranted('attr', $sub)
  • 17. Open/closed principle Entities should be open for extension, but closed for modification. 17 Open for extension: • Alter or add behavior • Extend an entity with new properties Closed for modification: • Adapt entity without modifying its source code • Provide an entity with clear and stable interface
  • 18. Open/closed principle 18 Techniques to stay in compliance with the open/closed principle: • Abstraction / Inheritance / Polymorphism • Dependency injection • Single responsibility principle • Design patterns. For example, those of GoF: • Abstract Factory, Factory Method, Builder, Prototype, • Bridge, Decorator, Proxy, • Command, Mediator, Memento, Observer, State, Strategy, Template Method, Visitor.
  • 19. SymfonyComponentHttpKernel App Open/closed principle 19 // public/index.php use AppKernel; use SymfonyComponentHttpFoundationRequest; $kernel = new Kernel($env, $debug); $request = Request::createFromGlobals(); $response = $kernel->handle($request); $response->send(); HttpKernel - dispatcher + handle($request): Response - container - httpKernel Kernel + handle($request) + registerBundles() + configureRoutes() Kernel + registerBundles() + configureRoutes() All HTTP requests are treated by front controller.
  • 20. Open/closed principle 20 Request-Response cycle is open for extension thanks to events dispatched at every step. Request Response resolve controller REQUEST resolve arguments call controller CONTROLLER CONTROLLER_ARGUMENTS Response RESPONSE FINISH_REQUEST Response exists TERMINATE VIEW Exception EXCEPTION
  • 22. Liskov substitution principle Objects should be replaceable with instances of their subtypes without altering the correctness of the program. 22 LSP describes behavioral subtyping – semantic rather than merely syntactic relation.
  • 23. Liskov substitution principle 23 Rectangle Square is a regular rectangle with four equal sides. - width - height + setWidth($width) + setHeight($height) + getArea() + setWidth($width) + setHeight($height) Square function client(Rectangle $rect) { $rect->setHeight(8); $rect->setWidth(3); assert($rect->area() == 24); } Client will fail when you pass Square object class Square extends Rectangle { public function setWidth($width) { $this->width = $width; $this->height = $width; } public function setHeight($height) { $this->height = $height; $this->width = $height; } }
  • 24. Liskov substitution principle 24 • Preconditions cannot be strengthened in a subtype • Postconditions cannot be weakened in a subtype • Invariants of the supertype must be preserved in a subtype LSP suggests behavioral conditions resembling those of design by contract methodology: Rectangle Precondition: width is integer > 0 Postcondition: $this->width equals $width Invariant: $this->height remains unchanged Precondition: width is integer > 0 Postcondition: $this->width equals $width Invariant: $this->height remains unchanged Invariant: $this->width equals $this->height - width - height + setWidth($width) + setHeight($height) + getArea() + setWidth($width) + setHeight($height) Square
  • 25. Liskov substitution principle 25 Authorization – verifying access rights/privileges of currently authenticated user. In Symfony authorization is based on: • Token: the user’s authentication information (roles, etc.), • Attributes: rights/privileges to verify the access to, • Object: Any object for which access control needs to be checked. $authorizationChecker->isGranted('ROLE_ADMIN'); $authorizationChecker->isGranted('EDIT’, $comment); $authorizationChecker->isGranted(['VIEW', 'MANAGE'], $order);
  • 26. Liskov substitution principle 26 - voters : VoterInterface[] + decide($token, $attributes, $object) AuthorizationChecker - tokenStorage - accessDecisionManager + isGranted($attributes, $object) AccessDecisionManager + vote($token, $subject, $attributes) VoterInterface isGranted returns true/false. It delegates decision to AccessDecisionManager::decide. decide asks all voters to vote and returns final decision. vote must return one of these values : ACCESS_GRANTED, ACCESS_ABSTAIN or ACCESS_DENIED.
  • 27. DoctrineORM Liskov substitution principle 27 Doctrine is several PHP libraries focused on database storage and object mapping. Instance of Article id: 17 author: Author(id=3, name=Marie) createdAt: DateTime(2018-10-01) text: "Hi Secrus! Today we…" Instance of Author id: 3 name: Marie articles: [Article(id=17, …)] article id author_id created_at text 16 2 2018-05-21 In thi… 17 17 2018-10-01 Hi sec… … author id name 2 Albert 3 Marie 4 Isaac …
  • 28. Liskov substitution principle 28 Doctrine triggers a bunch of events during the life-time of stored entities: prePersist and postPersist, preUpdate and postUpdate, preRemove and postRemove. use DoctrineORMEventLifecycleEventArgs; use DoctrineORMMapping as ORM; class Article { private $createdAt; private $updatedAt; private $createdBy; private $updatedBy; /** @ORMPrePersist() */ public function prePersist(LifecycleEventArgs $event) { $this->createdAt = new DateTime(); } /** @ORMPreUpdate() */ public function preUpdate(LifecycleEventArgs $event) { $article = $event->getEntity(); $article->setUpdatedAt(new DateTime()); } } Precondition: $event->getEntity() is an instance of Article
  • 29. use AppEntityArticle; use DoctrineORMEventLifecycleEventArgs; class ArticleLifecycleListener { /** @var AppEntity|Author */ private $user; public function prePersist(LifecycleEventArgs $event) { $article = $event->getEntity(); if ($article instanceof Article) { $article->setCreatedBy($this->user); } } public function preUpdate(LifecycleEventArgs $event) { $article = $event->getEntity(); if ($article instanceof Article) { $article->setUpdatedBy($this->user); } } } Liskov substitution principle 29 Precondition: $event->getEntity() is an instance of any entity Doctrine listeners as services have access to other services via dependency injection :
  • 31. Interface segregation principle 31 Many client-specific interfaces are better than one general-purpose interface. No client should be forced to depend on methods it does not use.
  • 32. Interface segregation principle 32 Service container Configuraion: yaml, xml, php For each service: - id - class name - dependencies - … - Instantiate service object on demand - Instantiate its dependencies - Inject dependencies into service - Store and return the service - Return the same instance on consecutive demands “Compilation” Container manages services which are any useful objects.
  • 33. PsrContainer Interface segregation principle 33 Fetch services ContainerInterface + get($id): mixed + has($id): bool SymfonyComponentDependencyInjection ContainerInterface + set($id, $service) + initialized($id): bool + getParameter($name): mixed Container - services - parameterBag - aliases + compile() Configure services, parameters Compile container (init, cache) (Any client code) (Extensions) (Kernel)
  • 34. Interface segregation principle 34 Routes configuration Url matcher '_route’ => string 'blog_list' '_controller' => string 'AppControllerBlog::list' 'page’ => string '2' 'category’ => string 'secr-conference' Url generator '/blog/secr-conference' '/blog/secr/2' $matcher->match('/blog/secr-conference/2'); $generator->generate('blog_list', ['category' => 'secr-conference']); $generator->generate('blog_list', ['category' => 'secr', 'page' => 2]); # config/routes.yaml blog_list: # route name path: /blog/{category}/{page} # path pattern controller: AppControllerBlog::list # controller to execute requirements: # param constraints category: '[a-z0-9-_]+' page: 'd+' defaults: # param default values page: 1
  • 35. SymfonyComponentRouting Interface segregation principle 35 UrlMatcherInterface + match($pathinfo): array UrlGeneratorInterface + generate ($name, $parameters, $referenceType): string RouterInterface + getRouteCollection(): RouteCollection Router - collection: RouteCollection - options: array - context Contains the configuration of all known routes.
  • 37. Dependency inversion principle 37 High-level modules should not depend on low-level modules. Both should depend on abstractions. Abstractions should not depend on details. Details should depend on abstractions.
  • 38. Framework Dependency inversion principle 38 namespace Monolog; class Logger { public function log($message) { echo $message; } } namespace Framework; use MonologLogger; class Kernel { private $logger; public function __construct(Logger $logger) { $this->logger = $logger; } public function handle() { $this->logger->log('...'); // ... } } Monolog Kernel Logger
  • 39. Dependency inversion principle 39 namespace Framework; class Kernel { private $logger; public function __construct(LoggerInterface $logger) { $this->logger = $logger; } } namespace Monolog; use FrameworkLoggerInterface; class Logger implements LoggerInterface { public function log($message) { echo $message; } } namespace Framework; interface LoggerInterface { public function log($message); } Framework Monolog Kernel LoggerLoggerInterface
  • 40. AbstractLogger Dependency inversion principle 40 More flexible solution Framework Monolog Kernel Logger LoggerInterface
  • 41. Dependency inversion principle 41 PsrLog SymfonyHTTPKernel Monolog Kernel Logger LoggerInterface PSR – PHP Standards Recommendations by FIG – Framework Interoperability Group SymfonyRouting Router SymfonySecurity Handlers ... ... ...
  • 42. Dependency inversion principle 42 Symfony uses interfaces and dependency injection everywhere. SymfonyForm SymfonyValidator ACMEValidator FormInterface Form ExtensionValidator ValidatorExtension ValidatorInterface Validator Validator - validator: ValidatorInterface FormExtensionInterface