SlideShare a Scribd company logo
1 of 124
Download to read offline
The IoC Hydra
Kacper Gunia @cakper
Technical Team Leader @SensioLabsUK
Symfony Certified Developer
PHPers Silesia @PHPersPL
CHAPTER 1: THE THEORY
THIS IS NOT YET ANOTHER
DEPENDENCY INJECTION TALK ;)
SO WE NEED SOME CLARIFICATION
IOC !== DI
–Pico Container
“Inversion of Control (IoC) is a design pattern
that addresses a component’s dependency
resolution, configuration and lifecycle. ”
–Pico Container
“It suggests that the control of those three
should not be the concern of the component
itself. Thus it is inverted back.”
–Pico Container
“Dependency Injection is where components
are given their dependencies through their
constructors, methods, or directly into fields.”
Inversion of Control
Dependency
Injection
Events
AOP
WHY DO WE IOC?
PROS
• Separation of concerns:
• dependency resolution, configuration and lifecycle
• Enforcing Single Responsibility Principle
• Easier testing
• Modular architecture, loose coupling
CONS
• Learning curve
• Code is harder do analyse/debug
• Moves complexity somewhere else (doesn’t remove)
• Need for extra tools like Containers / Dispatchers
HOW DO WE WRITE SOFTWARE
WITHOUT IOC?
EXAMPLE
interface FileEraser

{

public function erase($filename);

}
EXAMPLE
interface Logger

{

public function log($log);

}



class PrintingLogger implements Logger

{

public function log($log)

{

echo $log;

}

}
EXAMPLE
class LocalFileEraser implements FileEraser

{

public function erase($filename) {

$logger = new PrintingLogger();

$logger->log("Attempt to erase file: " . $filename);



unlink($filename);



$logger->log("File " . $filename . " was erased.”);

}

}
EXAMPLE
$eraser = new LocalFileEraser();

$eraser->erase('important-passwords.txt');
HOW CAN WE FIX IT WITH DI?
EXAMPLE WITH DI
class LocalFileEraser implements FileEraser
{

private $logger;



public function __construct(Logger $logger) {

$this->logger = $logger;

}



public function erase($path) {

$this->logger->log("Attempt to erase file: " . $path);


unlink($path);


$this->logger->log("File " . $path . " was erased.");

}

}
EXAMPLE WITH DI
$logger = new PrintingLogger();

$eraser = new LocalFileEraser($logger);



$eraser->erase('important-passwords.txt');
What (is being executed)
Known Unknown
KnownUnknown
When(isbeingexecuted)
Dependency
Injection
Stages of loosening control
(from the component point of view)
HOW CAN WE FIX IT WITH EVENTS?
EXAMPLE WITH EVENTS
interface Listener

{

public function handle(Event $event);

}



interface Event

{



}
EXAMPLE WITH EVENTS
class FileEvent implements Event

{

private $path;

public function __construct($path)

{

$this->path = $path;

}



public function getPath()

{

return $this->path;

}

}
EXAMPLE WITH EVENTS
class FileEraseWasInitialised extends FileEvent

{



}



class FileWasErased extends FileEvent

{



}
EXAMPLE WITH EVENTS
class LoggingFileEventListener implements Listener

{

private $logger;



public function __construct(Logger $logger)

{

$this->logger = $logger;

}



public function handle(Event $event)

{

if ($event instanceof FileEvent) {

$this->logger->log(get_class($event).' '.$event->getPath());

}

}

}
EXAMPLE WITH EVENTS
trait Observable

{

private $listeners = [];



public function addListener(Listener $listener)

{

$this->listeners[] = $listener;

}



public function dispatch(Event $event)

{

foreach ($this->listeners as $listener) {

$listener->handle($event);

}

}

}
EXAMPLE WITH EVENTS
class LocalFileEraser implements FileEraser

{

use Observable;



public function erase($filename)

{

$this->dispatch(new FileEraseWasInitialised($filename));



unlink($filename);



$this->dispatch(new FileWasErased($filename));

}

}
EXAMPLE WITH EVENTS
$eraser = new LocalFileEraser();

$listener = new LoggingFileEventListener(new PrintingLogger());
$eraser->addListener($listener);



$eraser->erase('important-passwords.txt');
What (is being executed)
Known Unknown
KnownUnknown
When(isbeingexecuted)
Events
Stages of loosening control
(from the component point of view)
HOW CAN WE FIX IT WITH AOP?
EXAMPLE WITH AOP USING DECORATOR
class LocalFileEraser implements FileEraser

{

public function erase($filename)

{

unlink($filename);

}

}
EXAMPLE WITH AOP USING DECORATOR
class LoggingFileEraser implements FileEraser

{

private $decorated;



private $logger;



public function __construct(FileEraser $decorated, Logger $logger)

{

$this->decorated = $decorated;

$this->logger = $logger;

}



public function erase($filename)

{

$this->logger->log('File erase was initialised' . $filename);



$this->decorated->erase($filename);



$this->logger->log('File was erased' . $filename);

}

}
EXAMPLE WITH AOP USING DECORATOR
$localFileEraser = new LocalFileEraser();

$logger = new PrintingLogger();



$eraser = new LoggingFileEraser($localFileEraser, $logger);



$eraser->erase('important-passwords.txt');
What (is being executed)
Known Unknown
KnownUnknown
When(isbeingexecuted)
AOP
Stages of loosening control
(from the component point of view)
What (is being executed)
Known Unknown
KnownUnknown
When(isbeingexecuted)
Dependency
Injection
Events
AOP
Stages of loosening control
(from the component point of view)
FRAMEWORKS & LIBRARIES
A libraries provide functionality that
you decide when to call.
Frameworks provide an architecture
for the application and
decide when to call your code.
“DON’T CALL US, WE’LL CALL YOU”
aka Hollywood Principle
Frameworks utilise IoC principles
and can be seen as one of its manifestations.
CHAPTER 2: THE PRACTICE
DEPENDENCY INJECTION
CONTAINERS
WHERE DIC CAN HELP
RESOLVING GRAPHS OF OBJECTS
$dsn = 'mysql:host=localhost;dbname=testdb;charset=utf8';

$dbUsername = 'username';

$dbPassword = 'password';

$customerRepository = new CustomerRepository(new PDO($dsn, $dbUsername, $dbPassword));



$smtpHost = 'smtp.example.org';

$smtpPort = 25;

$smtpUsername = 'username';

$smtpPassword = 'password';

$transport = new Swift_SmtpTransport($smtpHost, $smtpPort);

$transport->setUsername($smtpUsername);

$transport->setPassword($smtpPassword);

$mailer = new Swift_Mailer($transport);



$loggerName = "App";

$logger = new MonologLogger($loggerName);

$stream = "app.log";

$logger->pushHandler(new MonologHandlerStreamHandler($stream));



$controller = new RegistrationController($customerRepository, $mailer, $logger);
RESOLVING GRAPHS OF OBJECTS
use PimpleContainer;



$container = new Container();



$container['dsn'] = 'mysql:host=localhost;dbname=testdb;charset=utf8';

$container['db_username'] = 'username';

$container['dsn'] = 'password';



$container['pdo'] = function ($c) {

return new PDO($c['dsn'], $c['db_username'], $c['dsn']);

};


$container['customer_repository'] = function ($c) {

return new CustomerRepository($c['pdo']);

};
RESOLVING GRAPHS OF OBJECTS
$container['smtp_host'] = 'smtp.example.org';

$container['smtp_port'] = 25;

$container['smtp_username'] = 'username';

$container['smtp_password'] = 'password';



$container['transport'] = function ($c) {

return new Swift_SmtpTransport($c['smtp_host'], $c['smtp_port']);

};



$container->extend('transport', function ($transport, $c) {

$transport->setUsername($c['smtp_username']);

$transport->setPassword($c['smtp_password']);



return $transport;

});



$container['mailer'] = function ($c) {

return new Swift_Mailer($c['transport']);

};
RESOLVING GRAPHS OF OBJECTS
$container['logger_name'] = "App";

$container['stream_name'] = "app_" . $container['environment'] . ".log";



$container['logger'] = function ($c) {

return new MonologLogger($c['logger_name']);

};



$container->extend('transport', function ($logger, $c) {

$logger->pushHandler(
new MonologHandlerStreamHandler($c[‘stream_handler'])
);



return $logger;

});



$container['stream_handler'] = function ($c) {

return new MonologHandlerStreamHandler($c['stream_name']);

};
RESOLVING GRAPHS OF OBJECTS
$container['registration_controller'] = function ($c) {

return new RegistrationController(
$c['customer_repository'],
$c['mailer'],
$c[‘logger’]
);

};
LIFECYCLE MANAGEMENT
$container['session_storage'] = function ($c) {

return new SessionStorage('SESSION_ID');

};
LIFECYCLE MANAGEMENT
$container['session_storage'] = $container->factory(function ($c) {

return new SessionStorage('SESSION_ID');

});
WHERE DIC CAN HARM
SERVICE LOCATOR
class RegistrationController {

function resetPasswordAction() {

$mailer = Container::instance()['mailer'];

//...

}

}
SERVICE LOCATOR
• Coupled to container
• Responsible for resolving dependencies
• Dependencies are hidden
• Hard to test
• Might be ok when modernising legacy!
SETTER INJECTION
SETTER INJECTION
• Forces to be defensive as dependencies are optional
• Dependency is not locked (mutable)
• In some cases can be replaced with events
• We can avoid it by using NullObject pattern
SETTER INJECTION
class LocalFileEraser implements FileEraser

{

private $logger;



public function setLogger(Logger $logger)

{

$this->logger = $logger;

}



public function erase($filename)

{

if ($this->logger instanceof Logger) {

$this->logger->log("Attempt to erase file: " . $filename);

}



unlink($filename);



if ($this->logger instanceof Logger) {

$this->logger->log("File " . $filename . " was deleted");

}

}

}
SETTER INJECTION
class LocalFileEraser implements FileEraser

{

private $logger;



public function __construct(Logger $logger)

{

$this->logger = $logger;

}



public function erase($path)

{

$this->logger->log("Attempt to erase file: " . $path);



unlink($path);



$this->logger->log("File " . $path . " was erased.”);

}

}
SETTER INJECTION
class NullLogger implements Logger {



public function log($log)

{

// whateva...

}

}



$eraser = new LocalFileEraser(new NullLogger());

$eraser->erase('important-passwords.txt');
PARTIAL APPLICATION
DI WAY OF DOING THINGS
interface Logger

{

public function log($log);

}



class PrintingLogger implements Logger

{

public function log($log)

{

echo $log;

}

}
DI WAY OF DOING THINGS
class LocalFileEraser implements FileEraser

{

private $logger;



public function __construct(Logger $logger)

{

$this->logger = $logger;

}



public function erase($path)

{

$this->logger->log("Attempt to erase file: " . $path);



unlink($path);



$this->logger->log("File " . $path . " was deleted");

}

}
DI WAY OF DOING THINGS
$logger = new PrintingLogger();

$eraser = new LocalFileEraser($logger);



$eraser->erase('important-passwords.txt');
FUNCTIONAL WAY OF DOING THINGS
$erase = function (Logger $logger, $path)

{

$logger->log("Attempt to erase file: " . $path);



unlink($path);



$logger->log("File " . $path . " was deleted");

};
FUNCTIONAL WAY OF DOING THINGS
use ReactPartial;


$erase = function (Logger $logger, $path)

{

$logger->log("Attempt to erase file: " . $path);

unlink($path);

$logger->log("File " . $path . " was deleted");

};



$erase = Partialbind($erase, new PrintingLogger());


$erase('important-passwords.txt');
CHAPTER 3: THE SYMFONY
SYMFONY/DEPENDENCY-INJECTION
FEATURES
• Many configurations formats
• Supports Factories/Configurators/Scopes/Decoration
• Extendable with Compiler Passes
• Supports lazy loading of services
PERFORMANCE
PERFORMANCE OF SYMFONY DIC
• Cached/Dumped to PHP code
• In debug mode it checks whether config is fresh
• During Compilation phase container is being optimised
LARGE NUMBER OF
CONFIGURATION FILES
SLOWS CONTAINER BUILDER
SLOW COMPILATION
• Minimise number of bundles/config files used
• Try to avoid using extras like JMSDiExtraBundle
• Can be really painful on NFS
LARGE CONTAINERS
ARE SLOW TO LOAD
AND USE A LOT OF MEMORY
LARGE CONTAINERS
• Review and remove unnecessary services/bundles etc.
• Split application into smaller ones with separate kernels
PRIVATE SERVICES
PRIVATE SERVICES
• It’s only a hint for compiler
• Minor performance gain (inlines instations)
• Private services can still be fetched (not recommended)
LAZY LOADING OF SERVICES
LAZY LOADING OF SERVICES
• Used when instantiation is expensive or not needed
• i.e. event listeners
• Solutions:
• Injecting container directly
• Using proxy objects
INJECTING CONTAINER DIRECTLY
• As fast as it can be
• Couples service implementation to the container
• Makes testing harder
USING PROXY OBJECTS
• Easy to use (just configuration option)
• Code and test are not affected
• Adds a bit of overhead
• especially when services are called many times
• on proxy generation
DEFINING CLASS NAMES
AS PARAMETERS
DEFINING CLASS NAMES
AS PARAMETERS
• Rare use case (since decoration is supported even less)
• Adds overhead
• Will be removed in Symfony 3.0
CIRCULAR REFERENCES
Security
Listener
Doctrine
CIRCULAR REFERENCE
CIRCULAR REFERENCES
• Injecting Container is just a workaround
• Using setter injection after instantiation as well
• Solving design problem is the real challenge
Doctrine
Security
Listener
TokenStorage
BROKEN CIRCULAR REFERENCE
SCOPES
MEANT TO SOLVE
“THE REQUEST PROBLEM”
SCOPE DEFINES
STATE OF THE APPLICATION
PROBLEMS WITH INJECTING
REQUEST TO SERVICES
PROBLEMS WITH INJECTING
REQUEST TO SERVICES
• Causes ScopeWideningInjectionException
• Anti-pattern - Request is a Value Object
• Which means Container was managing it’s state
• Replaced with RequestStack
App
Controller A
Sub Request
Stateful
service
Sub
Request
Master Request
Stateful
service
Master
Request
Controller B
REQUESTS MANAGED WITH SCOPES
App
Controller A
Stateless
service
Request Stack
Controller B
Sub
Request
Master
Request
REQUESTS MANAGED WITH STACK
STATEFUL SERVICES
STATEFUL SERVICES
• Fetch state explicitly on per need basis (RequestStack)
• Use Prototype scope only if you have to…
PROTOTYPE SCOPE
Prototype scope
Prototype-
scoped
Service Z
Stateless
Service A
Prototype scope
Prototype-
scoped
Service Z
Stateless
Service A
Prototype scope
Prototype-
scoped
Service Z
Stateless
Service A
USING PROTOTYPE SCOPE WITH STRICT = TRUE
New Instances
Stateful
Service Z
Stateful
Service Z
Stateful
Service Z
Stateless
Service A
USING PROTOTYPE SCOPE WITH STRICT = FALSE
FORGET ABOUT SCOPES ANYWAY
WILL BE REMOVED IN SYMFONY 3.0
USE SHARED=FALSE INSTEAD
CONTROLLERS
EXTENDING BASE CONTROLLER
• Easy to use by newcomers / low learning curve
• Limits inheritance
• Encourages using DIC as Service Locator
• Hard unit testing
CONTAINER AWARE INTERFACE
• Controller is still coupled to framework
• Lack of convenience methods
• Encourages using DIC as Service Locator
• Testing is still hard
CONTROLLER AS A SERVICE
• Requires additional configuration
• Lack of convenience methods
• Full possibility to inject only relevant dependencies
• Unit testing is easy
• Enables Framework-agnostic controllers
NONE OF THE ABOVE OPTIONS WILL
FORCE YOU TO WRITE GOOD/BAD CODE
SYMFONY/EVENT-DISPATCHER
FEATURES
• Implementation of Mediator pattern
• Allows for many-to-many relationships between objects
• Makes your projects extensible
• Supports priorities/stopping event flow
EVENT DISPATCHER
• Can be (really) hard to debug
• Priorities of events / managing event flow
• Events can be mutable - indirect coupling
• Hard to test
INDIRECT COUPLING PROBLEM
• Two services listening on kernel.request event:
• Priority 16 - GeoIP detector - sets country code
• Priority 8 - Locale detector - uses country code and
user agent
INDIRECT COUPLING PROBLEM
• Both events indirectly coupled (via Request->attributes)
• Configuration change will change the app logic
• In reality we always want to call one after another
Listener A
Listener B
Listener C
DispatcherService
INDIRECT COUPLING PROBLEM
WHEN TO USE EVENT DISPATCHER
• Need to extend Framework or other Bundle
• Building reusable Bundle & need to add extension points
• Consider using separate dispatcher for Domain events
CHAPTER 4: THE END ;)
BE PRAGMATIC
BE EXPLICIT &
DON’T RELY ON MAGIC
Kacper Gunia @cakper
Technical Team Leader @SensioLabsUK
Symfony Certified Developer
PHPers Silesia @PHPersPL
Thanks!
https://joind.in/14979
REFERENCES
• http://martinfowler.com/bliki/InversionOfControl.html
• http://picocontainer.com/introduction.html
• http://www.infoq.com/presentations/8-lines-code-refactoring
• http://richardmiller.co.uk/2014/03/12/avoiding-setter-injection/
• http://art-of-software.blogspot.co.uk/2013/02/cztery-smaki-
odwracania-i-utraty.html

More Related Content

What's hot

Symfony2, creare bundle e valore per il cliente
Symfony2, creare bundle e valore per il clienteSymfony2, creare bundle e valore per il cliente
Symfony2, creare bundle e valore per il clienteLeonardo Proietti
 
Rich Model And Layered Architecture in SF2 Application
Rich Model And Layered Architecture in SF2 ApplicationRich Model And Layered Architecture in SF2 Application
Rich Model And Layered Architecture in SF2 ApplicationKirill Chebunin
 
Scaling Symfony2 apps with RabbitMQ - Symfony UK Meetup
Scaling Symfony2 apps with RabbitMQ - Symfony UK MeetupScaling Symfony2 apps with RabbitMQ - Symfony UK Meetup
Scaling Symfony2 apps with RabbitMQ - Symfony UK MeetupKacper Gunia
 
Design how your objects talk through mocking
Design how your objects talk through mockingDesign how your objects talk through mocking
Design how your objects talk through mockingKonstantin Kudryashov
 
Models and Service Layers, Hemoglobin and Hobgoblins
Models and Service Layers, Hemoglobin and HobgoblinsModels and Service Layers, Hemoglobin and Hobgoblins
Models and Service Layers, Hemoglobin and HobgoblinsRoss Tuck
 
Design Patterns avec PHP 5.3, Symfony et Pimple
Design Patterns avec PHP 5.3, Symfony et PimpleDesign Patterns avec PHP 5.3, Symfony et Pimple
Design Patterns avec PHP 5.3, Symfony et PimpleHugo Hamon
 
Min-Maxing Software Costs - Laracon EU 2015
Min-Maxing Software Costs - Laracon EU 2015Min-Maxing Software Costs - Laracon EU 2015
Min-Maxing Software Costs - Laracon EU 2015Konstantin Kudryashov
 
Dependency Injection in PHP
Dependency Injection in PHPDependency Injection in PHP
Dependency Injection in PHPKacper Gunia
 
Decoupling the Ulabox.com monolith. From CRUD to DDD
Decoupling the Ulabox.com monolith. From CRUD to DDDDecoupling the Ulabox.com monolith. From CRUD to DDD
Decoupling the Ulabox.com monolith. From CRUD to DDDAleix Vergés
 
When cqrs meets event sourcing
When cqrs meets event sourcingWhen cqrs meets event sourcing
When cqrs meets event sourcingManel Sellés
 
PHPCon 2016: PHP7 by Witek Adamus / XSolve
PHPCon 2016: PHP7 by Witek Adamus / XSolvePHPCon 2016: PHP7 by Witek Adamus / XSolve
PHPCon 2016: PHP7 by Witek Adamus / XSolveXSolve
 
Silex meets SOAP & REST
Silex meets SOAP & RESTSilex meets SOAP & REST
Silex meets SOAP & RESTHugo Hamon
 
Database Design Patterns
Database Design PatternsDatabase Design Patterns
Database Design PatternsHugo Hamon
 
Crafting beautiful software
Crafting beautiful softwareCrafting beautiful software
Crafting beautiful softwareJorn Oomen
 
The History of PHPersistence
The History of PHPersistenceThe History of PHPersistence
The History of PHPersistenceHugo Hamon
 
Command Bus To Awesome Town
Command Bus To Awesome TownCommand Bus To Awesome Town
Command Bus To Awesome TownRoss Tuck
 
Speed up your developments with Symfony2
Speed up your developments with Symfony2Speed up your developments with Symfony2
Speed up your developments with Symfony2Hugo Hamon
 
Doctrine fixtures
Doctrine fixturesDoctrine fixtures
Doctrine fixturesBill Chang
 
Beyond symfony 1.2 (Symfony Camp 2008)
Beyond symfony 1.2 (Symfony Camp 2008)Beyond symfony 1.2 (Symfony Camp 2008)
Beyond symfony 1.2 (Symfony Camp 2008)Fabien Potencier
 

What's hot (20)

Symfony2, creare bundle e valore per il cliente
Symfony2, creare bundle e valore per il clienteSymfony2, creare bundle e valore per il cliente
Symfony2, creare bundle e valore per il cliente
 
Rich Model And Layered Architecture in SF2 Application
Rich Model And Layered Architecture in SF2 ApplicationRich Model And Layered Architecture in SF2 Application
Rich Model And Layered Architecture in SF2 Application
 
Min-Maxing Software Costs
Min-Maxing Software CostsMin-Maxing Software Costs
Min-Maxing Software Costs
 
Scaling Symfony2 apps with RabbitMQ - Symfony UK Meetup
Scaling Symfony2 apps with RabbitMQ - Symfony UK MeetupScaling Symfony2 apps with RabbitMQ - Symfony UK Meetup
Scaling Symfony2 apps with RabbitMQ - Symfony UK Meetup
 
Design how your objects talk through mocking
Design how your objects talk through mockingDesign how your objects talk through mocking
Design how your objects talk through mocking
 
Models and Service Layers, Hemoglobin and Hobgoblins
Models and Service Layers, Hemoglobin and HobgoblinsModels and Service Layers, Hemoglobin and Hobgoblins
Models and Service Layers, Hemoglobin and Hobgoblins
 
Design Patterns avec PHP 5.3, Symfony et Pimple
Design Patterns avec PHP 5.3, Symfony et PimpleDesign Patterns avec PHP 5.3, Symfony et Pimple
Design Patterns avec PHP 5.3, Symfony et Pimple
 
Min-Maxing Software Costs - Laracon EU 2015
Min-Maxing Software Costs - Laracon EU 2015Min-Maxing Software Costs - Laracon EU 2015
Min-Maxing Software Costs - Laracon EU 2015
 
Dependency Injection in PHP
Dependency Injection in PHPDependency Injection in PHP
Dependency Injection in PHP
 
Decoupling the Ulabox.com monolith. From CRUD to DDD
Decoupling the Ulabox.com monolith. From CRUD to DDDDecoupling the Ulabox.com monolith. From CRUD to DDD
Decoupling the Ulabox.com monolith. From CRUD to DDD
 
When cqrs meets event sourcing
When cqrs meets event sourcingWhen cqrs meets event sourcing
When cqrs meets event sourcing
 
PHPCon 2016: PHP7 by Witek Adamus / XSolve
PHPCon 2016: PHP7 by Witek Adamus / XSolvePHPCon 2016: PHP7 by Witek Adamus / XSolve
PHPCon 2016: PHP7 by Witek Adamus / XSolve
 
Silex meets SOAP & REST
Silex meets SOAP & RESTSilex meets SOAP & REST
Silex meets SOAP & REST
 
Database Design Patterns
Database Design PatternsDatabase Design Patterns
Database Design Patterns
 
Crafting beautiful software
Crafting beautiful softwareCrafting beautiful software
Crafting beautiful software
 
The History of PHPersistence
The History of PHPersistenceThe History of PHPersistence
The History of PHPersistence
 
Command Bus To Awesome Town
Command Bus To Awesome TownCommand Bus To Awesome Town
Command Bus To Awesome Town
 
Speed up your developments with Symfony2
Speed up your developments with Symfony2Speed up your developments with Symfony2
Speed up your developments with Symfony2
 
Doctrine fixtures
Doctrine fixturesDoctrine fixtures
Doctrine fixtures
 
Beyond symfony 1.2 (Symfony Camp 2008)
Beyond symfony 1.2 (Symfony Camp 2008)Beyond symfony 1.2 (Symfony Camp 2008)
Beyond symfony 1.2 (Symfony Camp 2008)
 

Viewers also liked

Zephir - A Wind of Change for writing PHP extensions
Zephir - A Wind of Change for writing PHP extensionsZephir - A Wind of Change for writing PHP extensions
Zephir - A Wind of Change for writing PHP extensionsMark Baker
 
Enterprise Architecture Case in PHP (MUZIK Online)
Enterprise Architecture Case in PHP (MUZIK Online)Enterprise Architecture Case in PHP (MUZIK Online)
Enterprise Architecture Case in PHP (MUZIK Online)Yi-Feng Tzeng
 
Hexagonal architecture message-oriented software design
Hexagonal architecture   message-oriented software designHexagonal architecture   message-oriented software design
Hexagonal architecture message-oriented software designMatthias Noback
 
Holistic approach to machine learning
Holistic approach to machine learningHolistic approach to machine learning
Holistic approach to machine learningSource Ministry
 
Machine learning for developers
Machine learning for developersMachine learning for developers
Machine learning for developersSource Ministry
 
The top 10 things that any pro PHP developer should be doing
The top 10 things that any pro PHP developer should be doingThe top 10 things that any pro PHP developer should be doing
The top 10 things that any pro PHP developer should be doingKacper Gunia
 
Embrace Events and let CRUD die
Embrace Events and let CRUD dieEmbrace Events and let CRUD die
Embrace Events and let CRUD dieKacper Gunia
 
Service discovery and configuration provisioning
Service discovery and configuration provisioningService discovery and configuration provisioning
Service discovery and configuration provisioningSource Ministry
 
PHP7 - Scalar Type Hints & Return Types
PHP7 - Scalar Type Hints & Return TypesPHP7 - Scalar Type Hints & Return Types
PHP7 - Scalar Type Hints & Return TypesEric Poe
 
Kreishäuser in Siegen
Kreishäuser in SiegenKreishäuser in Siegen
Kreishäuser in Siegensiwiarchiv
 
Ba z cityformu
Ba z cityformuBa z cityformu
Ba z cityformufroloo
 
Hiperion Digital Microwave Radio Presentation
Hiperion Digital Microwave Radio PresentationHiperion Digital Microwave Radio Presentation
Hiperion Digital Microwave Radio PresentationBarry Rule
 
Reflexiones junto a la fuente taza, finales de octubre 2013
Reflexiones junto a la fuente taza, finales de octubre 2013Reflexiones junto a la fuente taza, finales de octubre 2013
Reflexiones junto a la fuente taza, finales de octubre 2013gamiruela
 
Jayakar, pupul krishnamurti. biografía
Jayakar, pupul   krishnamurti. biografíaJayakar, pupul   krishnamurti. biografía
Jayakar, pupul krishnamurti. biografíasergi75
 
Enhancing the gas barrier properties of polylactic acid by means of electrosp...
Enhancing the gas barrier properties of polylactic acid by means of electrosp...Enhancing the gas barrier properties of polylactic acid by means of electrosp...
Enhancing the gas barrier properties of polylactic acid by means of electrosp...Sergio Torres-Giner
 
Mi vce 2000 ss & vce-2200 ss - Servicio Tecnico Fagor
Mi vce 2000 ss & vce-2200 ss - Servicio Tecnico FagorMi vce 2000 ss & vce-2200 ss - Servicio Tecnico Fagor
Mi vce 2000 ss & vce-2200 ss - Servicio Tecnico Fagorserviciotecnicofagor
 

Viewers also liked (20)

Zephir - A Wind of Change for writing PHP extensions
Zephir - A Wind of Change for writing PHP extensionsZephir - A Wind of Change for writing PHP extensions
Zephir - A Wind of Change for writing PHP extensions
 
Enterprise Architecture Case in PHP (MUZIK Online)
Enterprise Architecture Case in PHP (MUZIK Online)Enterprise Architecture Case in PHP (MUZIK Online)
Enterprise Architecture Case in PHP (MUZIK Online)
 
Hexagonal architecture message-oriented software design
Hexagonal architecture   message-oriented software designHexagonal architecture   message-oriented software design
Hexagonal architecture message-oriented software design
 
Holistic approach to machine learning
Holistic approach to machine learningHolistic approach to machine learning
Holistic approach to machine learning
 
Machine learning for developers
Machine learning for developersMachine learning for developers
Machine learning for developers
 
MySQL under the siege
MySQL under the siegeMySQL under the siege
MySQL under the siege
 
The top 10 things that any pro PHP developer should be doing
The top 10 things that any pro PHP developer should be doingThe top 10 things that any pro PHP developer should be doing
The top 10 things that any pro PHP developer should be doing
 
Embrace Events and let CRUD die
Embrace Events and let CRUD dieEmbrace Events and let CRUD die
Embrace Events and let CRUD die
 
Time series databases
Time series databasesTime series databases
Time series databases
 
Service discovery and configuration provisioning
Service discovery and configuration provisioningService discovery and configuration provisioning
Service discovery and configuration provisioning
 
Php extensions
Php extensionsPhp extensions
Php extensions
 
PHP7 - Scalar Type Hints & Return Types
PHP7 - Scalar Type Hints & Return TypesPHP7 - Scalar Type Hints & Return Types
PHP7 - Scalar Type Hints & Return Types
 
Kreishäuser in Siegen
Kreishäuser in SiegenKreishäuser in Siegen
Kreishäuser in Siegen
 
Ba z cityformu
Ba z cityformuBa z cityformu
Ba z cityformu
 
Hiperion Digital Microwave Radio Presentation
Hiperion Digital Microwave Radio PresentationHiperion Digital Microwave Radio Presentation
Hiperion Digital Microwave Radio Presentation
 
Reflexiones junto a la fuente taza, finales de octubre 2013
Reflexiones junto a la fuente taza, finales de octubre 2013Reflexiones junto a la fuente taza, finales de octubre 2013
Reflexiones junto a la fuente taza, finales de octubre 2013
 
Jayakar, pupul krishnamurti. biografía
Jayakar, pupul   krishnamurti. biografíaJayakar, pupul   krishnamurti. biografía
Jayakar, pupul krishnamurti. biografía
 
Enhancing the gas barrier properties of polylactic acid by means of electrosp...
Enhancing the gas barrier properties of polylactic acid by means of electrosp...Enhancing the gas barrier properties of polylactic acid by means of electrosp...
Enhancing the gas barrier properties of polylactic acid by means of electrosp...
 
Mi vce 2000 ss & vce-2200 ss - Servicio Tecnico Fagor
Mi vce 2000 ss & vce-2200 ss - Servicio Tecnico FagorMi vce 2000 ss & vce-2200 ss - Servicio Tecnico Fagor
Mi vce 2000 ss & vce-2200 ss - Servicio Tecnico Fagor
 
edificios futuristas famosos
edificios futuristas famososedificios futuristas famosos
edificios futuristas famosos
 

Similar to The IoC Hydra

Symfony2 from the Trenches
Symfony2 from the TrenchesSymfony2 from the Trenches
Symfony2 from the TrenchesJonathan Wage
 
Singletons in PHP - Why they are bad and how you can eliminate them from your...
Singletons in PHP - Why they are bad and how you can eliminate them from your...Singletons in PHP - Why they are bad and how you can eliminate them from your...
Singletons in PHP - Why they are bad and how you can eliminate them from your...go_oh
 
Symfony2 - from the trenches
Symfony2 - from the trenchesSymfony2 - from the trenches
Symfony2 - from the trenchesLukas Smith
 
Dependency injection in Drupal 8
Dependency injection in Drupal 8Dependency injection in Drupal 8
Dependency injection in Drupal 8Alexei Gorobets
 
PHP: 4 Design Patterns to Make Better Code
PHP: 4 Design Patterns to Make Better CodePHP: 4 Design Patterns to Make Better Code
PHP: 4 Design Patterns to Make Better CodeSWIFTotter Solutions
 
Doctrine For Beginners
Doctrine For BeginnersDoctrine For Beginners
Doctrine For BeginnersJonathan Wage
 
Inversion Of Control
Inversion Of ControlInversion Of Control
Inversion Of ControlChad Hietala
 
Modularity and Layered Data Model
Modularity and Layered Data ModelModularity and Layered Data Model
Modularity and Layered Data ModelAttila Jenei
 
How Kris Writes Symfony Apps
How Kris Writes Symfony AppsHow Kris Writes Symfony Apps
How Kris Writes Symfony AppsKris Wallsmith
 
Phpne august-2012-symfony-components-friends
Phpne august-2012-symfony-components-friendsPhpne august-2012-symfony-components-friends
Phpne august-2012-symfony-components-friendsMichael Peacock
 
Domain Driven Design using Laravel
Domain Driven Design using LaravelDomain Driven Design using Laravel
Domain Driven Design using Laravelwajrcs
 
Decouple Your Code For Reusability (International PHP Conference / IPC 2008)
Decouple Your Code For Reusability (International PHP Conference / IPC 2008)Decouple Your Code For Reusability (International PHP Conference / IPC 2008)
Decouple Your Code For Reusability (International PHP Conference / IPC 2008)Fabien Potencier
 
ZF2 for the ZF1 Developer
ZF2 for the ZF1 DeveloperZF2 for the ZF1 Developer
ZF2 for the ZF1 DeveloperGary Hockin
 
What's New In Laravel 5
What's New In Laravel 5What's New In Laravel 5
What's New In Laravel 5Darren Craig
 
ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 2, Dependency I...
ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 2, Dependency I...ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 2, Dependency I...
ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 2, Dependency I...ZFConf Conference
 
Lithium: The Framework for People Who Hate Frameworks
Lithium: The Framework for People Who Hate FrameworksLithium: The Framework for People Who Hate Frameworks
Lithium: The Framework for People Who Hate FrameworksNate Abele
 
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 Symfony2Hugo Hamon
 
Symfony components in the wild, PHPNW12
Symfony components in the wild, PHPNW12Symfony components in the wild, PHPNW12
Symfony components in the wild, PHPNW12Jakub Zalas
 
Symfony War Stories
Symfony War StoriesSymfony War Stories
Symfony War StoriesJakub Zalas
 

Similar to The IoC Hydra (20)

Symfony2 from the Trenches
Symfony2 from the TrenchesSymfony2 from the Trenches
Symfony2 from the Trenches
 
Singletons in PHP - Why they are bad and how you can eliminate them from your...
Singletons in PHP - Why they are bad and how you can eliminate them from your...Singletons in PHP - Why they are bad and how you can eliminate them from your...
Singletons in PHP - Why they are bad and how you can eliminate them from your...
 
Symfony2 - from the trenches
Symfony2 - from the trenchesSymfony2 - from the trenches
Symfony2 - from the trenches
 
Dependency injection in Drupal 8
Dependency injection in Drupal 8Dependency injection in Drupal 8
Dependency injection in Drupal 8
 
PHP: 4 Design Patterns to Make Better Code
PHP: 4 Design Patterns to Make Better CodePHP: 4 Design Patterns to Make Better Code
PHP: 4 Design Patterns to Make Better Code
 
Doctrine For Beginners
Doctrine For BeginnersDoctrine For Beginners
Doctrine For Beginners
 
Inversion Of Control
Inversion Of ControlInversion Of Control
Inversion Of Control
 
Modularity and Layered Data Model
Modularity and Layered Data ModelModularity and Layered Data Model
Modularity and Layered Data Model
 
How Kris Writes Symfony Apps
How Kris Writes Symfony AppsHow Kris Writes Symfony Apps
How Kris Writes Symfony Apps
 
Phpne august-2012-symfony-components-friends
Phpne august-2012-symfony-components-friendsPhpne august-2012-symfony-components-friends
Phpne august-2012-symfony-components-friends
 
Domain Driven Design using Laravel
Domain Driven Design using LaravelDomain Driven Design using Laravel
Domain Driven Design using Laravel
 
Decouple Your Code For Reusability (International PHP Conference / IPC 2008)
Decouple Your Code For Reusability (International PHP Conference / IPC 2008)Decouple Your Code For Reusability (International PHP Conference / IPC 2008)
Decouple Your Code For Reusability (International PHP Conference / IPC 2008)
 
ZF2 for the ZF1 Developer
ZF2 for the ZF1 DeveloperZF2 for the ZF1 Developer
ZF2 for the ZF1 Developer
 
Dependency Injection
Dependency InjectionDependency Injection
Dependency Injection
 
What's New In Laravel 5
What's New In Laravel 5What's New In Laravel 5
What's New In Laravel 5
 
ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 2, Dependency I...
ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 2, Dependency I...ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 2, Dependency I...
ZFConf 2010: Zend Framework & MVC, Model Implementation (Part 2, Dependency I...
 
Lithium: The Framework for People Who Hate Frameworks
Lithium: The Framework for People Who Hate FrameworksLithium: The Framework for People Who Hate Frameworks
Lithium: The Framework for People Who Hate Frameworks
 
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
 
Symfony components in the wild, PHPNW12
Symfony components in the wild, PHPNW12Symfony components in the wild, PHPNW12
Symfony components in the wild, PHPNW12
 
Symfony War Stories
Symfony War StoriesSymfony War Stories
Symfony War Stories
 

More from Kacper Gunia

How a large corporation used Domain-Driven Design to replace a loyalty system
How a large corporation used Domain-Driven Design to replace a loyalty systemHow a large corporation used Domain-Driven Design to replace a loyalty system
How a large corporation used Domain-Driven Design to replace a loyalty systemKacper Gunia
 
Rebuilding Legacy Apps with Domain-Driven Design - Lessons learned
Rebuilding Legacy Apps with Domain-Driven Design - Lessons learnedRebuilding Legacy Apps with Domain-Driven Design - Lessons learned
Rebuilding Legacy Apps with Domain-Driven Design - Lessons learnedKacper Gunia
 
Domain-driven Design in PHP and Symfony - Drupal Camp Wroclaw!
Domain-driven Design in PHP and Symfony - Drupal Camp Wroclaw!Domain-driven Design in PHP and Symfony - Drupal Camp Wroclaw!
Domain-driven Design in PHP and Symfony - Drupal Camp Wroclaw!Kacper Gunia
 
OmniFocus - the #1 ‘Getting Things Done’ tool
OmniFocus - the #1 ‘Getting Things Done’ toolOmniFocus - the #1 ‘Getting Things Done’ tool
OmniFocus - the #1 ‘Getting Things Done’ toolKacper Gunia
 

More from Kacper Gunia (6)

How a large corporation used Domain-Driven Design to replace a loyalty system
How a large corporation used Domain-Driven Design to replace a loyalty systemHow a large corporation used Domain-Driven Design to replace a loyalty system
How a large corporation used Domain-Driven Design to replace a loyalty system
 
Rebuilding Legacy Apps with Domain-Driven Design - Lessons learned
Rebuilding Legacy Apps with Domain-Driven Design - Lessons learnedRebuilding Legacy Apps with Domain-Driven Design - Lessons learned
Rebuilding Legacy Apps with Domain-Driven Design - Lessons learned
 
Domain-driven Design in PHP and Symfony - Drupal Camp Wroclaw!
Domain-driven Design in PHP and Symfony - Drupal Camp Wroclaw!Domain-driven Design in PHP and Symfony - Drupal Camp Wroclaw!
Domain-driven Design in PHP and Symfony - Drupal Camp Wroclaw!
 
OmniFocus - the #1 ‘Getting Things Done’ tool
OmniFocus - the #1 ‘Getting Things Done’ toolOmniFocus - the #1 ‘Getting Things Done’ tool
OmniFocus - the #1 ‘Getting Things Done’ tool
 
Code Dojo
Code DojoCode Dojo
Code Dojo
 
SpecBDD in PHP
SpecBDD in PHPSpecBDD in PHP
SpecBDD in PHP
 

Recently uploaded

Immutable Image-Based Operating Systems - EW2024.pdf
Immutable Image-Based Operating Systems - EW2024.pdfImmutable Image-Based Operating Systems - EW2024.pdf
Immutable Image-Based Operating Systems - EW2024.pdfDrew Moseley
 
Robotics Group 10 (Control Schemes) cse.pdf
Robotics Group 10  (Control Schemes) cse.pdfRobotics Group 10  (Control Schemes) cse.pdf
Robotics Group 10 (Control Schemes) cse.pdfsahilsajad201
 
Turn leadership mistakes into a better future.pptx
Turn leadership mistakes into a better future.pptxTurn leadership mistakes into a better future.pptx
Turn leadership mistakes into a better future.pptxStephen Sitton
 
『澳洲文凭』买麦考瑞大学毕业证书成绩单办理澳洲Macquarie文凭学位证书
『澳洲文凭』买麦考瑞大学毕业证书成绩单办理澳洲Macquarie文凭学位证书『澳洲文凭』买麦考瑞大学毕业证书成绩单办理澳洲Macquarie文凭学位证书
『澳洲文凭』买麦考瑞大学毕业证书成绩单办理澳洲Macquarie文凭学位证书rnrncn29
 
multiple access in wireless communication
multiple access in wireless communicationmultiple access in wireless communication
multiple access in wireless communicationpanditadesh123
 
Earthing details of Electrical Substation
Earthing details of Electrical SubstationEarthing details of Electrical Substation
Earthing details of Electrical Substationstephanwindworld
 
Comprehensive energy systems.pdf Comprehensive energy systems.pdf
Comprehensive energy systems.pdf Comprehensive energy systems.pdfComprehensive energy systems.pdf Comprehensive energy systems.pdf
Comprehensive energy systems.pdf Comprehensive energy systems.pdfalene1
 
Katarzyna Lipka-Sidor - BIM School Course
Katarzyna Lipka-Sidor - BIM School CourseKatarzyna Lipka-Sidor - BIM School Course
Katarzyna Lipka-Sidor - BIM School Coursebim.edu.pl
 
SOFTWARE ESTIMATION COCOMO AND FP CALCULATION
SOFTWARE ESTIMATION COCOMO AND FP CALCULATIONSOFTWARE ESTIMATION COCOMO AND FP CALCULATION
SOFTWARE ESTIMATION COCOMO AND FP CALCULATIONSneha Padhiar
 
Computer Graphics Introduction, Open GL, Line and Circle drawing algorithm
Computer Graphics Introduction, Open GL, Line and Circle drawing algorithmComputer Graphics Introduction, Open GL, Line and Circle drawing algorithm
Computer Graphics Introduction, Open GL, Line and Circle drawing algorithmDeepika Walanjkar
 
Virtual memory management in Operating System
Virtual memory management in Operating SystemVirtual memory management in Operating System
Virtual memory management in Operating SystemRashmi Bhat
 
High Voltage Engineering- OVER VOLTAGES IN ELECTRICAL POWER SYSTEMS
High Voltage Engineering- OVER VOLTAGES IN ELECTRICAL POWER SYSTEMSHigh Voltage Engineering- OVER VOLTAGES IN ELECTRICAL POWER SYSTEMS
High Voltage Engineering- OVER VOLTAGES IN ELECTRICAL POWER SYSTEMSsandhya757531
 
signals in triangulation .. ...Surveying
signals in triangulation .. ...Surveyingsignals in triangulation .. ...Surveying
signals in triangulation .. ...Surveyingsapna80328
 
Robotics-Asimov's Laws, Mechanical Subsystems, Robot Kinematics, Robot Dynami...
Robotics-Asimov's Laws, Mechanical Subsystems, Robot Kinematics, Robot Dynami...Robotics-Asimov's Laws, Mechanical Subsystems, Robot Kinematics, Robot Dynami...
Robotics-Asimov's Laws, Mechanical Subsystems, Robot Kinematics, Robot Dynami...Sumanth A
 
OOP concepts -in-Python programming language
OOP concepts -in-Python programming languageOOP concepts -in-Python programming language
OOP concepts -in-Python programming languageSmritiSharma901052
 
Module-1-(Building Acoustics) Noise Control (Unit-3). pdf
Module-1-(Building Acoustics) Noise Control (Unit-3). pdfModule-1-(Building Acoustics) Noise Control (Unit-3). pdf
Module-1-(Building Acoustics) Noise Control (Unit-3). pdfManish Kumar
 
FUNCTIONAL AND NON FUNCTIONAL REQUIREMENT
FUNCTIONAL AND NON FUNCTIONAL REQUIREMENTFUNCTIONAL AND NON FUNCTIONAL REQUIREMENT
FUNCTIONAL AND NON FUNCTIONAL REQUIREMENTSneha Padhiar
 
Energy Awareness training ppt for manufacturing process.pptx
Energy Awareness training ppt for manufacturing process.pptxEnergy Awareness training ppt for manufacturing process.pptx
Energy Awareness training ppt for manufacturing process.pptxsiddharthjain2303
 
Ch10-Global Supply Chain - Cadena de Suministro.pdf
Ch10-Global Supply Chain - Cadena de Suministro.pdfCh10-Global Supply Chain - Cadena de Suministro.pdf
Ch10-Global Supply Chain - Cadena de Suministro.pdfChristianCDAM
 

Recently uploaded (20)

Immutable Image-Based Operating Systems - EW2024.pdf
Immutable Image-Based Operating Systems - EW2024.pdfImmutable Image-Based Operating Systems - EW2024.pdf
Immutable Image-Based Operating Systems - EW2024.pdf
 
Designing pile caps according to ACI 318-19.pptx
Designing pile caps according to ACI 318-19.pptxDesigning pile caps according to ACI 318-19.pptx
Designing pile caps according to ACI 318-19.pptx
 
Robotics Group 10 (Control Schemes) cse.pdf
Robotics Group 10  (Control Schemes) cse.pdfRobotics Group 10  (Control Schemes) cse.pdf
Robotics Group 10 (Control Schemes) cse.pdf
 
Turn leadership mistakes into a better future.pptx
Turn leadership mistakes into a better future.pptxTurn leadership mistakes into a better future.pptx
Turn leadership mistakes into a better future.pptx
 
『澳洲文凭』买麦考瑞大学毕业证书成绩单办理澳洲Macquarie文凭学位证书
『澳洲文凭』买麦考瑞大学毕业证书成绩单办理澳洲Macquarie文凭学位证书『澳洲文凭』买麦考瑞大学毕业证书成绩单办理澳洲Macquarie文凭学位证书
『澳洲文凭』买麦考瑞大学毕业证书成绩单办理澳洲Macquarie文凭学位证书
 
multiple access in wireless communication
multiple access in wireless communicationmultiple access in wireless communication
multiple access in wireless communication
 
Earthing details of Electrical Substation
Earthing details of Electrical SubstationEarthing details of Electrical Substation
Earthing details of Electrical Substation
 
Comprehensive energy systems.pdf Comprehensive energy systems.pdf
Comprehensive energy systems.pdf Comprehensive energy systems.pdfComprehensive energy systems.pdf Comprehensive energy systems.pdf
Comprehensive energy systems.pdf Comprehensive energy systems.pdf
 
Katarzyna Lipka-Sidor - BIM School Course
Katarzyna Lipka-Sidor - BIM School CourseKatarzyna Lipka-Sidor - BIM School Course
Katarzyna Lipka-Sidor - BIM School Course
 
SOFTWARE ESTIMATION COCOMO AND FP CALCULATION
SOFTWARE ESTIMATION COCOMO AND FP CALCULATIONSOFTWARE ESTIMATION COCOMO AND FP CALCULATION
SOFTWARE ESTIMATION COCOMO AND FP CALCULATION
 
Computer Graphics Introduction, Open GL, Line and Circle drawing algorithm
Computer Graphics Introduction, Open GL, Line and Circle drawing algorithmComputer Graphics Introduction, Open GL, Line and Circle drawing algorithm
Computer Graphics Introduction, Open GL, Line and Circle drawing algorithm
 
Virtual memory management in Operating System
Virtual memory management in Operating SystemVirtual memory management in Operating System
Virtual memory management in Operating System
 
High Voltage Engineering- OVER VOLTAGES IN ELECTRICAL POWER SYSTEMS
High Voltage Engineering- OVER VOLTAGES IN ELECTRICAL POWER SYSTEMSHigh Voltage Engineering- OVER VOLTAGES IN ELECTRICAL POWER SYSTEMS
High Voltage Engineering- OVER VOLTAGES IN ELECTRICAL POWER SYSTEMS
 
signals in triangulation .. ...Surveying
signals in triangulation .. ...Surveyingsignals in triangulation .. ...Surveying
signals in triangulation .. ...Surveying
 
Robotics-Asimov's Laws, Mechanical Subsystems, Robot Kinematics, Robot Dynami...
Robotics-Asimov's Laws, Mechanical Subsystems, Robot Kinematics, Robot Dynami...Robotics-Asimov's Laws, Mechanical Subsystems, Robot Kinematics, Robot Dynami...
Robotics-Asimov's Laws, Mechanical Subsystems, Robot Kinematics, Robot Dynami...
 
OOP concepts -in-Python programming language
OOP concepts -in-Python programming languageOOP concepts -in-Python programming language
OOP concepts -in-Python programming language
 
Module-1-(Building Acoustics) Noise Control (Unit-3). pdf
Module-1-(Building Acoustics) Noise Control (Unit-3). pdfModule-1-(Building Acoustics) Noise Control (Unit-3). pdf
Module-1-(Building Acoustics) Noise Control (Unit-3). pdf
 
FUNCTIONAL AND NON FUNCTIONAL REQUIREMENT
FUNCTIONAL AND NON FUNCTIONAL REQUIREMENTFUNCTIONAL AND NON FUNCTIONAL REQUIREMENT
FUNCTIONAL AND NON FUNCTIONAL REQUIREMENT
 
Energy Awareness training ppt for manufacturing process.pptx
Energy Awareness training ppt for manufacturing process.pptxEnergy Awareness training ppt for manufacturing process.pptx
Energy Awareness training ppt for manufacturing process.pptx
 
Ch10-Global Supply Chain - Cadena de Suministro.pdf
Ch10-Global Supply Chain - Cadena de Suministro.pdfCh10-Global Supply Chain - Cadena de Suministro.pdf
Ch10-Global Supply Chain - Cadena de Suministro.pdf
 

The IoC Hydra

  • 2. Kacper Gunia @cakper Technical Team Leader @SensioLabsUK Symfony Certified Developer PHPers Silesia @PHPersPL
  • 3. CHAPTER 1: THE THEORY
  • 4. THIS IS NOT YET ANOTHER DEPENDENCY INJECTION TALK ;)
  • 5. SO WE NEED SOME CLARIFICATION
  • 7. –Pico Container “Inversion of Control (IoC) is a design pattern that addresses a component’s dependency resolution, configuration and lifecycle. ”
  • 8. –Pico Container “It suggests that the control of those three should not be the concern of the component itself. Thus it is inverted back.”
  • 9. –Pico Container “Dependency Injection is where components are given their dependencies through their constructors, methods, or directly into fields.”
  • 11. WHY DO WE IOC?
  • 12. PROS • Separation of concerns: • dependency resolution, configuration and lifecycle • Enforcing Single Responsibility Principle • Easier testing • Modular architecture, loose coupling
  • 13. CONS • Learning curve • Code is harder do analyse/debug • Moves complexity somewhere else (doesn’t remove) • Need for extra tools like Containers / Dispatchers
  • 14. HOW DO WE WRITE SOFTWARE WITHOUT IOC?
  • 16. EXAMPLE interface Logger
 {
 public function log($log);
 }
 
 class PrintingLogger implements Logger
 {
 public function log($log)
 {
 echo $log;
 }
 }
  • 17. EXAMPLE class LocalFileEraser implements FileEraser
 {
 public function erase($filename) {
 $logger = new PrintingLogger();
 $logger->log("Attempt to erase file: " . $filename);
 
 unlink($filename);
 
 $logger->log("File " . $filename . " was erased.”);
 }
 }
  • 18. EXAMPLE $eraser = new LocalFileEraser();
 $eraser->erase('important-passwords.txt');
  • 19. HOW CAN WE FIX IT WITH DI?
  • 20. EXAMPLE WITH DI class LocalFileEraser implements FileEraser {
 private $logger;
 
 public function __construct(Logger $logger) {
 $this->logger = $logger;
 }
 
 public function erase($path) {
 $this->logger->log("Attempt to erase file: " . $path); 
 unlink($path); 
 $this->logger->log("File " . $path . " was erased.");
 }
 }
  • 21. EXAMPLE WITH DI $logger = new PrintingLogger();
 $eraser = new LocalFileEraser($logger);
 
 $eraser->erase('important-passwords.txt');
  • 22. What (is being executed) Known Unknown KnownUnknown When(isbeingexecuted) Dependency Injection Stages of loosening control (from the component point of view)
  • 23. HOW CAN WE FIX IT WITH EVENTS?
  • 24. EXAMPLE WITH EVENTS interface Listener
 {
 public function handle(Event $event);
 }
 
 interface Event
 {
 
 }
  • 25. EXAMPLE WITH EVENTS class FileEvent implements Event
 {
 private $path;
 public function __construct($path)
 {
 $this->path = $path;
 }
 
 public function getPath()
 {
 return $this->path;
 }
 }
  • 26. EXAMPLE WITH EVENTS class FileEraseWasInitialised extends FileEvent
 {
 
 }
 
 class FileWasErased extends FileEvent
 {
 
 }
  • 27. EXAMPLE WITH EVENTS class LoggingFileEventListener implements Listener
 {
 private $logger;
 
 public function __construct(Logger $logger)
 {
 $this->logger = $logger;
 }
 
 public function handle(Event $event)
 {
 if ($event instanceof FileEvent) {
 $this->logger->log(get_class($event).' '.$event->getPath());
 }
 }
 }
  • 28. EXAMPLE WITH EVENTS trait Observable
 {
 private $listeners = [];
 
 public function addListener(Listener $listener)
 {
 $this->listeners[] = $listener;
 }
 
 public function dispatch(Event $event)
 {
 foreach ($this->listeners as $listener) {
 $listener->handle($event);
 }
 }
 }
  • 29. EXAMPLE WITH EVENTS class LocalFileEraser implements FileEraser
 {
 use Observable;
 
 public function erase($filename)
 {
 $this->dispatch(new FileEraseWasInitialised($filename));
 
 unlink($filename);
 
 $this->dispatch(new FileWasErased($filename));
 }
 }
  • 30. EXAMPLE WITH EVENTS $eraser = new LocalFileEraser();
 $listener = new LoggingFileEventListener(new PrintingLogger()); $eraser->addListener($listener);
 
 $eraser->erase('important-passwords.txt');
  • 31. What (is being executed) Known Unknown KnownUnknown When(isbeingexecuted) Events Stages of loosening control (from the component point of view)
  • 32. HOW CAN WE FIX IT WITH AOP?
  • 33. EXAMPLE WITH AOP USING DECORATOR class LocalFileEraser implements FileEraser
 {
 public function erase($filename)
 {
 unlink($filename);
 }
 }
  • 34. EXAMPLE WITH AOP USING DECORATOR class LoggingFileEraser implements FileEraser
 {
 private $decorated;
 
 private $logger;
 
 public function __construct(FileEraser $decorated, Logger $logger)
 {
 $this->decorated = $decorated;
 $this->logger = $logger;
 }
 
 public function erase($filename)
 {
 $this->logger->log('File erase was initialised' . $filename);
 
 $this->decorated->erase($filename);
 
 $this->logger->log('File was erased' . $filename);
 }
 }
  • 35. EXAMPLE WITH AOP USING DECORATOR $localFileEraser = new LocalFileEraser();
 $logger = new PrintingLogger();
 
 $eraser = new LoggingFileEraser($localFileEraser, $logger);
 
 $eraser->erase('important-passwords.txt');
  • 36. What (is being executed) Known Unknown KnownUnknown When(isbeingexecuted) AOP Stages of loosening control (from the component point of view)
  • 37. What (is being executed) Known Unknown KnownUnknown When(isbeingexecuted) Dependency Injection Events AOP Stages of loosening control (from the component point of view)
  • 39. A libraries provide functionality that you decide when to call.
  • 40. Frameworks provide an architecture for the application and decide when to call your code.
  • 41. “DON’T CALL US, WE’LL CALL YOU” aka Hollywood Principle
  • 42. Frameworks utilise IoC principles and can be seen as one of its manifestations.
  • 43. CHAPTER 2: THE PRACTICE
  • 46. RESOLVING GRAPHS OF OBJECTS $dsn = 'mysql:host=localhost;dbname=testdb;charset=utf8';
 $dbUsername = 'username';
 $dbPassword = 'password';
 $customerRepository = new CustomerRepository(new PDO($dsn, $dbUsername, $dbPassword));
 
 $smtpHost = 'smtp.example.org';
 $smtpPort = 25;
 $smtpUsername = 'username';
 $smtpPassword = 'password';
 $transport = new Swift_SmtpTransport($smtpHost, $smtpPort);
 $transport->setUsername($smtpUsername);
 $transport->setPassword($smtpPassword);
 $mailer = new Swift_Mailer($transport);
 
 $loggerName = "App";
 $logger = new MonologLogger($loggerName);
 $stream = "app.log";
 $logger->pushHandler(new MonologHandlerStreamHandler($stream));
 
 $controller = new RegistrationController($customerRepository, $mailer, $logger);
  • 47. RESOLVING GRAPHS OF OBJECTS use PimpleContainer;
 
 $container = new Container();
 
 $container['dsn'] = 'mysql:host=localhost;dbname=testdb;charset=utf8';
 $container['db_username'] = 'username';
 $container['dsn'] = 'password';
 
 $container['pdo'] = function ($c) {
 return new PDO($c['dsn'], $c['db_username'], $c['dsn']);
 }; 
 $container['customer_repository'] = function ($c) {
 return new CustomerRepository($c['pdo']);
 };
  • 48. RESOLVING GRAPHS OF OBJECTS $container['smtp_host'] = 'smtp.example.org';
 $container['smtp_port'] = 25;
 $container['smtp_username'] = 'username';
 $container['smtp_password'] = 'password';
 
 $container['transport'] = function ($c) {
 return new Swift_SmtpTransport($c['smtp_host'], $c['smtp_port']);
 };
 
 $container->extend('transport', function ($transport, $c) {
 $transport->setUsername($c['smtp_username']);
 $transport->setPassword($c['smtp_password']);
 
 return $transport;
 });
 
 $container['mailer'] = function ($c) {
 return new Swift_Mailer($c['transport']);
 };
  • 49. RESOLVING GRAPHS OF OBJECTS $container['logger_name'] = "App";
 $container['stream_name'] = "app_" . $container['environment'] . ".log";
 
 $container['logger'] = function ($c) {
 return new MonologLogger($c['logger_name']);
 };
 
 $container->extend('transport', function ($logger, $c) {
 $logger->pushHandler( new MonologHandlerStreamHandler($c[‘stream_handler']) );
 
 return $logger;
 });
 
 $container['stream_handler'] = function ($c) {
 return new MonologHandlerStreamHandler($c['stream_name']);
 };
  • 50. RESOLVING GRAPHS OF OBJECTS $container['registration_controller'] = function ($c) {
 return new RegistrationController( $c['customer_repository'], $c['mailer'], $c[‘logger’] );
 };
  • 51. LIFECYCLE MANAGEMENT $container['session_storage'] = function ($c) {
 return new SessionStorage('SESSION_ID');
 };
  • 52. LIFECYCLE MANAGEMENT $container['session_storage'] = $container->factory(function ($c) {
 return new SessionStorage('SESSION_ID');
 });
  • 54. SERVICE LOCATOR class RegistrationController {
 function resetPasswordAction() {
 $mailer = Container::instance()['mailer'];
 //...
 }
 }
  • 55. SERVICE LOCATOR • Coupled to container • Responsible for resolving dependencies • Dependencies are hidden • Hard to test • Might be ok when modernising legacy!
  • 57. SETTER INJECTION • Forces to be defensive as dependencies are optional • Dependency is not locked (mutable) • In some cases can be replaced with events • We can avoid it by using NullObject pattern
  • 58. SETTER INJECTION class LocalFileEraser implements FileEraser
 {
 private $logger;
 
 public function setLogger(Logger $logger)
 {
 $this->logger = $logger;
 }
 
 public function erase($filename)
 {
 if ($this->logger instanceof Logger) {
 $this->logger->log("Attempt to erase file: " . $filename);
 }
 
 unlink($filename);
 
 if ($this->logger instanceof Logger) {
 $this->logger->log("File " . $filename . " was deleted");
 }
 }
 }
  • 59. SETTER INJECTION class LocalFileEraser implements FileEraser
 {
 private $logger;
 
 public function __construct(Logger $logger)
 {
 $this->logger = $logger;
 }
 
 public function erase($path)
 {
 $this->logger->log("Attempt to erase file: " . $path);
 
 unlink($path);
 
 $this->logger->log("File " . $path . " was erased.”);
 }
 }
  • 60. SETTER INJECTION class NullLogger implements Logger {
 
 public function log($log)
 {
 // whateva...
 }
 }
 
 $eraser = new LocalFileEraser(new NullLogger());
 $eraser->erase('important-passwords.txt');
  • 62. DI WAY OF DOING THINGS interface Logger
 {
 public function log($log);
 }
 
 class PrintingLogger implements Logger
 {
 public function log($log)
 {
 echo $log;
 }
 }
  • 63. DI WAY OF DOING THINGS class LocalFileEraser implements FileEraser
 {
 private $logger;
 
 public function __construct(Logger $logger)
 {
 $this->logger = $logger;
 }
 
 public function erase($path)
 {
 $this->logger->log("Attempt to erase file: " . $path);
 
 unlink($path);
 
 $this->logger->log("File " . $path . " was deleted");
 }
 }
  • 64. DI WAY OF DOING THINGS $logger = new PrintingLogger();
 $eraser = new LocalFileEraser($logger);
 
 $eraser->erase('important-passwords.txt');
  • 65. FUNCTIONAL WAY OF DOING THINGS $erase = function (Logger $logger, $path)
 {
 $logger->log("Attempt to erase file: " . $path);
 
 unlink($path);
 
 $logger->log("File " . $path . " was deleted");
 };
  • 66. FUNCTIONAL WAY OF DOING THINGS use ReactPartial; 
 $erase = function (Logger $logger, $path)
 {
 $logger->log("Attempt to erase file: " . $path);
 unlink($path);
 $logger->log("File " . $path . " was deleted");
 };
 
 $erase = Partialbind($erase, new PrintingLogger()); 
 $erase('important-passwords.txt');
  • 67. CHAPTER 3: THE SYMFONY
  • 69. FEATURES • Many configurations formats • Supports Factories/Configurators/Scopes/Decoration • Extendable with Compiler Passes • Supports lazy loading of services
  • 71. PERFORMANCE OF SYMFONY DIC • Cached/Dumped to PHP code • In debug mode it checks whether config is fresh • During Compilation phase container is being optimised
  • 72. LARGE NUMBER OF CONFIGURATION FILES SLOWS CONTAINER BUILDER
  • 73.
  • 74. SLOW COMPILATION • Minimise number of bundles/config files used • Try to avoid using extras like JMSDiExtraBundle • Can be really painful on NFS
  • 75. LARGE CONTAINERS ARE SLOW TO LOAD AND USE A LOT OF MEMORY
  • 76. LARGE CONTAINERS • Review and remove unnecessary services/bundles etc. • Split application into smaller ones with separate kernels
  • 78.
  • 79. PRIVATE SERVICES • It’s only a hint for compiler • Minor performance gain (inlines instations) • Private services can still be fetched (not recommended)
  • 80. LAZY LOADING OF SERVICES
  • 81. LAZY LOADING OF SERVICES • Used when instantiation is expensive or not needed • i.e. event listeners • Solutions: • Injecting container directly • Using proxy objects
  • 82. INJECTING CONTAINER DIRECTLY • As fast as it can be • Couples service implementation to the container • Makes testing harder
  • 83. USING PROXY OBJECTS • Easy to use (just configuration option) • Code and test are not affected • Adds a bit of overhead • especially when services are called many times • on proxy generation
  • 85. DEFINING CLASS NAMES AS PARAMETERS • Rare use case (since decoration is supported even less) • Adds overhead • Will be removed in Symfony 3.0
  • 87.
  • 89. CIRCULAR REFERENCES • Injecting Container is just a workaround • Using setter injection after instantiation as well • Solving design problem is the real challenge
  • 92. MEANT TO SOLVE “THE REQUEST PROBLEM”
  • 93. SCOPE DEFINES STATE OF THE APPLICATION
  • 95. PROBLEMS WITH INJECTING REQUEST TO SERVICES • Causes ScopeWideningInjectionException • Anti-pattern - Request is a Value Object • Which means Container was managing it’s state • Replaced with RequestStack
  • 96. App Controller A Sub Request Stateful service Sub Request Master Request Stateful service Master Request Controller B REQUESTS MANAGED WITH SCOPES
  • 97. App Controller A Stateless service Request Stack Controller B Sub Request Master Request REQUESTS MANAGED WITH STACK
  • 99.
  • 100. STATEFUL SERVICES • Fetch state explicitly on per need basis (RequestStack) • Use Prototype scope only if you have to…
  • 102.
  • 103. Prototype scope Prototype- scoped Service Z Stateless Service A Prototype scope Prototype- scoped Service Z Stateless Service A Prototype scope Prototype- scoped Service Z Stateless Service A USING PROTOTYPE SCOPE WITH STRICT = TRUE
  • 104. New Instances Stateful Service Z Stateful Service Z Stateful Service Z Stateless Service A USING PROTOTYPE SCOPE WITH STRICT = FALSE
  • 105. FORGET ABOUT SCOPES ANYWAY WILL BE REMOVED IN SYMFONY 3.0 USE SHARED=FALSE INSTEAD
  • 107.
  • 108. EXTENDING BASE CONTROLLER • Easy to use by newcomers / low learning curve • Limits inheritance • Encourages using DIC as Service Locator • Hard unit testing
  • 109. CONTAINER AWARE INTERFACE • Controller is still coupled to framework • Lack of convenience methods • Encourages using DIC as Service Locator • Testing is still hard
  • 110. CONTROLLER AS A SERVICE • Requires additional configuration • Lack of convenience methods • Full possibility to inject only relevant dependencies • Unit testing is easy • Enables Framework-agnostic controllers
  • 111. NONE OF THE ABOVE OPTIONS WILL FORCE YOU TO WRITE GOOD/BAD CODE
  • 113. FEATURES • Implementation of Mediator pattern • Allows for many-to-many relationships between objects • Makes your projects extensible • Supports priorities/stopping event flow
  • 114. EVENT DISPATCHER • Can be (really) hard to debug • Priorities of events / managing event flow • Events can be mutable - indirect coupling • Hard to test
  • 115. INDIRECT COUPLING PROBLEM • Two services listening on kernel.request event: • Priority 16 - GeoIP detector - sets country code • Priority 8 - Locale detector - uses country code and user agent
  • 116. INDIRECT COUPLING PROBLEM • Both events indirectly coupled (via Request->attributes) • Configuration change will change the app logic • In reality we always want to call one after another
  • 117. Listener A Listener B Listener C DispatcherService INDIRECT COUPLING PROBLEM
  • 118.
  • 119. WHEN TO USE EVENT DISPATCHER • Need to extend Framework or other Bundle • Building reusable Bundle & need to add extension points • Consider using separate dispatcher for Domain events
  • 120. CHAPTER 4: THE END ;)
  • 122. BE EXPLICIT & DON’T RELY ON MAGIC
  • 123. Kacper Gunia @cakper Technical Team Leader @SensioLabsUK Symfony Certified Developer PHPers Silesia @PHPersPL Thanks! https://joind.in/14979
  • 124. REFERENCES • http://martinfowler.com/bliki/InversionOfControl.html • http://picocontainer.com/introduction.html • http://www.infoq.com/presentations/8-lines-code-refactoring • http://richardmiller.co.uk/2014/03/12/avoiding-setter-injection/ • http://art-of-software.blogspot.co.uk/2013/02/cztery-smaki- odwracania-i-utraty.html