SlideShare une entreprise Scribd logo
Decouple your PHP code
    for reusability
       Fabien Potencier
Who am I?
•  Founder of Sensio
  –  Web Agency
  –  Since 1998
  –  About 50 people
  –  Open-Source Specialists
  –  Big corporate customers


•  Creator and lead developer of symfony
  –  PHP framework
Coupling?



Coupling is the degree to which
 each program module relies on
 each one of the other modules.

                 http://en.wikipedia.org/wiki/Coupling_(computer_science)
Low Coupling



With low coupling, a change in one
 module will not require a change
 in the implementation of another
             module.
Low Coupling



A module can interact with another
   module but through a stable
             interface
Why does it matter?
Testability



The ability to instantiate a class
     in a test demonstrates
     the level of decoupling
           of your code
Readability



 Code spends more time
being read and maintained
    than being created
Maintainability


A change "here"
 must not cause
a problem "there"
Extensibility



Smaller loosely coupled modules
         makes your code
         easier to extend
Reusability
The programming world
  is evolving fast… very fast

But the ultimate goal of these
      changes is the same
Build better tools
    to avoid reinventing
         the wheel
Build on existing code / work / libraries
Specialize for your specific needs
That’s why Open-Source wins
Better tools are possible because
we base our work on existing work

  We learn from other projects

    We can adopt their ideas

    We can make them better

 This is the process of evolution
Reusability

     Configuration
Customization / Extension
Documentation / Support
Dependency Injection
A real world « web » example
In most web applications,
you need to manage the user preferences

  –  The user language
  –  Whether the user is authenticated or not
  –  The user credentials
  –  …
This can be done with a User object

  – setLanguage(), getLanguage()
  – setAuthenticated(), isAuthenticated()
  – addCredential(), hasCredential()
  – ...
The User information
         need to be persisted
        between HTTP requests

We use the PHP session for the Storage
class SessionStorage
{
  function __construct($cookieName = 'PHP_SESS_ID')
  {
    session_name($cookieName);
    session_start();
  }

    function set($key, $value)
    {
      $_SESSION[$key] = $value;
    }

    // ...
}
class User
{
  protected $storage;

    function __construct()
    {
      $this->storage = new SessionStorage();
    }

    function setLanguage($language)
    {
      $this->storage->set('language', $language);
    }

    // ...
}

$user = new User();
I want to change the session cookie name
class User
{
  protected $storage;                   Hardcode it in
                                        the User class
    function __construct()
    {
      $this->storage = new SessionStorage('SESSION_ID');
    }

    function setLanguage($language)
    {
      $this->storage->set('language', $language);
    }

    // ...
}

$user = new User();
class User
{
  protected $storage;                           Add a global
                                               configuration?
    function __construct()
    {
        $this->storage = new SessionStorage(STORAGE_SESSION_NAME);
    }
}



define('STORAGE_SESSION_NAME', 'SESSION_ID');

$user = new User();
Configure via
class User
                                           User?
{
  protected $storage;

    function __construct($sessionName)
    {
      $this->storage = new SessionStorage($sessionName);
    }
}

$user = new User('SESSION_ID');
Configure with
class User                                an array
{
  protected $storage;

  function __construct($storageOptions)
  {
    $this->storage = new
 SessionStorage($storageOptions['session_name']);

$user = new User(
   array('session_name' => 'SESSION_ID')
);
I want to change the session storage engine

                Filesystem
                  MySQL
                  SQLite
                     …
Use a global
class User                             registry object?
{
  protected $storage;

    function __construct()
    {
      $this->storage = Registry::get('session_storage');
    }
}

$storage = new SessionStorage();
Registry::set('session_storage', $storage);
$user = new User();
The User now depends on the Registry
Instead of harcoding
  the Storage dependency
      in the User class

Inject the Storage dependency
       in the User object
Constructor
class User                              argument
{
  protected $storage;

    function __construct($storage)
    {
      $this->storage = $storage;
    }
}

$storage = new SessionStorage('SESSION_ID');
$user = new User($storage);
Use different Storage strategies
class User
{
  protected $storage;

    function __construct($storage)   Use a different
    {                                Storage engine
      $this->storage = $storage;
    }
}

$storage = new MySQLSessionStorage('SESSION_ID');
$user = new User($storage);
Configuration becomes natural
class User
{
  protected $storage;

    function __construct($storage)   Configuration
    {                                 is natural
      $this->storage = $storage;
    }
}

$storage = new MySQLSessionStorage('SESSION_ID');
$user = new User($storage);
Wrap third-party classes (Interface / Adapter)
class User
{
  protected $storage;

  function __construct(ISessionStorage $storage)
  {
    $this->storage = $storage;
  }                                      Add an
}                                       interface

interface ISessionStorage
{
  function get($key);

    function set($key, $value);
}
Mock the Storage object (for testing)
class User
{
  protected $storage;

    function __construct(ISessionStorage $storage)
    {
      $this->storage = $storage;
    }
}

class SessionStorageForTests implements ISessionStorage
{
  protected $data
  function set($key, $value)
  {                                        Mock the
    self::$data[$key] = $value;             Session
  }
}
Use different Storage strategies
       Configuration becomes natural
Wrap third-party classes (Interface / Adapter)
    Mock the Storage object (for testing)


Easy without changing the User class
That’s Dependency Injection

      Nothing more
« Dependency Injection is
    where components are given
     their dependencies through
    their constructors, methods,
       or directly into fields. »
http://www.picocontainer.org/injection.html
$storage = new SessionStorage();

// constructor injection
$user = new User($storage);

// setter injection
$user = new User();
$user->setStorage($storage);

// property injection
$user = new User();
$user->storage = $storage;
A slightly more complex
      web example
$request = new WebRequest();
$response = new WebResponse();

$storage = new
 FileSessionStorage('SESSION_ID');
$user = new User($storage);

$cache = new FileCache(
   array('dir' => dirname(__FILE__).'/cache')
);
$routing = new Routing($cache);
class Application
{
  function __construct()
  {
    $this->request = new WebRequest();
    $this->response = new WebResponse();

        $storage = new FileSessionStorage('SESSION_ID');
        $this->user = new User($storage);

        $cache = new FileCache(
           array('dir' => dirname(__FILE__).'/cache')
        );
        $this->routing = new Routing($cache);
    }
}

$application = new Application();
Back to square 1
class Application
{
  function __construct()
  {
    $request = new WebRequest();
    $response = new WebResponse();

        $storage = new FileSessionStorage('SESSION_ID');
        $user = new User($storage);

        $cache = new FileCache(
           array('dir' => dirname(__FILE__).'/cache')
        );
        $routing = new Routing($cache);
    }
}

$application = new Application();
We need a Container
           Objects
and relationships description

       Configuration

        Instantiation
Service
                                  description




$storageDef = new ServiceDefinition(
   'FileSessionStorage'
);




                     Class name
$storageDef = new ServiceDefinition(
   'FileSessionStorage',
   array('SESSION_ID')
);


        Arguments to
         pass to the
         constructor
$container = new ServiceContainer(array(
  'storage' => $storageDef,
));



      Each object has a
       unique identifier
$userDef = new ServiceDefinition(‘User’,
   array(new ServiceReference('storage'))
);



                                 Reference to
                                another object
$storageDef = new ServiceDefinition(
   ‘FileSessionStorage’,
   array(‘SESSION_ID’)
);

$userDef = new ServiceDefinition(‘User’,
   array(new ServiceReference(‘storage’))
);

$container = new ServiceContainer(array(
  'storage' => $storageDef,
  'user'    => $userDef,
));
$user = $container->getService('user');



         Get the configuration for the user object

   The User constructor must be given a storage object

        Get the storage object from the container

Create a User object by passing the constructor arguments
$user = $container->getService('user');



          is roughly equivalent to


$storage = new SessionStorage('SESSION_ID');
         $user = new User($storage);
A container
      is able to manage
      any object (POPO)


The objects do not need to know
       they are managed
         by a container
Implementation tips
public function getService ($id)
{
  $def = $this->definitions[$id];

    $r = new ReflectionClass($def->getClass());

    if (is_null($r->getConstructor()))
    {
      return $r->newInstance();
    }

    $args = $def->getArguments();
    $args = $this->evaluateArguments($args);

    return $r->newInstanceArgs($args);
}
public function evaluateArguments($arg)
{
  if (is_array($arg))
  {
    return array_map(
       array($this, 'evaluateArguments'), $arg
    );
  }

    if (
      is_object($arg)
      && $arg instanceof ServiceReference
    )
    {
      return $this->getService($arg);
    }

    return $arg;
}
Towards a real implementation
Scope
Each time you get a service:
 Do you want a new object
  or
 Does the container must return the same object?

$userDef->setGlobal(true);

$feedReaderDef->setGlobal(false);
Service definition
$container = new ServiceContainer(array(               PHP
  'storage' => new ServiceDefinition('FileSessionStorage'),
  'user'    => new ServiceDefinition('User',
                     array(new ServiceReference('storage'))
                  ),
));



<service id="storage" class="FileSessionStorage" />    XML
<service id="user" class="User">
  <constructor_arg type="service" id="storage" />
</service>
Service configuration
                                     Configuration is
<parameter key="storage.class">      decoupled from
  SQLiteSessionStorage                the definition
</parameter>
<parameter key="storage.session_name">
  SESSION_ID
</parameter>


<service id="storage" class="%storage.class%">
  <constructor_arg>
    %storage.session_name%
  </constructor_arg>
</service>
Service configuration


[storage]
  class = SQLiteSessionStorage
  session_name = SESSION_ID


<service id="storage" class="%storage.class%">
  <constructor_arg>
    %storage.session_name%
  </constructor_arg>
</service>
// Access parameters

$sessionName = $container['storage.session_name'];



// Access services

$user = $container->user;
Implementations in PHP
•  Crafty: http://phpcrafty.sourceforge.net/

•  Garden: http://garden.tigris.org/
                            spring
•  Stubbles: http://www.stubbles.net/wiki/Docs/IOC
                                       Google Guice


•  symfony 2 will have its dependency injection
   framework                            spring
Remember, most of the time,
 you don’t need a Container
to use Dependency Injection
You can start to use and benefit
from Dependency Injection today
by implementing it
       in your projects

 by using externals libraries
      that already use DI
without the need of a container
symfony
Zend Framework
 ezComponents

   Doctrine
  Swift Mailer
       …
Let’s add some i18n fun
class User
{
  protected $storage, $i18n;

 function __construct($storage, $i18n)
 {
   $this->storage = $storage;
   $this->i18n = $i18n;
 }

 function setLanguage($language)
 {
   $this->storage->set('language', $language);

     $this->i18n->setLanguage($language);
 }

  // ...
•  It makes sense that the User class depends on a
    Storage class
  –  We can’t use the User object without a Storage


•  It does not make sense to tie the User class to
    the I18n class
  –  We want to be able to use the User with non
     internationalized websites
class User
{
  protected $storage, $i18n;

 function __construct($storage, $i18n = null)
 {
   $this->storage = $storage;
   $this->i18n = $i18n;
 }

 function setLanguage($language)
 {
   $this->storage->set('language', $language);

     if (!is_null($this->i18n))
     {
       $this->i18n->setLanguage($language);
     }
 }
class User
{
  protected $storage;

    function __construct($storage)
    {
      $this->storage = $storage;
    }

    function setI18n($i18n)
    {
      $this->i18n = $i18n;
    }

    function setLanguage($language)
    {
      $this->storage->set('language', $language);

        if (!is_null($this->i18n))
        {
          $this->i18n->setLanguage($language);
        }
    }
}
The Observer pattern
•  The Observer pattern is a way to allow changes in
   an object to update many other objects

•  It is a powerful mechanism to extend applications
    without having to change the object itself

•  Associated words: hook, listener, event, subject,
   …
•  Used by a lot of applications for:
        –  Plugins (Wordpress, …)
        –  Bridges between applications
                •  As a master application:
                        –  Gallery2 (90% events / hooks for user / group create / update / delete, logout,
                           login, ..missing: configuration changes)
                        –  Xaraya (100% events / hooks for user / group create / update / delete,
                           configuration changes, logout, login, ..)
                        –  Wordpress (90% events / hooks for user / update / delete, rewrites, logout,
                           login, ..)
                        –  Drupal (80% maybe?)
                        –  Joomla (100% joomla 1.5; login, logout, create, update, delete user, block,
                           activation, system before and after start)Typo3 (50% maybe?, e.g. no unified create
                           user event / hook)
                •  As a slave application:
                        –  Gallery 2
                        –  Phorum.org
http://codex.gallery2.org/Gallery2:Embedding:Event-Based_Loose-Coupled_Integration
Implementations in PHP
•  PEAR_Dispatcher
  –  http://pear.php.net/package/Event_Dispatcher

•  symfony implementation
  –  http://svn.symfony-project.com/branches/1.1/lib/event/
  –  http://www.symfony-project.org/book/1_1/17-Extending-Symfony
  –  Based on the Cocoa notification center
     •  Simple and powerful
     •  Decoupled from symfony
     •  Simple to use
$i18n = new I18n();
$dispatcher = new sfEventDispatcher();
$listener = array($i18n, 'listenToChangeCultureEvent');
$dispatcher->connect('user.change_language', $listener);

$storage = new FileSessionStorage();
$user = new User($dispatcher, $storage);
class User
{
  protected $storage, $dispatcher;

 function __construct($dispatcher, $storage)
 {
   $this->dispatcher = $dispatcher;
   $this->storage = $storage;
 }

 function setLanguage($language)
 {
   $this->storage->set('language', $language);

     $event = new sfEvent(
        $this,
        'user.change_language',
        array('language' => $language)
     );

     $this->dispatcher->notify($event);
 }
Notifiers          Dispatcher             Listeners

                                                 I18n listens
1                                          to user.change_culture

       User notifies           Calls           I18n callback
2   user.change_culture    all listeners          is called
The User object knows nothing about the I18n one
The I18n object knows nothing about the User one

They communicate through the Dispatcher object

Any class can listen to the ‘user.change_culture’
  event and acts accordingly
Notifiers          Dispatcher             Listeners

                                                 I18n listens
1                                          to user.change_culture
                                              Your class listens
                                           to user.change_culture

       User notifies           Calls           I18n callback
2   user.change_culture    all listeners          is called
                                             Your class callback
                                                  is called
Notifiers          Dispatcher




   User notifies       Calls
user.change_culture   nothing




                            Very small
                             overhead
In this example, the implementation is very simple
  No interface to implement
  No need to create an event class for each event
  An event is just
    a unique identifier (user.change_culture)
   some conventions (parameter names)
Advantages
  very simple to use
  easy to add new arguments to the listener
  very fast
  very easy to add a new event, just notify it with a
   unique name
Disadvantages
 the contract between the listener and the notifier
   is quite loose
Implementation
function connect($name, $listener)
{
  if (!isset($this->listeners[$name]))
  {
    $this->listeners[$name] = array();
  }

    $this->listeners[$name][] = $listener;
}

function notify(sfEvent $event)
{
  if (!isset($this->listeners[$name]))
  {
    foreach ($this->listeners[$event->getName()] as $listener)
    {
      call_user_func($listener, $event);
    }
  }
}
•  3 types of notification
  –  Notify : all listeners are called in turn, no feedback to
     the notifier
     •  Logging, …
  –  Notify Until : all listeners are called until one has
     « processed » the event. The listener that has
     processed the event can return something to the
     caller
     •  Exceptions, …
  –  Filter : Each listener filter a given value and can
     change it. The filtered value is returned to the caller
     •  HTML content, …
Questions?

            Contact
       Fabien Potencier
 fabien.potencier@sensio.com



  http://www.sensiolabs.com/
http://www.symfony-project.org/

Contenu connexe

Tendances

Vector class in C++
Vector class in C++Vector class in C++
Vector class in C++Jawad Khan
 
ANSI-SPARC Architecture - (3-Tier Architecture)
ANSI-SPARC Architecture - (3-Tier Architecture)ANSI-SPARC Architecture - (3-Tier Architecture)
ANSI-SPARC Architecture - (3-Tier Architecture)Yaksh Jethva
 
Introduction to SQL
Introduction to SQLIntroduction to SQL
Introduction to SQLRam Kedem
 
Object Oriented Programming Using C++
Object Oriented Programming Using C++Object Oriented Programming Using C++
Object Oriented Programming Using C++Muhammad Waqas
 
Common dialog control
Common dialog controlCommon dialog control
Common dialog controlSoumya Vijoy
 
Bootcamp sql fundamental
Bootcamp sql fundamentalBootcamp sql fundamental
Bootcamp sql fundamentalvarunbhatt23
 
Classes, Objects and Method - Object Oriented Programming with Java
Classes, Objects and Method - Object Oriented Programming with JavaClasses, Objects and Method - Object Oriented Programming with Java
Classes, Objects and Method - Object Oriented Programming with JavaRadhika Talaviya
 
Object oriented programming concepts
Object oriented programming conceptsObject oriented programming concepts
Object oriented programming conceptsrahuld115
 
JAVA SCRIPT
JAVA SCRIPTJAVA SCRIPT
JAVA SCRIPTGo4Guru
 
Introduction to Data Structures & Algorithms
Introduction to Data Structures & AlgorithmsIntroduction to Data Structures & Algorithms
Introduction to Data Structures & AlgorithmsAfaq Mansoor Khan
 
2. Classes | Object Oriented Programming in JavaScript | ES6 | JavaScript
2. Classes | Object Oriented Programming in JavaScript | ES6 | JavaScript2. Classes | Object Oriented Programming in JavaScript | ES6 | JavaScript
2. Classes | Object Oriented Programming in JavaScript | ES6 | JavaScriptpcnmtutorials
 
Object-oriented Programming-with C#
Object-oriented Programming-with C#Object-oriented Programming-with C#
Object-oriented Programming-with C#Doncho Minkov
 

Tendances (20)

Vector class in C++
Vector class in C++Vector class in C++
Vector class in C++
 
ANSI-SPARC Architecture - (3-Tier Architecture)
ANSI-SPARC Architecture - (3-Tier Architecture)ANSI-SPARC Architecture - (3-Tier Architecture)
ANSI-SPARC Architecture - (3-Tier Architecture)
 
Introduction to-sql
Introduction to-sqlIntroduction to-sql
Introduction to-sql
 
DBMS Part-4.pdf
DBMS Part-4.pdfDBMS Part-4.pdf
DBMS Part-4.pdf
 
Joins in SQL
Joins in SQLJoins in SQL
Joins in SQL
 
Introduction to SQL
Introduction to SQLIntroduction to SQL
Introduction to SQL
 
Object Oriented Programming Using C++
Object Oriented Programming Using C++Object Oriented Programming Using C++
Object Oriented Programming Using C++
 
Common dialog control
Common dialog controlCommon dialog control
Common dialog control
 
DBMS unit-3.pdf
DBMS unit-3.pdfDBMS unit-3.pdf
DBMS unit-3.pdf
 
Bootcamp sql fundamental
Bootcamp sql fundamentalBootcamp sql fundamental
Bootcamp sql fundamental
 
Classes, Objects and Method - Object Oriented Programming with Java
Classes, Objects and Method - Object Oriented Programming with JavaClasses, Objects and Method - Object Oriented Programming with Java
Classes, Objects and Method - Object Oriented Programming with Java
 
Object oriented programming concepts
Object oriented programming conceptsObject oriented programming concepts
Object oriented programming concepts
 
JAVA SCRIPT
JAVA SCRIPTJAVA SCRIPT
JAVA SCRIPT
 
Introduction to Data Structures & Algorithms
Introduction to Data Structures & AlgorithmsIntroduction to Data Structures & Algorithms
Introduction to Data Structures & Algorithms
 
Sql injection
Sql injectionSql injection
Sql injection
 
Javascript
JavascriptJavascript
Javascript
 
Dictionaries in Python
Dictionaries in PythonDictionaries in Python
Dictionaries in Python
 
2. Classes | Object Oriented Programming in JavaScript | ES6 | JavaScript
2. Classes | Object Oriented Programming in JavaScript | ES6 | JavaScript2. Classes | Object Oriented Programming in JavaScript | ES6 | JavaScript
2. Classes | Object Oriented Programming in JavaScript | ES6 | JavaScript
 
Object-oriented Programming-with C#
Object-oriented Programming-with C#Object-oriented Programming-with C#
Object-oriented Programming-with C#
 
Introduction to c#
Introduction to c#Introduction to c#
Introduction to c#
 

En vedette

Decoupling Your HTML, CSS & JavaScript
Decoupling Your HTML, CSS & JavaScriptDecoupling Your HTML, CSS & JavaScript
Decoupling Your HTML, CSS & JavaScriptTomislav Mesić
 
C4DM Seminar 2016-07-12: Brecht De Man
C4DM Seminar 2016-07-12: Brecht De ManC4DM Seminar 2016-07-12: Brecht De Man
C4DM Seminar 2016-07-12: Brecht De Mansebastianewert
 
Web Services: Encapsulation, Reusability, and Simplicity
Web Services: Encapsulation, Reusability, and SimplicityWeb Services: Encapsulation, Reusability, and Simplicity
Web Services: Encapsulation, Reusability, and Simplicityhannonhill
 
Ciklum Odessa PHP Saturday - Dependency Injection
Ciklum Odessa PHP Saturday - Dependency InjectionCiklum Odessa PHP Saturday - Dependency Injection
Ciklum Odessa PHP Saturday - Dependency InjectionPavel Voznenko
 
Dependency Injection. Как сказать всё, не говоря ничего. Кожевников Дмитрий. ...
Dependency Injection. Как сказать всё, не говоря ничего. Кожевников Дмитрий. ...Dependency Injection. Как сказать всё, не говоря ничего. Кожевников Дмитрий. ...
Dependency Injection. Как сказать всё, не говоря ничего. Кожевников Дмитрий. ...Dev2Dev
 
Dependency Injection Pattern in JavaScript, Speakers' Corner by Evgeny Dmitri...
Dependency Injection Pattern in JavaScript, Speakers' Corner by Evgeny Dmitri...Dependency Injection Pattern in JavaScript, Speakers' Corner by Evgeny Dmitri...
Dependency Injection Pattern in JavaScript, Speakers' Corner by Evgeny Dmitri...Ciklum Minsk
 
Dependency Injection in PHP
Dependency Injection in PHPDependency Injection in PHP
Dependency Injection in PHPKacper Gunia
 
Measuring maintainability; software metrics explained
Measuring maintainability; software metrics explainedMeasuring maintainability; software metrics explained
Measuring maintainability; software metrics explainedDennis de Greef
 
Dependency Injection with PHP 5.3
Dependency Injection with PHP 5.3Dependency Injection with PHP 5.3
Dependency Injection with PHP 5.3Fabien Potencier
 
Тестирование безопасности: PHP инъекция
Тестирование безопасности: PHP инъекцияТестирование безопасности: PHP инъекция
Тестирование безопасности: PHP инъекцияSQALab
 
What Makes Great Infographics
What Makes Great InfographicsWhat Makes Great Infographics
What Makes Great InfographicsSlideShare
 
Masters of SlideShare
Masters of SlideShareMasters of SlideShare
Masters of SlideShareKapost
 
STOP! VIEW THIS! 10-Step Checklist When Uploading to Slideshare
STOP! VIEW THIS! 10-Step Checklist When Uploading to SlideshareSTOP! VIEW THIS! 10-Step Checklist When Uploading to Slideshare
STOP! VIEW THIS! 10-Step Checklist When Uploading to SlideshareEmpowered Presentations
 
10 Ways to Win at SlideShare SEO & Presentation Optimization
10 Ways to Win at SlideShare SEO & Presentation Optimization10 Ways to Win at SlideShare SEO & Presentation Optimization
10 Ways to Win at SlideShare SEO & Presentation OptimizationOneupweb
 
How To Get More From SlideShare - Super-Simple Tips For Content Marketing
How To Get More From SlideShare - Super-Simple Tips For Content MarketingHow To Get More From SlideShare - Super-Simple Tips For Content Marketing
How To Get More From SlideShare - Super-Simple Tips For Content MarketingContent Marketing Institute
 
How to Make Awesome SlideShares: Tips & Tricks
How to Make Awesome SlideShares: Tips & TricksHow to Make Awesome SlideShares: Tips & Tricks
How to Make Awesome SlideShares: Tips & TricksSlideShare
 

En vedette (17)

Decoupling Your HTML, CSS & JavaScript
Decoupling Your HTML, CSS & JavaScriptDecoupling Your HTML, CSS & JavaScript
Decoupling Your HTML, CSS & JavaScript
 
C4DM Seminar 2016-07-12: Brecht De Man
C4DM Seminar 2016-07-12: Brecht De ManC4DM Seminar 2016-07-12: Brecht De Man
C4DM Seminar 2016-07-12: Brecht De Man
 
Web Services: Encapsulation, Reusability, and Simplicity
Web Services: Encapsulation, Reusability, and SimplicityWeb Services: Encapsulation, Reusability, and Simplicity
Web Services: Encapsulation, Reusability, and Simplicity
 
Ciklum Odessa PHP Saturday - Dependency Injection
Ciklum Odessa PHP Saturday - Dependency InjectionCiklum Odessa PHP Saturday - Dependency Injection
Ciklum Odessa PHP Saturday - Dependency Injection
 
Dependency Injection. Как сказать всё, не говоря ничего. Кожевников Дмитрий. ...
Dependency Injection. Как сказать всё, не говоря ничего. Кожевников Дмитрий. ...Dependency Injection. Как сказать всё, не говоря ничего. Кожевников Дмитрий. ...
Dependency Injection. Как сказать всё, не говоря ничего. Кожевников Дмитрий. ...
 
Dependency Injection Pattern in JavaScript, Speakers' Corner by Evgeny Dmitri...
Dependency Injection Pattern in JavaScript, Speakers' Corner by Evgeny Dmitri...Dependency Injection Pattern in JavaScript, Speakers' Corner by Evgeny Dmitri...
Dependency Injection Pattern in JavaScript, Speakers' Corner by Evgeny Dmitri...
 
Dependency Injection in PHP
Dependency Injection in PHPDependency Injection in PHP
Dependency Injection in PHP
 
Measuring maintainability; software metrics explained
Measuring maintainability; software metrics explainedMeasuring maintainability; software metrics explained
Measuring maintainability; software metrics explained
 
Dependency Injection with PHP 5.3
Dependency Injection with PHP 5.3Dependency Injection with PHP 5.3
Dependency Injection with PHP 5.3
 
Тестирование безопасности: PHP инъекция
Тестирование безопасности: PHP инъекцияТестирование безопасности: PHP инъекция
Тестирование безопасности: PHP инъекция
 
What Makes Great Infographics
What Makes Great InfographicsWhat Makes Great Infographics
What Makes Great Infographics
 
Masters of SlideShare
Masters of SlideShareMasters of SlideShare
Masters of SlideShare
 
STOP! VIEW THIS! 10-Step Checklist When Uploading to Slideshare
STOP! VIEW THIS! 10-Step Checklist When Uploading to SlideshareSTOP! VIEW THIS! 10-Step Checklist When Uploading to Slideshare
STOP! VIEW THIS! 10-Step Checklist When Uploading to Slideshare
 
You Suck At PowerPoint!
You Suck At PowerPoint!You Suck At PowerPoint!
You Suck At PowerPoint!
 
10 Ways to Win at SlideShare SEO & Presentation Optimization
10 Ways to Win at SlideShare SEO & Presentation Optimization10 Ways to Win at SlideShare SEO & Presentation Optimization
10 Ways to Win at SlideShare SEO & Presentation Optimization
 
How To Get More From SlideShare - Super-Simple Tips For Content Marketing
How To Get More From SlideShare - Super-Simple Tips For Content MarketingHow To Get More From SlideShare - Super-Simple Tips For Content Marketing
How To Get More From SlideShare - Super-Simple Tips For Content Marketing
 
How to Make Awesome SlideShares: Tips & Tricks
How to Make Awesome SlideShares: Tips & TricksHow to Make Awesome SlideShares: Tips & Tricks
How to Make Awesome SlideShares: Tips & Tricks
 

Similaire à Decouple Your Code For Reusability (International PHP Conference / IPC 2008)

Dependency Injection IPC 201
Dependency Injection IPC 201Dependency Injection IPC 201
Dependency Injection IPC 201Fabien Potencier
 
Dependency injection - phpday 2010
Dependency injection - phpday 2010Dependency injection - phpday 2010
Dependency injection - phpday 2010Fabien Potencier
 
Dependency Injection - ConFoo 2010
Dependency Injection - ConFoo 2010Dependency Injection - ConFoo 2010
Dependency Injection - ConFoo 2010Fabien Potencier
 
Dependency Injection with PHP and PHP 5.3
Dependency Injection with PHP and PHP 5.3Dependency Injection with PHP and PHP 5.3
Dependency Injection with PHP and PHP 5.3Fabien Potencier
 
Dependency injection in PHP 5.3/5.4
Dependency injection in PHP 5.3/5.4Dependency injection in PHP 5.3/5.4
Dependency injection in PHP 5.3/5.4Fabien Potencier
 
Dependency injection-zendcon-2010
Dependency injection-zendcon-2010Dependency injection-zendcon-2010
Dependency injection-zendcon-2010Fabien Potencier
 
Dependency injection in Drupal 8
Dependency injection in Drupal 8Dependency injection in Drupal 8
Dependency injection in Drupal 8Alexei Gorobets
 
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
 
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
 
Dependency Injection
Dependency InjectionDependency Injection
Dependency InjectionRifat Nabi
 
Doctrine MongoDB Object Document Mapper
Doctrine MongoDB Object Document MapperDoctrine MongoDB Object Document Mapper
Doctrine MongoDB Object Document MapperJonathan Wage
 
Symfony2 from the Trenches
Symfony2 from the TrenchesSymfony2 from the Trenches
Symfony2 from the TrenchesJonathan Wage
 
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
 
Modularity and Layered Data Model
Modularity and Layered Data ModelModularity and Layered Data Model
Modularity and Layered Data ModelAttila Jenei
 
The Zen of Lithium
The Zen of LithiumThe Zen of Lithium
The Zen of LithiumNate Abele
 

Similaire à Decouple Your Code For Reusability (International PHP Conference / IPC 2008) (20)

Dependency Injection IPC 201
Dependency Injection IPC 201Dependency Injection IPC 201
Dependency Injection IPC 201
 
Dependency injection - phpday 2010
Dependency injection - phpday 2010Dependency injection - phpday 2010
Dependency injection - phpday 2010
 
Dependency Injection - ConFoo 2010
Dependency Injection - ConFoo 2010Dependency Injection - ConFoo 2010
Dependency Injection - ConFoo 2010
 
Dependency Injection
Dependency InjectionDependency Injection
Dependency Injection
 
Dependency Injection with PHP and PHP 5.3
Dependency Injection with PHP and PHP 5.3Dependency Injection with PHP and PHP 5.3
Dependency Injection with PHP and PHP 5.3
 
Dependency injection in PHP 5.3/5.4
Dependency injection in PHP 5.3/5.4Dependency injection in PHP 5.3/5.4
Dependency injection in PHP 5.3/5.4
 
Dependency injection-zendcon-2010
Dependency injection-zendcon-2010Dependency injection-zendcon-2010
Dependency injection-zendcon-2010
 
Dependency injection in Drupal 8
Dependency injection in Drupal 8Dependency injection in Drupal 8
Dependency injection in Drupal 8
 
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)
 
BEAR DI
BEAR DIBEAR DI
BEAR DI
 
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
 
Dependency Injection
Dependency InjectionDependency Injection
Dependency Injection
 
The IoC Hydra
The IoC HydraThe IoC Hydra
The IoC Hydra
 
Doctrine MongoDB Object Document Mapper
Doctrine MongoDB Object Document MapperDoctrine MongoDB Object Document Mapper
Doctrine MongoDB Object Document Mapper
 
PHP pod mikroskopom
PHP pod mikroskopomPHP pod mikroskopom
PHP pod mikroskopom
 
Symfony2 from the Trenches
Symfony2 from the TrenchesSymfony2 from the Trenches
Symfony2 from the Trenches
 
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...
 
Modularity and Layered Data Model
Modularity and Layered Data ModelModularity and Layered Data Model
Modularity and Layered Data Model
 
The Zen of Lithium
The Zen of LithiumThe Zen of Lithium
The Zen of Lithium
 

Plus de Fabien Potencier

Plus de Fabien Potencier (20)

Varnish
VarnishVarnish
Varnish
 
Look beyond PHP
Look beyond PHPLook beyond PHP
Look beyond PHP
 
Caching on the Edge
Caching on the EdgeCaching on the Edge
Caching on the Edge
 
Design patterns revisited with PHP 5.3
Design patterns revisited with PHP 5.3Design patterns revisited with PHP 5.3
Design patterns revisited with PHP 5.3
 
The state of Symfony2 - SymfonyDay 2010
The state of Symfony2 - SymfonyDay 2010The state of Symfony2 - SymfonyDay 2010
The state of Symfony2 - SymfonyDay 2010
 
PhpBB meets Symfony2
PhpBB meets Symfony2PhpBB meets Symfony2
PhpBB meets Symfony2
 
Symfony2 - WebExpo 2010
Symfony2 - WebExpo 2010Symfony2 - WebExpo 2010
Symfony2 - WebExpo 2010
 
Symfony2 - WebExpo 2010
Symfony2 - WebExpo 2010Symfony2 - WebExpo 2010
Symfony2 - WebExpo 2010
 
Symfony2 - OSIDays 2010
Symfony2 - OSIDays 2010Symfony2 - OSIDays 2010
Symfony2 - OSIDays 2010
 
Caching on the Edge with Symfony2
Caching on the Edge with Symfony2Caching on the Edge with Symfony2
Caching on the Edge with Symfony2
 
Unit and Functional Testing with Symfony2
Unit and Functional Testing with Symfony2Unit and Functional Testing with Symfony2
Unit and Functional Testing with Symfony2
 
News of the Symfony2 World
News of the Symfony2 WorldNews of the Symfony2 World
News of the Symfony2 World
 
Symfony Components
Symfony ComponentsSymfony Components
Symfony Components
 
PHP 5.3 in practice
PHP 5.3 in practicePHP 5.3 in practice
PHP 5.3 in practice
 
Symfony2 revealed
Symfony2 revealedSymfony2 revealed
Symfony2 revealed
 
Symfony Components 2.0 on PHP 5.3
Symfony Components 2.0 on PHP 5.3Symfony Components 2.0 on PHP 5.3
Symfony Components 2.0 on PHP 5.3
 
Playing With PHP 5.3
Playing With PHP 5.3Playing With PHP 5.3
Playing With PHP 5.3
 
Symfony 2.0 on PHP 5.3
Symfony 2.0 on PHP 5.3Symfony 2.0 on PHP 5.3
Symfony 2.0 on PHP 5.3
 
Symfony2 San Francisco Meetup 2009
Symfony2 San Francisco Meetup 2009Symfony2 San Francisco Meetup 2009
Symfony2 San Francisco Meetup 2009
 
Symfony And Zend Framework Together 2009
Symfony And Zend Framework Together 2009Symfony And Zend Framework Together 2009
Symfony And Zend Framework Together 2009
 

Dernier

WSO2CONMay2024OpenSourceConferenceDebrief.pptx
WSO2CONMay2024OpenSourceConferenceDebrief.pptxWSO2CONMay2024OpenSourceConferenceDebrief.pptx
WSO2CONMay2024OpenSourceConferenceDebrief.pptxJennifer Lim
 
Introduction to FDO and How It works Applications _ Richard at FIDO Alliance.pdf
Introduction to FDO and How It works Applications _ Richard at FIDO Alliance.pdfIntroduction to FDO and How It works Applications _ Richard at FIDO Alliance.pdf
Introduction to FDO and How It works Applications _ Richard at FIDO Alliance.pdfFIDO Alliance
 
Custom Approval Process: A New Perspective, Pavel Hrbacek & Anindya Halder
Custom Approval Process: A New Perspective, Pavel Hrbacek & Anindya HalderCustom Approval Process: A New Perspective, Pavel Hrbacek & Anindya Halder
Custom Approval Process: A New Perspective, Pavel Hrbacek & Anindya HalderCzechDreamin
 
Demystifying gRPC in .Net by John Staveley
Demystifying gRPC in .Net by John StaveleyDemystifying gRPC in .Net by John Staveley
Demystifying gRPC in .Net by John StaveleyJohn Staveley
 
Designing for Hardware Accessibility at Comcast
Designing for Hardware Accessibility at ComcastDesigning for Hardware Accessibility at Comcast
Designing for Hardware Accessibility at ComcastUXDXConf
 
AI presentation and introduction - Retrieval Augmented Generation RAG 101
AI presentation and introduction - Retrieval Augmented Generation RAG 101AI presentation and introduction - Retrieval Augmented Generation RAG 101
AI presentation and introduction - Retrieval Augmented Generation RAG 101vincent683379
 
Connecting the Dots in Product Design at KAYAK
Connecting the Dots in Product Design at KAYAKConnecting the Dots in Product Design at KAYAK
Connecting the Dots in Product Design at KAYAKUXDXConf
 
Optimizing NoSQL Performance Through Observability
Optimizing NoSQL Performance Through ObservabilityOptimizing NoSQL Performance Through Observability
Optimizing NoSQL Performance Through ObservabilityScyllaDB
 
Secure Zero Touch enabled Edge compute with Dell NativeEdge via FDO _ Brad at...
Secure Zero Touch enabled Edge compute with Dell NativeEdge via FDO _ Brad at...Secure Zero Touch enabled Edge compute with Dell NativeEdge via FDO _ Brad at...
Secure Zero Touch enabled Edge compute with Dell NativeEdge via FDO _ Brad at...FIDO Alliance
 
Linux Foundation Edge _ Overview of FDO Software Components _ Randy at Intel.pdf
Linux Foundation Edge _ Overview of FDO Software Components _ Randy at Intel.pdfLinux Foundation Edge _ Overview of FDO Software Components _ Randy at Intel.pdf
Linux Foundation Edge _ Overview of FDO Software Components _ Randy at Intel.pdfFIDO Alliance
 
Salesforce Adoption – Metrics, Methods, and Motivation, Antone Kom
Salesforce Adoption – Metrics, Methods, and Motivation, Antone KomSalesforce Adoption – Metrics, Methods, and Motivation, Antone Kom
Salesforce Adoption – Metrics, Methods, and Motivation, Antone KomCzechDreamin
 
The Value of Certifying Products for FDO _ Paul at FIDO Alliance.pdf
The Value of Certifying Products for FDO _ Paul at FIDO Alliance.pdfThe Value of Certifying Products for FDO _ Paul at FIDO Alliance.pdf
The Value of Certifying Products for FDO _ Paul at FIDO Alliance.pdfFIDO Alliance
 
ASRock Industrial FDO Solutions in Action for Industrial Edge AI _ Kenny at A...
ASRock Industrial FDO Solutions in Action for Industrial Edge AI _ Kenny at A...ASRock Industrial FDO Solutions in Action for Industrial Edge AI _ Kenny at A...
ASRock Industrial FDO Solutions in Action for Industrial Edge AI _ Kenny at A...FIDO Alliance
 
Powerful Start- the Key to Project Success, Barbara Laskowska
Powerful Start- the Key to Project Success, Barbara LaskowskaPowerful Start- the Key to Project Success, Barbara Laskowska
Powerful Start- the Key to Project Success, Barbara LaskowskaCzechDreamin
 
Free and Effective: Making Flows Publicly Accessible, Yumi Ibrahimzade
Free and Effective: Making Flows Publicly Accessible, Yumi IbrahimzadeFree and Effective: Making Flows Publicly Accessible, Yumi Ibrahimzade
Free and Effective: Making Flows Publicly Accessible, Yumi IbrahimzadeCzechDreamin
 
Structuring Teams and Portfolios for Success
Structuring Teams and Portfolios for SuccessStructuring Teams and Portfolios for Success
Structuring Teams and Portfolios for SuccessUXDXConf
 
Syngulon - Selection technology May 2024.pdf
Syngulon - Selection technology May 2024.pdfSyngulon - Selection technology May 2024.pdf
Syngulon - Selection technology May 2024.pdfSyngulon
 
Top 10 Symfony Development Companies 2024
Top 10 Symfony Development Companies 2024Top 10 Symfony Development Companies 2024
Top 10 Symfony Development Companies 2024TopCSSGallery
 
A Business-Centric Approach to Design System Strategy
A Business-Centric Approach to Design System StrategyA Business-Centric Approach to Design System Strategy
A Business-Centric Approach to Design System StrategyUXDXConf
 
Agentic RAG What it is its types applications and implementation.pdf
Agentic RAG What it is its types applications and implementation.pdfAgentic RAG What it is its types applications and implementation.pdf
Agentic RAG What it is its types applications and implementation.pdfChristopherTHyatt
 

Dernier (20)

WSO2CONMay2024OpenSourceConferenceDebrief.pptx
WSO2CONMay2024OpenSourceConferenceDebrief.pptxWSO2CONMay2024OpenSourceConferenceDebrief.pptx
WSO2CONMay2024OpenSourceConferenceDebrief.pptx
 
Introduction to FDO and How It works Applications _ Richard at FIDO Alliance.pdf
Introduction to FDO and How It works Applications _ Richard at FIDO Alliance.pdfIntroduction to FDO and How It works Applications _ Richard at FIDO Alliance.pdf
Introduction to FDO and How It works Applications _ Richard at FIDO Alliance.pdf
 
Custom Approval Process: A New Perspective, Pavel Hrbacek & Anindya Halder
Custom Approval Process: A New Perspective, Pavel Hrbacek & Anindya HalderCustom Approval Process: A New Perspective, Pavel Hrbacek & Anindya Halder
Custom Approval Process: A New Perspective, Pavel Hrbacek & Anindya Halder
 
Demystifying gRPC in .Net by John Staveley
Demystifying gRPC in .Net by John StaveleyDemystifying gRPC in .Net by John Staveley
Demystifying gRPC in .Net by John Staveley
 
Designing for Hardware Accessibility at Comcast
Designing for Hardware Accessibility at ComcastDesigning for Hardware Accessibility at Comcast
Designing for Hardware Accessibility at Comcast
 
AI presentation and introduction - Retrieval Augmented Generation RAG 101
AI presentation and introduction - Retrieval Augmented Generation RAG 101AI presentation and introduction - Retrieval Augmented Generation RAG 101
AI presentation and introduction - Retrieval Augmented Generation RAG 101
 
Connecting the Dots in Product Design at KAYAK
Connecting the Dots in Product Design at KAYAKConnecting the Dots in Product Design at KAYAK
Connecting the Dots in Product Design at KAYAK
 
Optimizing NoSQL Performance Through Observability
Optimizing NoSQL Performance Through ObservabilityOptimizing NoSQL Performance Through Observability
Optimizing NoSQL Performance Through Observability
 
Secure Zero Touch enabled Edge compute with Dell NativeEdge via FDO _ Brad at...
Secure Zero Touch enabled Edge compute with Dell NativeEdge via FDO _ Brad at...Secure Zero Touch enabled Edge compute with Dell NativeEdge via FDO _ Brad at...
Secure Zero Touch enabled Edge compute with Dell NativeEdge via FDO _ Brad at...
 
Linux Foundation Edge _ Overview of FDO Software Components _ Randy at Intel.pdf
Linux Foundation Edge _ Overview of FDO Software Components _ Randy at Intel.pdfLinux Foundation Edge _ Overview of FDO Software Components _ Randy at Intel.pdf
Linux Foundation Edge _ Overview of FDO Software Components _ Randy at Intel.pdf
 
Salesforce Adoption – Metrics, Methods, and Motivation, Antone Kom
Salesforce Adoption – Metrics, Methods, and Motivation, Antone KomSalesforce Adoption – Metrics, Methods, and Motivation, Antone Kom
Salesforce Adoption – Metrics, Methods, and Motivation, Antone Kom
 
The Value of Certifying Products for FDO _ Paul at FIDO Alliance.pdf
The Value of Certifying Products for FDO _ Paul at FIDO Alliance.pdfThe Value of Certifying Products for FDO _ Paul at FIDO Alliance.pdf
The Value of Certifying Products for FDO _ Paul at FIDO Alliance.pdf
 
ASRock Industrial FDO Solutions in Action for Industrial Edge AI _ Kenny at A...
ASRock Industrial FDO Solutions in Action for Industrial Edge AI _ Kenny at A...ASRock Industrial FDO Solutions in Action for Industrial Edge AI _ Kenny at A...
ASRock Industrial FDO Solutions in Action for Industrial Edge AI _ Kenny at A...
 
Powerful Start- the Key to Project Success, Barbara Laskowska
Powerful Start- the Key to Project Success, Barbara LaskowskaPowerful Start- the Key to Project Success, Barbara Laskowska
Powerful Start- the Key to Project Success, Barbara Laskowska
 
Free and Effective: Making Flows Publicly Accessible, Yumi Ibrahimzade
Free and Effective: Making Flows Publicly Accessible, Yumi IbrahimzadeFree and Effective: Making Flows Publicly Accessible, Yumi Ibrahimzade
Free and Effective: Making Flows Publicly Accessible, Yumi Ibrahimzade
 
Structuring Teams and Portfolios for Success
Structuring Teams and Portfolios for SuccessStructuring Teams and Portfolios for Success
Structuring Teams and Portfolios for Success
 
Syngulon - Selection technology May 2024.pdf
Syngulon - Selection technology May 2024.pdfSyngulon - Selection technology May 2024.pdf
Syngulon - Selection technology May 2024.pdf
 
Top 10 Symfony Development Companies 2024
Top 10 Symfony Development Companies 2024Top 10 Symfony Development Companies 2024
Top 10 Symfony Development Companies 2024
 
A Business-Centric Approach to Design System Strategy
A Business-Centric Approach to Design System StrategyA Business-Centric Approach to Design System Strategy
A Business-Centric Approach to Design System Strategy
 
Agentic RAG What it is its types applications and implementation.pdf
Agentic RAG What it is its types applications and implementation.pdfAgentic RAG What it is its types applications and implementation.pdf
Agentic RAG What it is its types applications and implementation.pdf
 

Decouple Your Code For Reusability (International PHP Conference / IPC 2008)

  • 1. Decouple your PHP code for reusability Fabien Potencier
  • 2. Who am I? •  Founder of Sensio –  Web Agency –  Since 1998 –  About 50 people –  Open-Source Specialists –  Big corporate customers •  Creator and lead developer of symfony –  PHP framework
  • 3. Coupling? Coupling is the degree to which each program module relies on each one of the other modules. http://en.wikipedia.org/wiki/Coupling_(computer_science)
  • 4. Low Coupling With low coupling, a change in one module will not require a change in the implementation of another module.
  • 5. Low Coupling A module can interact with another module but through a stable interface
  • 6. Why does it matter?
  • 7. Testability The ability to instantiate a class in a test demonstrates the level of decoupling of your code
  • 8. Readability Code spends more time being read and maintained than being created
  • 9. Maintainability A change "here" must not cause a problem "there"
  • 10. Extensibility Smaller loosely coupled modules makes your code easier to extend
  • 12. The programming world is evolving fast… very fast But the ultimate goal of these changes is the same
  • 13. Build better tools to avoid reinventing the wheel Build on existing code / work / libraries Specialize for your specific needs That’s why Open-Source wins
  • 14. Better tools are possible because we base our work on existing work We learn from other projects We can adopt their ideas We can make them better This is the process of evolution
  • 15. Reusability Configuration Customization / Extension Documentation / Support
  • 17. A real world « web » example
  • 18. In most web applications, you need to manage the user preferences –  The user language –  Whether the user is authenticated or not –  The user credentials –  …
  • 19. This can be done with a User object – setLanguage(), getLanguage() – setAuthenticated(), isAuthenticated() – addCredential(), hasCredential() – ...
  • 20. The User information need to be persisted between HTTP requests We use the PHP session for the Storage
  • 21. class SessionStorage { function __construct($cookieName = 'PHP_SESS_ID') { session_name($cookieName); session_start(); } function set($key, $value) { $_SESSION[$key] = $value; } // ... }
  • 22. class User { protected $storage; function __construct() { $this->storage = new SessionStorage(); } function setLanguage($language) { $this->storage->set('language', $language); } // ... } $user = new User();
  • 23. I want to change the session cookie name
  • 24. class User { protected $storage; Hardcode it in the User class function __construct() { $this->storage = new SessionStorage('SESSION_ID'); } function setLanguage($language) { $this->storage->set('language', $language); } // ... } $user = new User();
  • 25. class User { protected $storage; Add a global configuration? function __construct() { $this->storage = new SessionStorage(STORAGE_SESSION_NAME); } } define('STORAGE_SESSION_NAME', 'SESSION_ID'); $user = new User();
  • 26. Configure via class User User? { protected $storage; function __construct($sessionName) { $this->storage = new SessionStorage($sessionName); } } $user = new User('SESSION_ID');
  • 27. Configure with class User an array { protected $storage; function __construct($storageOptions) { $this->storage = new SessionStorage($storageOptions['session_name']); $user = new User( array('session_name' => 'SESSION_ID') );
  • 28. I want to change the session storage engine Filesystem MySQL SQLite …
  • 29. Use a global class User registry object? { protected $storage; function __construct() { $this->storage = Registry::get('session_storage'); } } $storage = new SessionStorage(); Registry::set('session_storage', $storage); $user = new User();
  • 30. The User now depends on the Registry
  • 31. Instead of harcoding the Storage dependency in the User class Inject the Storage dependency in the User object
  • 32. Constructor class User argument { protected $storage; function __construct($storage) { $this->storage = $storage; } } $storage = new SessionStorage('SESSION_ID'); $user = new User($storage);
  • 33. Use different Storage strategies
  • 34. class User { protected $storage; function __construct($storage) Use a different { Storage engine $this->storage = $storage; } } $storage = new MySQLSessionStorage('SESSION_ID'); $user = new User($storage);
  • 36. class User { protected $storage; function __construct($storage) Configuration { is natural $this->storage = $storage; } } $storage = new MySQLSessionStorage('SESSION_ID'); $user = new User($storage);
  • 37. Wrap third-party classes (Interface / Adapter)
  • 38. class User { protected $storage; function __construct(ISessionStorage $storage) { $this->storage = $storage; } Add an } interface interface ISessionStorage { function get($key); function set($key, $value); }
  • 39. Mock the Storage object (for testing)
  • 40. class User { protected $storage; function __construct(ISessionStorage $storage) { $this->storage = $storage; } } class SessionStorageForTests implements ISessionStorage { protected $data function set($key, $value) { Mock the self::$data[$key] = $value; Session } }
  • 41. Use different Storage strategies Configuration becomes natural Wrap third-party classes (Interface / Adapter) Mock the Storage object (for testing) Easy without changing the User class
  • 43. « Dependency Injection is where components are given their dependencies through their constructors, methods, or directly into fields. » http://www.picocontainer.org/injection.html
  • 44. $storage = new SessionStorage(); // constructor injection $user = new User($storage); // setter injection $user = new User(); $user->setStorage($storage); // property injection $user = new User(); $user->storage = $storage;
  • 45. A slightly more complex web example
  • 46. $request = new WebRequest(); $response = new WebResponse(); $storage = new FileSessionStorage('SESSION_ID'); $user = new User($storage); $cache = new FileCache( array('dir' => dirname(__FILE__).'/cache') ); $routing = new Routing($cache);
  • 47. class Application { function __construct() { $this->request = new WebRequest(); $this->response = new WebResponse(); $storage = new FileSessionStorage('SESSION_ID'); $this->user = new User($storage); $cache = new FileCache( array('dir' => dirname(__FILE__).'/cache') ); $this->routing = new Routing($cache); } } $application = new Application();
  • 49. class Application { function __construct() { $request = new WebRequest(); $response = new WebResponse(); $storage = new FileSessionStorage('SESSION_ID'); $user = new User($storage); $cache = new FileCache( array('dir' => dirname(__FILE__).'/cache') ); $routing = new Routing($cache); } } $application = new Application();
  • 50. We need a Container Objects and relationships description Configuration Instantiation
  • 51. Service description $storageDef = new ServiceDefinition( 'FileSessionStorage' ); Class name
  • 52. $storageDef = new ServiceDefinition( 'FileSessionStorage', array('SESSION_ID') ); Arguments to pass to the constructor
  • 53. $container = new ServiceContainer(array( 'storage' => $storageDef, )); Each object has a unique identifier
  • 54. $userDef = new ServiceDefinition(‘User’, array(new ServiceReference('storage')) ); Reference to another object
  • 55. $storageDef = new ServiceDefinition( ‘FileSessionStorage’, array(‘SESSION_ID’) ); $userDef = new ServiceDefinition(‘User’, array(new ServiceReference(‘storage’)) ); $container = new ServiceContainer(array( 'storage' => $storageDef, 'user' => $userDef, ));
  • 56. $user = $container->getService('user'); Get the configuration for the user object The User constructor must be given a storage object Get the storage object from the container Create a User object by passing the constructor arguments
  • 57. $user = $container->getService('user'); is roughly equivalent to $storage = new SessionStorage('SESSION_ID'); $user = new User($storage);
  • 58. A container is able to manage any object (POPO) The objects do not need to know they are managed by a container
  • 60. public function getService ($id) { $def = $this->definitions[$id]; $r = new ReflectionClass($def->getClass()); if (is_null($r->getConstructor())) { return $r->newInstance(); } $args = $def->getArguments(); $args = $this->evaluateArguments($args); return $r->newInstanceArgs($args); }
  • 61. public function evaluateArguments($arg) { if (is_array($arg)) { return array_map( array($this, 'evaluateArguments'), $arg ); } if ( is_object($arg) && $arg instanceof ServiceReference ) { return $this->getService($arg); } return $arg; }
  • 62. Towards a real implementation
  • 63. Scope Each time you get a service: Do you want a new object or Does the container must return the same object? $userDef->setGlobal(true); $feedReaderDef->setGlobal(false);
  • 64. Service definition $container = new ServiceContainer(array( PHP 'storage' => new ServiceDefinition('FileSessionStorage'), 'user' => new ServiceDefinition('User', array(new ServiceReference('storage')) ), )); <service id="storage" class="FileSessionStorage" /> XML <service id="user" class="User"> <constructor_arg type="service" id="storage" /> </service>
  • 65. Service configuration Configuration is <parameter key="storage.class"> decoupled from SQLiteSessionStorage the definition </parameter> <parameter key="storage.session_name"> SESSION_ID </parameter> <service id="storage" class="%storage.class%"> <constructor_arg> %storage.session_name% </constructor_arg> </service>
  • 66. Service configuration [storage] class = SQLiteSessionStorage session_name = SESSION_ID <service id="storage" class="%storage.class%"> <constructor_arg> %storage.session_name% </constructor_arg> </service>
  • 67. // Access parameters $sessionName = $container['storage.session_name']; // Access services $user = $container->user;
  • 68. Implementations in PHP •  Crafty: http://phpcrafty.sourceforge.net/ •  Garden: http://garden.tigris.org/ spring •  Stubbles: http://www.stubbles.net/wiki/Docs/IOC Google Guice •  symfony 2 will have its dependency injection framework spring
  • 69. Remember, most of the time, you don’t need a Container to use Dependency Injection
  • 70. You can start to use and benefit from Dependency Injection today
  • 71. by implementing it in your projects by using externals libraries that already use DI without the need of a container
  • 72. symfony Zend Framework ezComponents Doctrine Swift Mailer …
  • 73. Let’s add some i18n fun
  • 74. class User { protected $storage, $i18n; function __construct($storage, $i18n) { $this->storage = $storage; $this->i18n = $i18n; } function setLanguage($language) { $this->storage->set('language', $language); $this->i18n->setLanguage($language); } // ...
  • 75. •  It makes sense that the User class depends on a Storage class –  We can’t use the User object without a Storage •  It does not make sense to tie the User class to the I18n class –  We want to be able to use the User with non internationalized websites
  • 76. class User { protected $storage, $i18n; function __construct($storage, $i18n = null) { $this->storage = $storage; $this->i18n = $i18n; } function setLanguage($language) { $this->storage->set('language', $language); if (!is_null($this->i18n)) { $this->i18n->setLanguage($language); } }
  • 77. class User { protected $storage; function __construct($storage) { $this->storage = $storage; } function setI18n($i18n) { $this->i18n = $i18n; } function setLanguage($language) { $this->storage->set('language', $language); if (!is_null($this->i18n)) { $this->i18n->setLanguage($language); } } }
  • 79. •  The Observer pattern is a way to allow changes in an object to update many other objects •  It is a powerful mechanism to extend applications without having to change the object itself •  Associated words: hook, listener, event, subject, …
  • 80. •  Used by a lot of applications for: –  Plugins (Wordpress, …) –  Bridges between applications •  As a master application: –  Gallery2 (90% events / hooks for user / group create / update / delete, logout, login, ..missing: configuration changes) –  Xaraya (100% events / hooks for user / group create / update / delete, configuration changes, logout, login, ..) –  Wordpress (90% events / hooks for user / update / delete, rewrites, logout, login, ..) –  Drupal (80% maybe?) –  Joomla (100% joomla 1.5; login, logout, create, update, delete user, block, activation, system before and after start)Typo3 (50% maybe?, e.g. no unified create user event / hook) •  As a slave application: –  Gallery 2 –  Phorum.org http://codex.gallery2.org/Gallery2:Embedding:Event-Based_Loose-Coupled_Integration
  • 81. Implementations in PHP •  PEAR_Dispatcher –  http://pear.php.net/package/Event_Dispatcher •  symfony implementation –  http://svn.symfony-project.com/branches/1.1/lib/event/ –  http://www.symfony-project.org/book/1_1/17-Extending-Symfony –  Based on the Cocoa notification center •  Simple and powerful •  Decoupled from symfony •  Simple to use
  • 82. $i18n = new I18n(); $dispatcher = new sfEventDispatcher(); $listener = array($i18n, 'listenToChangeCultureEvent'); $dispatcher->connect('user.change_language', $listener); $storage = new FileSessionStorage(); $user = new User($dispatcher, $storage);
  • 83. class User { protected $storage, $dispatcher; function __construct($dispatcher, $storage) { $this->dispatcher = $dispatcher; $this->storage = $storage; } function setLanguage($language) { $this->storage->set('language', $language); $event = new sfEvent( $this, 'user.change_language', array('language' => $language) ); $this->dispatcher->notify($event); }
  • 84. Notifiers Dispatcher Listeners I18n listens 1 to user.change_culture User notifies Calls I18n callback 2 user.change_culture all listeners is called
  • 85. The User object knows nothing about the I18n one The I18n object knows nothing about the User one They communicate through the Dispatcher object Any class can listen to the ‘user.change_culture’ event and acts accordingly
  • 86. Notifiers Dispatcher Listeners I18n listens 1 to user.change_culture Your class listens to user.change_culture User notifies Calls I18n callback 2 user.change_culture all listeners is called Your class callback is called
  • 87. Notifiers Dispatcher User notifies Calls user.change_culture nothing Very small overhead
  • 88. In this example, the implementation is very simple No interface to implement No need to create an event class for each event An event is just a unique identifier (user.change_culture) some conventions (parameter names)
  • 89. Advantages very simple to use easy to add new arguments to the listener very fast very easy to add a new event, just notify it with a unique name Disadvantages the contract between the listener and the notifier is quite loose
  • 91. function connect($name, $listener) { if (!isset($this->listeners[$name])) { $this->listeners[$name] = array(); } $this->listeners[$name][] = $listener; } function notify(sfEvent $event) { if (!isset($this->listeners[$name])) { foreach ($this->listeners[$event->getName()] as $listener) { call_user_func($listener, $event); } } }
  • 92. •  3 types of notification –  Notify : all listeners are called in turn, no feedback to the notifier •  Logging, … –  Notify Until : all listeners are called until one has « processed » the event. The listener that has processed the event can return something to the caller •  Exceptions, … –  Filter : Each listener filter a given value and can change it. The filtered value is returned to the caller •  HTML content, …
  • 93. Questions? Contact Fabien Potencier fabien.potencier@sensio.com http://www.sensiolabs.com/ http://www.symfony-project.org/