SlideShare una empresa de Scribd logo
1 de 77
Dependency
Adding
Injection To Legacy
    Applications
Who Is i3logix?
Inversion of Control
Dependency Injection
Built-In
Flexibility
interface Calc {
    public function __invoke($left, $right);
}

class AddCalc implements Calc {
    public function __invoke($left, $right) {
        return $left + $right;
    }
}

class SubCalc implements Calc {
    public function __invoke($left, $right) {
        return $left - $right;
    }
}
class Calculator{
    public function __invoke(Calc $calc, $left, $right){
        return $calc($left, $right);
    }
}

$calculator = new Calculator();
echo $calculator(new AddCalc(), 2, 1), "n";
echo $calculator(new SubCalc(), 2, 1), "n";
De-Coupling
Have Clear Goals
It’s
only
  a
Tool
I   T
N   E
J   C
    H
E
    N
C
    I
T
    Q
I
    U
O
    E
N   S
class Status {
    public function get($system) {
        $client = new Zend_Http_Client();
        $r = $client->setUri(SERVICE_URI)
            ->setParameterGet(compact('system'))
            ->request('GET');

        if ($r->isSuccessful()) {
            return $r->getBody();
        }
        return false;
    }
}
Constructor
   Injection
      Vs.
Setter/Property
   Injection
class StatusSetterInject{
    protected $client;

    public function setClient(Zend_Http_Client $client){
        $this->client = $client;
    }

    public function get($system){
        $r = $this->client->setUri(SERVICE_URI)
            ->setParameterGet(compact('system'))
            ->request('GET');

        if ($r->isSuccessful()){
            return $r->getBody();
        }
        return false;
    }
}
class StatusConstructInject{
    protected $client;

    public function __construct(Zend_Http_Client $client){
        $this->client = $client;
    }

    public function get($system){
        $r = $this->client->setUri(SERVICE_URI)
            ->setParameterGet(compact('system'))
            ->request('GET');

        if($r->isSuccessful()){
            return $r->getBody();
        }
        return false;
    }
}
Init Pattern
class StatusInit{
    protected $client;

   public function __construct(Zend_Http_Client $client){
       $this->client = $client;
       $this->init();
   }

   public function init(){
       //Left empty
   }

    public function get($system){
        $r = $this->client->setUri(SERVICE_URI)
            ->setParameterGet(compact('system'))
            ->request('GET');
//...
    }
}
Optional
Injection
class StatusConstructInjectOptional{
    protected $client;

   public function __construct(
       Zend_Http_Client $client = null){
       if($client === null){
           $client = new Zend_Http_Client();
       }
       $this->client = $client;
   }

    public function get($system){
        $r = $this->client->setUri(SERVICE_URI)
            ->setParameterGet(compact('system'))
            ->request('GET');
//...
    }
}
class StatusSetterInjectOptional{
    protected $client;

   public function setClient(Zend_Http_Client $client){
       $this->client = $client;
   }

   protected function getClient(){
       if ($this->client === null){
           $this->client = new Zend_Http_Client();
       }
       return $this->client;
   }

    public function get($system){
        $r = $this->getClient()->setUri(SERVICE_URI)
            ->setParameterGet(compact('system'))
            ->request('GET');
//...
Class Name Override
class StatusClassNameOverrideConstruct{
    protected $clientClass;

    public function __construct($class = 'Zend_Http_Client'){
        $this->clientClass = $class;
    }

    public function get($system){
        $client = new $this->clientClass;
        $r = $this->getClient()->setUri(SERVICE_URI)
            ->setParameterGet(compact('system'))
            ->request('GET');

        if($r->isSuccessful()){
            return $r->getBody();
        }
        return false;
    }
}
class StatusClassNameOverrideSetter{
    protected $clientClass = 'Zend_Http_Client';

    public function setClass($class){
        $this->clientClass = $class;
    }

    public function get($system){
        $client = new $this->clientClass;
        $r = $this->getClient()->setUri(SERVICE_URI)
            ->setParameterGet(compact('system'))
            ->request('GET');

        if($r->isSuccessful()){
            return $r->getBody();
        }
        return false;
    }
}
BUT I NEED TO CREATE OBJECTS?
class PolyBad {
    public function foo($bar) {
        if (get_class($bar) === 'SomeOtherClass') {
            $tmp = new SomeClass();
        }
    }
}
class PolyGood {
    public function foo(SomeClass $bar) {
        if ($baz instanceof SomeInterface) {
            // Do something
        }
    }
}
class Factory{
    public function create(){
        return new SimpleClass();
    }
}
Dynamic Factory
abstract class FactoryAbstract{
    protected abstract function getClassName();

    public function create(){
        $class = $this->getClassName();
        $argList = func_get_args();
        if (count($argList) < 1){
            return new $class;
        }
        $rClass = new ReflectionClass($class);
        return $rClass->newInstanceArgs($argList);
    }
}
function __autoload($class){
    $classPath = str_replace('_', '/', $class);
    $filePath = __DIR__."/src/$classPath.php";

    if (file_exists($filePath))
       return require $filePath;

    if (substr($class, -7) !== 'Factory')
        return;

    $subName = substr($class, 0, -8);
    eval("class $class extends FactoryAbstract{
        protected function getClassName(){
            return '$subName';
        }
    }");
}
WHAT IS INJECTING THESE OBJECTS?
Injector, Provider, Container
Configuration
<service id="bar" class="FooClass" shared="true"
       constructor="getInstance">
  <file>%path%/foo.php</file>
  <argument>foo</argument>
  <argument type="service" id="foo" />
  <argument type="collection">
    <argument>true</argument>
    <argument>false</argument>
  </argument>
  <configurator function="configure" />
  <call method="setBar" />
  <call method="setBar">
    <argument>foo</argument>
    <argument type="service" id="foo" />
    <argument type="collection">
      <argument>true</argument>
      <argument>false</argument>
    </argument>
  </call>
</service>
Interfaces
if($obj instanceof InjectDb){
    $obj->setDb($this->serviceLocator->getDb());
}

if($obj instanceof InjectTool){
    $obj->setTool($this->serviceLocator->getTool());
}

if($obj instanceof InjectClientBuilder){
    $obj->setClientBuilder($this->getClientBuilder());
}

if($obj instanceof InjectEvent){
    $obj->setEvent($this->serviceLocator->getEvent());
}
Duck Typing
abstract class Zend_View_Abstract
       implements Zend_View_Interface
//...
public function registerHelper($helper, $name){
//...
    if (!$helper instanceof Zend_View_Interface){
        if (!method_exists($helper, $name)){
            require_once 'Zend/View/Exception.php';
            $e = new Zend_View_Exception(
                'View helper must …');
            $e->setView($this);
            throw $e;
        }
    }
    if (method_exists($helper, 'setView')){
        $helper->setView($this);
    }
//...
Auto Wiring
$rParmList = $methodReflection->getParameters();

foreach($rParmList as $rParm ){
    $parmClass = $rParm->getClass();

    if($parmClass !== null){
        $bindConfig->getInjectionConfig()
            ->addMethodInstanceKey(
                $methodName, $parmClass->getName());
    }else{
        throw new Exception(
            "Not possible to configure automatically"
        );
    }
}
Annotations
/**
 * @Singleton
 */
class LoggerSimple{
    /**
     * @Inject Zend_Db_Adapter_Abstract
     */
    public $db;

    /**
     * @Inject
     * @Arg Zend_Db_Adapter_Abstract
     */
    public function __construct($db){
        $this->db = $db;
    }
    /**
     * @Inject
     * @Arg Zend_Db_Adapter_Abstract
     */
    public function setDb($db){
        $this->db = $db;
    }
}
/**
 * @ImplementedBy LoggerSimple
 */
interface Logger{
    public function log($message, $level);
}
$rClass = new ReflectionAnnotatedClass($config->getClass());

if($rClass->isInterface()){
   if($rClass->hasAnnotation('ImplementedBy') === false){
       throw new Exception(…);
   }

    $impClass = $rClass->getAnnotation('ImplementedBy')->value;

    if($impClass === null){
        throw new Exception (…);
    }
    $config->setImplementationClass($impClass);
}
Combine.   Win!
Singleton
class Db{
    protected function __construct(){}
    protected function __clone(){}

    public static function instance(){
        static $instance = null;
        if($instance === null){
            $instance = new static();
        }
        return $instance;
    }
}
Singleton + Registry
class Registry{
    protected static $reg = array();

    public static function add($key, $value){
        static::$reg[$key] = $value;
    }

    public static function get($key){
        return static::$reg[$key];
    }
}
class Registry{
    protected static $reg = array();

    public static function add($key, $value){
        static::$reg[$key] = $value;
    }

    public static function get($key){
        $value = static::$reg[$key];
        if(is_callable($value)){
            return $value();
        }
        return $value;
    }
}
Registry::add('db', function (){return new Db();});
var_dump(Registry::get('db'));
Service Locator
class ServiceLocator{
    protected function __construct(){}
    protected function __clone(){}
    public static function instance(){
        static $instance = null;
        if($instance === null){
            $instance = new static();
        }
        return $instance;
    }

    public function getDb(){
        static $db = null;
        if($db === null){
            $db = new Db();
        }
        return $db;
    }
}
Coarse-Grained




                 Fine-Grained
Design by




            Contract
class Logger{}
abstract class LoggerAbstract{}

class LoggerEcho extends LoggerAbstract{}

class LoggerFile extends LoggerAbstract{}
interface LoggerInterface{}

abstract class LoggerAbstract implements LoggerInterface{}

class LoggerEcho extends LoggerAbstract{}

class LoggerFile extends LoggerAbstract{}

class LoggerOddBall implements LoggerInterface{}
class Logger{}
abstract class Logger{}

class LoggerEcho extends Logger{}

class LoggerFile extends Logger{}
interface Logger{}

abstract class LoggerAbstract implements Logger{}

class LoggerEcho extends Logger{}

class LoggerFile extends Logger{}

class LoggerOddBall implements Logger{}
Prefer Composition Over Inheritance
WHAT’S ALREADY OUT THERE?
YOU NEED
    A
GAME PLAN!
http://joind.in/3740

T HANK Y OU!

Más contenido relacionado

La actualidad más candente

PHPUnit elevato alla Symfony2
PHPUnit elevato alla Symfony2PHPUnit elevato alla Symfony2
PHPUnit elevato alla Symfony2eugenio pombi
 
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 domain model with symfony 2.5 and doctrine 2.5
Rich domain model with symfony 2.5 and doctrine 2.5Rich domain model with symfony 2.5 and doctrine 2.5
Rich domain model with symfony 2.5 and doctrine 2.5Leonardo Proietti
 
Crafting beautiful software
Crafting beautiful softwareCrafting beautiful software
Crafting beautiful softwareJorn Oomen
 
The IoC Hydra - Dutch PHP Conference 2016
The IoC Hydra - Dutch PHP Conference 2016The IoC Hydra - Dutch PHP Conference 2016
The IoC Hydra - Dutch PHP Conference 2016Kacper Gunia
 
Decoupling with Design Patterns and Symfony2 DIC
Decoupling with Design Patterns and Symfony2 DICDecoupling with Design Patterns and Symfony2 DIC
Decoupling with Design Patterns and Symfony2 DICKonstantin Kudryashov
 
Introduction to Zend Framework web services
Introduction to Zend Framework web servicesIntroduction to Zend Framework web services
Introduction to Zend Framework web servicesMichelangelo van Dam
 
Symfony2 Building on Alpha / Beta technology
Symfony2 Building on Alpha / Beta technologySymfony2 Building on Alpha / Beta technology
Symfony2 Building on Alpha / Beta technologyDaniel Knell
 
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
 
Why is crud a bad idea - focus on real scenarios
Why is crud a bad idea - focus on real scenariosWhy is crud a bad idea - focus on real scenarios
Why is crud a bad idea - focus on real scenariosDivante
 
Your code sucks, let's fix it - DPC UnCon
Your code sucks, let's fix it - DPC UnConYour code sucks, let's fix it - DPC UnCon
Your code sucks, let's fix it - DPC UnConRafael Dohms
 
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
 
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
 
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
 
PhpUnit - The most unknown Parts
PhpUnit - The most unknown PartsPhpUnit - The most unknown Parts
PhpUnit - The most unknown PartsBastian Feder
 
Object Calisthenics Adapted for PHP
Object Calisthenics Adapted for PHPObject Calisthenics Adapted for PHP
Object Calisthenics Adapted for PHPChad Gray
 
When cqrs meets event sourcing
When cqrs meets event sourcingWhen cqrs meets event sourcing
When cqrs meets event sourcingManel Sellés
 

La actualidad más candente (20)

PHPUnit elevato alla Symfony2
PHPUnit elevato alla Symfony2PHPUnit elevato alla Symfony2
PHPUnit elevato alla Symfony2
 
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 domain model with symfony 2.5 and doctrine 2.5
Rich domain model with symfony 2.5 and doctrine 2.5Rich domain model with symfony 2.5 and doctrine 2.5
Rich domain model with symfony 2.5 and doctrine 2.5
 
Min-Maxing Software Costs
Min-Maxing Software CostsMin-Maxing Software Costs
Min-Maxing Software Costs
 
Crafting beautiful software
Crafting beautiful softwareCrafting beautiful software
Crafting beautiful software
 
The IoC Hydra
The IoC HydraThe IoC Hydra
The IoC Hydra
 
The IoC Hydra - Dutch PHP Conference 2016
The IoC Hydra - Dutch PHP Conference 2016The IoC Hydra - Dutch PHP Conference 2016
The IoC Hydra - Dutch PHP Conference 2016
 
Decoupling with Design Patterns and Symfony2 DIC
Decoupling with Design Patterns and Symfony2 DICDecoupling with Design Patterns and Symfony2 DIC
Decoupling with Design Patterns and Symfony2 DIC
 
Introduction to Zend Framework web services
Introduction to Zend Framework web servicesIntroduction to Zend Framework web services
Introduction to Zend Framework web services
 
Symfony2 Building on Alpha / Beta technology
Symfony2 Building on Alpha / Beta technologySymfony2 Building on Alpha / Beta technology
Symfony2 Building on Alpha / Beta technology
 
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
 
Why is crud a bad idea - focus on real scenarios
Why is crud a bad idea - focus on real scenariosWhy is crud a bad idea - focus on real scenarios
Why is crud a bad idea - focus on real scenarios
 
Your code sucks, let's fix it - DPC UnCon
Your code sucks, let's fix it - DPC UnConYour code sucks, let's fix it - DPC UnCon
Your code sucks, let's fix it - DPC UnCon
 
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
 
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
 
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...
 
PhpUnit - The most unknown Parts
PhpUnit - The most unknown PartsPhpUnit - The most unknown Parts
PhpUnit - The most unknown Parts
 
Object Calisthenics Adapted for PHP
Object Calisthenics Adapted for PHPObject Calisthenics Adapted for PHP
Object Calisthenics Adapted for PHP
 
When cqrs meets event sourcing
When cqrs meets event sourcingWhen cqrs meets event sourcing
When cqrs meets event sourcing
 
Php Enums
Php EnumsPhp Enums
Php Enums
 

Similar a Adding Dependency Injection to Legacy Applications

PHPUnit でよりよくテストを書くために
PHPUnit でよりよくテストを書くためにPHPUnit でよりよくテストを書くために
PHPUnit でよりよくテストを書くためにYuya Takeyama
 
Things I Believe Now That I'm Old
Things I Believe Now That I'm OldThings I Believe Now That I'm Old
Things I Believe Now That I'm OldRoss Tuck
 
Dependency Injection
Dependency InjectionDependency Injection
Dependency InjectionRifat Nabi
 
Tidy Up Your Code
Tidy Up Your CodeTidy Up Your Code
Tidy Up Your CodeAbbas Ali
 
Code moi une RH! (PHP tour 2017)
Code moi une RH! (PHP tour 2017)Code moi une RH! (PHP tour 2017)
Code moi une RH! (PHP tour 2017)Arnaud Langlade
 
How Kris Writes Symfony Apps
How Kris Writes Symfony AppsHow Kris Writes Symfony Apps
How Kris Writes Symfony AppsKris Wallsmith
 
Melhorando sua API com DSLs
Melhorando sua API com DSLsMelhorando sua API com DSLs
Melhorando sua API com DSLsAugusto Pascutti
 
PHP Experience 2016 - [Palestra] Melhorando a comunicação da API através de DSL
PHP Experience 2016 - [Palestra] Melhorando a comunicação da API através de DSLPHP Experience 2016 - [Palestra] Melhorando a comunicação da API através de DSL
PHP Experience 2016 - [Palestra] Melhorando a comunicação da API através de DSLiMasters
 
laravel tricks in 50minutes
laravel tricks in 50minuteslaravel tricks in 50minutes
laravel tricks in 50minutesBarang CK
 
50 Laravel Tricks in 50 Minutes
50 Laravel Tricks in 50 Minutes50 Laravel Tricks in 50 Minutes
50 Laravel Tricks in 50 MinutesAzim Kurt
 
ZF2 for the ZF1 Developer
ZF2 for the ZF1 DeveloperZF2 for the ZF1 Developer
ZF2 for the ZF1 DeveloperGary Hockin
 
Command Bus To Awesome Town
Command Bus To Awesome TownCommand Bus To Awesome Town
Command Bus To Awesome TownRoss Tuck
 
Meet Magento Sweden - Magento 2 Layout and Code Compilation for Performance
Meet Magento Sweden - Magento 2 Layout and Code Compilation for PerformanceMeet Magento Sweden - Magento 2 Layout and Code Compilation for Performance
Meet Magento Sweden - Magento 2 Layout and Code Compilation for PerformanceIvan Chepurnyi
 
PHP for Adults: Clean Code and Object Calisthenics
PHP for Adults: Clean Code and Object CalisthenicsPHP for Adults: Clean Code and Object Calisthenics
PHP for Adults: Clean Code and Object CalisthenicsGuilherme Blanco
 
Migrating to dependency injection
Migrating to dependency injectionMigrating to dependency injection
Migrating to dependency injectionJosh Adell
 

Similar a Adding Dependency Injection to Legacy Applications (20)

PHPUnit でよりよくテストを書くために
PHPUnit でよりよくテストを書くためにPHPUnit でよりよくテストを書くために
PHPUnit でよりよくテストを書くために
 
Things I Believe Now That I'm Old
Things I Believe Now That I'm OldThings I Believe Now That I'm Old
Things I Believe Now That I'm Old
 
Unittests für Dummies
Unittests für DummiesUnittests für Dummies
Unittests für Dummies
 
Dependency Injection
Dependency InjectionDependency Injection
Dependency Injection
 
Tidy Up Your Code
Tidy Up Your CodeTidy Up Your Code
Tidy Up Your Code
 
Code moi une RH! (PHP tour 2017)
Code moi une RH! (PHP tour 2017)Code moi une RH! (PHP tour 2017)
Code moi une RH! (PHP tour 2017)
 
How Kris Writes Symfony Apps
How Kris Writes Symfony AppsHow Kris Writes Symfony Apps
How Kris Writes Symfony Apps
 
Melhorando sua API com DSLs
Melhorando sua API com DSLsMelhorando sua API com DSLs
Melhorando sua API com DSLs
 
PHP Experience 2016 - [Palestra] Melhorando a comunicação da API através de DSL
PHP Experience 2016 - [Palestra] Melhorando a comunicação da API através de DSLPHP Experience 2016 - [Palestra] Melhorando a comunicação da API através de DSL
PHP Experience 2016 - [Palestra] Melhorando a comunicação da API através de DSL
 
laravel tricks in 50minutes
laravel tricks in 50minuteslaravel tricks in 50minutes
laravel tricks in 50minutes
 
50 Laravel Tricks in 50 Minutes
50 Laravel Tricks in 50 Minutes50 Laravel Tricks in 50 Minutes
50 Laravel Tricks in 50 Minutes
 
ZF2 for the ZF1 Developer
ZF2 for the ZF1 DeveloperZF2 for the ZF1 Developer
ZF2 for the ZF1 Developer
 
BEAR DI
BEAR DIBEAR DI
BEAR DI
 
Command Bus To Awesome Town
Command Bus To Awesome TownCommand Bus To Awesome Town
Command Bus To Awesome Town
 
Oops in php
Oops in phpOops in php
Oops in php
 
Meet Magento Sweden - Magento 2 Layout and Code Compilation for Performance
Meet Magento Sweden - Magento 2 Layout and Code Compilation for PerformanceMeet Magento Sweden - Magento 2 Layout and Code Compilation for Performance
Meet Magento Sweden - Magento 2 Layout and Code Compilation for Performance
 
PHP for Adults: Clean Code and Object Calisthenics
PHP for Adults: Clean Code and Object CalisthenicsPHP for Adults: Clean Code and Object Calisthenics
PHP for Adults: Clean Code and Object Calisthenics
 
Bacbkone js
Bacbkone jsBacbkone js
Bacbkone js
 
Taming Command Bus
Taming Command BusTaming Command Bus
Taming Command Bus
 
Migrating to dependency injection
Migrating to dependency injectionMigrating to dependency injection
Migrating to dependency injection
 

Último

New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024BookNet Canada
 
Gen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdfGen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdfAddepto
 
How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.Curtis Poe
 
Unleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubUnleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubKalema Edgar
 
TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024Lonnie McRorey
 
Digital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptxDigital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptxLoriGlavin3
 
Generative AI for Technical Writer or Information Developers
Generative AI for Technical Writer or Information DevelopersGenerative AI for Technical Writer or Information Developers
Generative AI for Technical Writer or Information DevelopersRaghuram Pandurangan
 
unit 4 immunoblotting technique complete.pptx
unit 4 immunoblotting technique complete.pptxunit 4 immunoblotting technique complete.pptx
unit 4 immunoblotting technique complete.pptxBkGupta21
 
"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr BaganFwdays
 
DevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache MavenDevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache MavenHervé Boutemy
 
Hyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdf
Hyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdfHyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdf
Hyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdfPrecisely
 
"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii Soldatenko"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii SoldatenkoFwdays
 
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptxThe Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptxLoriGlavin3
 
SAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptxSAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptxNavinnSomaal
 
SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024Lorenzo Miniero
 
SALESFORCE EDUCATION CLOUD | FEXLE SERVICES
SALESFORCE EDUCATION CLOUD | FEXLE SERVICESSALESFORCE EDUCATION CLOUD | FEXLE SERVICES
SALESFORCE EDUCATION CLOUD | FEXLE SERVICESmohitsingh558521
 
Unraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfUnraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfAlex Barbosa Coqueiro
 
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptxThe Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptxLoriGlavin3
 
From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .Alan Dix
 
DevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsDevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsSergiu Bodiu
 

Último (20)

New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
 
Gen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdfGen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdf
 
How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.
 
Unleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubUnleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding Club
 
TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024
 
Digital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptxDigital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptx
 
Generative AI for Technical Writer or Information Developers
Generative AI for Technical Writer or Information DevelopersGenerative AI for Technical Writer or Information Developers
Generative AI for Technical Writer or Information Developers
 
unit 4 immunoblotting technique complete.pptx
unit 4 immunoblotting technique complete.pptxunit 4 immunoblotting technique complete.pptx
unit 4 immunoblotting technique complete.pptx
 
"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan
 
DevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache MavenDevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache Maven
 
Hyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdf
Hyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdfHyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdf
Hyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdf
 
"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii Soldatenko"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii Soldatenko
 
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptxThe Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
 
SAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptxSAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptx
 
SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024
 
SALESFORCE EDUCATION CLOUD | FEXLE SERVICES
SALESFORCE EDUCATION CLOUD | FEXLE SERVICESSALESFORCE EDUCATION CLOUD | FEXLE SERVICES
SALESFORCE EDUCATION CLOUD | FEXLE SERVICES
 
Unraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfUnraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdf
 
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptxThe Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
 
From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .
 
DevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsDevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platforms
 

Adding Dependency Injection to Legacy Applications

  • 2.
  • 6.
  • 7.
  • 9. interface Calc { public function __invoke($left, $right); } class AddCalc implements Calc { public function __invoke($left, $right) { return $left + $right; } } class SubCalc implements Calc { public function __invoke($left, $right) { return $left - $right; } }
  • 10. class Calculator{ public function __invoke(Calc $calc, $left, $right){ return $calc($left, $right); } } $calculator = new Calculator(); echo $calculator(new AddCalc(), 2, 1), "n"; echo $calculator(new SubCalc(), 2, 1), "n";
  • 13.
  • 15. I T N E J C H E N C I T Q I U O E N S
  • 16.
  • 17. class Status { public function get($system) { $client = new Zend_Http_Client(); $r = $client->setUri(SERVICE_URI) ->setParameterGet(compact('system')) ->request('GET'); if ($r->isSuccessful()) { return $r->getBody(); } return false; } }
  • 18. Constructor Injection Vs. Setter/Property Injection
  • 19. class StatusSetterInject{ protected $client; public function setClient(Zend_Http_Client $client){ $this->client = $client; } public function get($system){ $r = $this->client->setUri(SERVICE_URI) ->setParameterGet(compact('system')) ->request('GET'); if ($r->isSuccessful()){ return $r->getBody(); } return false; } }
  • 20. class StatusConstructInject{ protected $client; public function __construct(Zend_Http_Client $client){ $this->client = $client; } public function get($system){ $r = $this->client->setUri(SERVICE_URI) ->setParameterGet(compact('system')) ->request('GET'); if($r->isSuccessful()){ return $r->getBody(); } return false; } }
  • 22. class StatusInit{ protected $client; public function __construct(Zend_Http_Client $client){ $this->client = $client; $this->init(); } public function init(){ //Left empty } public function get($system){ $r = $this->client->setUri(SERVICE_URI) ->setParameterGet(compact('system')) ->request('GET'); //... } }
  • 24. class StatusConstructInjectOptional{ protected $client; public function __construct( Zend_Http_Client $client = null){ if($client === null){ $client = new Zend_Http_Client(); } $this->client = $client; } public function get($system){ $r = $this->client->setUri(SERVICE_URI) ->setParameterGet(compact('system')) ->request('GET'); //... } }
  • 25. class StatusSetterInjectOptional{ protected $client; public function setClient(Zend_Http_Client $client){ $this->client = $client; } protected function getClient(){ if ($this->client === null){ $this->client = new Zend_Http_Client(); } return $this->client; } public function get($system){ $r = $this->getClient()->setUri(SERVICE_URI) ->setParameterGet(compact('system')) ->request('GET'); //...
  • 27. class StatusClassNameOverrideConstruct{ protected $clientClass; public function __construct($class = 'Zend_Http_Client'){ $this->clientClass = $class; } public function get($system){ $client = new $this->clientClass; $r = $this->getClient()->setUri(SERVICE_URI) ->setParameterGet(compact('system')) ->request('GET'); if($r->isSuccessful()){ return $r->getBody(); } return false; } }
  • 28. class StatusClassNameOverrideSetter{ protected $clientClass = 'Zend_Http_Client'; public function setClass($class){ $this->clientClass = $class; } public function get($system){ $client = new $this->clientClass; $r = $this->getClient()->setUri(SERVICE_URI) ->setParameterGet(compact('system')) ->request('GET'); if($r->isSuccessful()){ return $r->getBody(); } return false; } }
  • 29. BUT I NEED TO CREATE OBJECTS?
  • 30. class PolyBad { public function foo($bar) { if (get_class($bar) === 'SomeOtherClass') { $tmp = new SomeClass(); } } }
  • 31. class PolyGood { public function foo(SomeClass $bar) { if ($baz instanceof SomeInterface) { // Do something } } }
  • 32.
  • 33. class Factory{ public function create(){ return new SimpleClass(); } }
  • 35. abstract class FactoryAbstract{ protected abstract function getClassName(); public function create(){ $class = $this->getClassName(); $argList = func_get_args(); if (count($argList) < 1){ return new $class; } $rClass = new ReflectionClass($class); return $rClass->newInstanceArgs($argList); } }
  • 36. function __autoload($class){ $classPath = str_replace('_', '/', $class); $filePath = __DIR__."/src/$classPath.php"; if (file_exists($filePath)) return require $filePath; if (substr($class, -7) !== 'Factory') return; $subName = substr($class, 0, -8); eval("class $class extends FactoryAbstract{ protected function getClassName(){ return '$subName'; } }"); }
  • 37. WHAT IS INJECTING THESE OBJECTS?
  • 40. <service id="bar" class="FooClass" shared="true" constructor="getInstance"> <file>%path%/foo.php</file> <argument>foo</argument> <argument type="service" id="foo" /> <argument type="collection"> <argument>true</argument> <argument>false</argument> </argument> <configurator function="configure" /> <call method="setBar" /> <call method="setBar"> <argument>foo</argument> <argument type="service" id="foo" /> <argument type="collection"> <argument>true</argument> <argument>false</argument> </argument> </call> </service>
  • 42. if($obj instanceof InjectDb){ $obj->setDb($this->serviceLocator->getDb()); } if($obj instanceof InjectTool){ $obj->setTool($this->serviceLocator->getTool()); } if($obj instanceof InjectClientBuilder){ $obj->setClientBuilder($this->getClientBuilder()); } if($obj instanceof InjectEvent){ $obj->setEvent($this->serviceLocator->getEvent()); }
  • 44. abstract class Zend_View_Abstract implements Zend_View_Interface //... public function registerHelper($helper, $name){ //... if (!$helper instanceof Zend_View_Interface){ if (!method_exists($helper, $name)){ require_once 'Zend/View/Exception.php'; $e = new Zend_View_Exception( 'View helper must …'); $e->setView($this); throw $e; } } if (method_exists($helper, 'setView')){ $helper->setView($this); } //...
  • 46. $rParmList = $methodReflection->getParameters(); foreach($rParmList as $rParm ){ $parmClass = $rParm->getClass(); if($parmClass !== null){ $bindConfig->getInjectionConfig() ->addMethodInstanceKey( $methodName, $parmClass->getName()); }else{ throw new Exception( "Not possible to configure automatically" ); } }
  • 48. /** * @Singleton */ class LoggerSimple{ /** * @Inject Zend_Db_Adapter_Abstract */ public $db; /** * @Inject * @Arg Zend_Db_Adapter_Abstract */ public function __construct($db){ $this->db = $db; } /** * @Inject * @Arg Zend_Db_Adapter_Abstract */ public function setDb($db){ $this->db = $db; } }
  • 49. /** * @ImplementedBy LoggerSimple */ interface Logger{ public function log($message, $level); }
  • 50. $rClass = new ReflectionAnnotatedClass($config->getClass()); if($rClass->isInterface()){ if($rClass->hasAnnotation('ImplementedBy') === false){ throw new Exception(…); } $impClass = $rClass->getAnnotation('ImplementedBy')->value; if($impClass === null){ throw new Exception (…); } $config->setImplementationClass($impClass); }
  • 51. Combine. Win!
  • 52.
  • 54. class Db{ protected function __construct(){} protected function __clone(){} public static function instance(){ static $instance = null; if($instance === null){ $instance = new static(); } return $instance; } }
  • 56. class Registry{ protected static $reg = array(); public static function add($key, $value){ static::$reg[$key] = $value; } public static function get($key){ return static::$reg[$key]; } }
  • 57. class Registry{ protected static $reg = array(); public static function add($key, $value){ static::$reg[$key] = $value; } public static function get($key){ $value = static::$reg[$key]; if(is_callable($value)){ return $value(); } return $value; } }
  • 58. Registry::add('db', function (){return new Db();}); var_dump(Registry::get('db'));
  • 60. class ServiceLocator{ protected function __construct(){} protected function __clone(){} public static function instance(){ static $instance = null; if($instance === null){ $instance = new static(); } return $instance; } public function getDb(){ static $db = null; if($db === null){ $db = new Db(); } return $db; } }
  • 61. Coarse-Grained Fine-Grained
  • 62.
  • 63. Design by Contract
  • 65. abstract class LoggerAbstract{} class LoggerEcho extends LoggerAbstract{} class LoggerFile extends LoggerAbstract{}
  • 66. interface LoggerInterface{} abstract class LoggerAbstract implements LoggerInterface{} class LoggerEcho extends LoggerAbstract{} class LoggerFile extends LoggerAbstract{} class LoggerOddBall implements LoggerInterface{}
  • 68. abstract class Logger{} class LoggerEcho extends Logger{} class LoggerFile extends Logger{}
  • 69. interface Logger{} abstract class LoggerAbstract implements Logger{} class LoggerEcho extends Logger{} class LoggerFile extends Logger{} class LoggerOddBall implements Logger{}
  • 70. Prefer Composition Over Inheritance
  • 72.
  • 73.
  • 74.
  • 75. YOU NEED A GAME PLAN!
  • 76.

Notas del editor

  1. http://www.flickr.com/photos/jon_bradley/3360454148/sizes/o/in/photostream/http://www.flickr.com/photos/walker-chris-steph-jordan/2983082765/sizes/o/in/photostream/
  2. http://www.flickr.com/photos/santomarco/5427382270/sizes/l/in/photostream/
  3. The Hollywood principle Try to make your code ignorant of it’s context
  4. It’s a way of adding abstraction.By abstraction, we mean to abstract from view or hide.
  5. danielspils
  6. tnarik&apos;s - flickr
  7. Have you ever felt like a crash test dummyAdd automated testing
  8. Strategy PatternExplain picPic – Flickr - dominicbartolini
  9. Add pointers to dependencies
  10. Welding customHitch interfaceRope a lot of workWelder – Flickr - F0t0Synthcogdogblog – tow hitch - flickr
  11. DI should not be your goal, especially when it comes to adding DI to you’re legacy appsMaintainable codeQuality codeFlexible codeReusable codeNVJ – Flickr
  12. Bang for the Buck!Not everything needs to have DI or fit the goal you are going afterIf you’re goal is testability and you are using ZF1 for example, not every plugin or helper you create maybe worth the time it would take to create unit tests for.If you are adding DI to a code base where not everyone is on-board with the concept. This will help you fall foul of the perception you are wasting time.Being a purest in legacy code may take you to an early grave.http://misternewuzer.deviantart.com/art/Pop-Bang-Warpath-119523671
  13. What I hope to give to you are some new tools to add to your tool boxWhiteforgeflickr
  14. The Hollywood principle in practiceYou’re code should not know what it’s doing in the grand schema of things It should not be aware of it’s contexthttp://www.flickr.com/photos/duke_raoul/2262882022/sizes/l/in/photostream/
  15. Be careful, opinions vary on this topicBike shed question,It doesn’t matter when you are adding DI to legacy, because the answer is, what ever works for you right now.http://www.flickr.com/photos/sue_langford/4525633192/sizes/l/in/photostream/
  16. A helper pattern that works well with constructor injection, when you expect people to extend the classhttp://www.flickr.com/photos/22212359@N06/2307645669/sizes/l/in/photostream/
  17. http://www.flickr.com/photos/mag3737/377132773/sizes/o/in/photostream/
  18. This can get ugly with large dependency listsThat’s also a code smell that your object is trying to do too much
  19. You can combine this with constructor injection also
  20. showbiz kids - flickr
  21. Mixed string with instance
  22. If you so an string check you could combine this is injection of an object instance
  23. Hollywood principle againIf you use a class name where polymorphism can’t be used then you are calling out to the global namespace.Polymorphism is the ability to switch or replace an object of one type with an object of another typehttp://www.flickr.com/photos/demonbaby/3788532381/sizes/o/in/photostream/
  24. Many types and names (factory method, builder, containers)Dirty work happens hereNeed to inject the factory into the objects that needs to create objectsRamson – Flickr
  25. This is a little tedious for simple things
  26. CDEGlobal – Flickr
  27. Need to be careful once you start to combine with other techniques
  28. Need some class name conventionCreate the real one to overrideDon’t have to use eval
  29. So I can inject an instanceI can inject a factoryBut when and how do I do thatThis is the real hard workMichael D. Dunn – flickr
  30. Just a sophisticated factorySo we will just be building upon what we have already cover for factoriesPinkpurse - Flickr
  31. DavidMenting – Flickr
  32. Could be PHP, XML, ini, etc
  33. DAN_DAN2 – Flickr
  34. Remember this would be inside of a factoryDoesn&apos;t scale great, but not awful
  35. If it walks like a duck and it talks like a duck, then it’s a duck!http://www.flickr.com/photos/shinyhappyworld/5475939747/sizes/l/in/photostream/
  36. Code from ZF1Could go further and check type hits and param counts.Could become a mess if it’s used a lot. In PHP you will need to do some kind of introspection You can cache the result of the introspection based on class nameIn reality this is the most powerful model for decupling, but with great power come great opportunity to kill yourself
  37. Try to wire the objects up with out a central configuration and without a hand coded factory for every non-trivial object
  38. Code from a DI project I created
  39. Well sudoZalgon – Flickr
  40. Will also have to check inheritance tree for things like class level annotations
  41. Used with auto wiring
  42. If you process the annotations by creating a config object about the class, you can then cache that config object.
  43. It not always possible or advisable to be 100% DI, especially but not right away.
  44. Gives you global access and a shared instanceWill spread global access all over your codeBob.Fornal– Flickr
  45. Hard to test without adding test hooks to reset, which is evil.
  46. You can put anything you need in the registryAnyone can put or change the data in the registry
  47. A little better than just a singleton. Something still has to fill it with class instances first. Could use anonymous function.
  48. ilovememphis – Flickr
  49. Like a fixed registry with builder code baked in.Still has an issue with testing, but solutions are less evilIf you’ve ever worked with ZF1 boot-strapper and resource plugins this is much like thatIt also is a model of making the service locator pluggable
  50. cogdogblog – Flickr
  51. Refactoring&apos;sKaptain Kobold – Flickr
  52. Don&apos;t call an interface an interface
  53. Written, verbal, call a meeting, socialize it, lunch and learns. Give it time.