SlideShare ist ein Scribd-Unternehmen logo
1 von 93
Downloaden Sie, um offline zu lesen
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/

Weitere ähnliche Inhalte

Was ist angesagt?

Project ACRN expose and pass through platform hidden PCIe devices to SOS
Project ACRN expose and pass through platform hidden PCIe devices to SOSProject ACRN expose and pass through platform hidden PCIe devices to SOS
Project ACRN expose and pass through platform hidden PCIe devices to SOSProject ACRN
 
Android media framework overview
Android media framework overviewAndroid media framework overview
Android media framework overviewJerrin George
 
Vue js 大型專案架構
Vue js 大型專案架構Vue js 大型專案架構
Vue js 大型專案架構Hina Chen
 
XPDDS17: PL011 UART Emulation in Xen on ARM - Bhupinder Thakur, Qualcomm Data...
XPDDS17: PL011 UART Emulation in Xen on ARM - Bhupinder Thakur, Qualcomm Data...XPDDS17: PL011 UART Emulation in Xen on ARM - Bhupinder Thakur, Qualcomm Data...
XPDDS17: PL011 UART Emulation in Xen on ARM - Bhupinder Thakur, Qualcomm Data...The Linux Foundation
 
Infrastructure Deployment with Docker & Ansible
Infrastructure Deployment with Docker & AnsibleInfrastructure Deployment with Docker & Ansible
Infrastructure Deployment with Docker & AnsibleRobert Reiz
 
Automação de Teste para REST, Web e Mobile
Automação de Teste para REST, Web e MobileAutomação de Teste para REST, Web e Mobile
Automação de Teste para REST, Web e MobileElias Nogueira
 
Empowering Your Java Applications with Quarkus. A New Era of Fast, Efficient,...
Empowering Your Java Applications with Quarkus. A New Era of Fast, Efficient,...Empowering Your Java Applications with Quarkus. A New Era of Fast, Efficient,...
Empowering Your Java Applications with Quarkus. A New Era of Fast, Efficient,...Ivelin Yanev
 
Implementing a WebRTC endpoint in GStreamer: challenges, problems and perspec...
Implementing a WebRTC endpoint in GStreamer: challenges, problems and perspec...Implementing a WebRTC endpoint in GStreamer: challenges, problems and perspec...
Implementing a WebRTC endpoint in GStreamer: challenges, problems and perspec...Luis Lopez
 
Disco API - OpenJDK distributions as a service
Disco API - OpenJDK distributions as a serviceDisco API - OpenJDK distributions as a service
Disco API - OpenJDK distributions as a serviceGerrit Grunwald
 
Introduction To Appium With Robotframework
Introduction To Appium With RobotframeworkIntroduction To Appium With Robotframework
Introduction To Appium With RobotframeworkSyam Sasi
 
Asm bot mitigations v3 final- lior rotkovitch
Asm bot mitigations v3 final- lior rotkovitchAsm bot mitigations v3 final- lior rotkovitch
Asm bot mitigations v3 final- lior rotkovitchLior Rotkovitch
 
Android audio system(audioflinger)
Android audio system(audioflinger)Android audio system(audioflinger)
Android audio system(audioflinger)fefe7270
 
Practical Application of the API Security Top Ten: A Tester's Perspective
Practical Application of the API Security Top Ten: A Tester's PerspectivePractical Application of the API Security Top Ten: A Tester's Perspective
Practical Application of the API Security Top Ten: A Tester's PerspectiveRajniHatti
 
Robot Framework no DevTests #34
Robot Framework no DevTests #34Robot Framework no DevTests #34
Robot Framework no DevTests #34Mayara Fernandes
 
Test Driven Development with Laravel
Test Driven Development with LaravelTest Driven Development with Laravel
Test Driven Development with LaravelTyler Johnston
 

Was ist angesagt? (20)

Project ACRN expose and pass through platform hidden PCIe devices to SOS
Project ACRN expose and pass through platform hidden PCIe devices to SOSProject ACRN expose and pass through platform hidden PCIe devices to SOS
Project ACRN expose and pass through platform hidden PCIe devices to SOS
 
Android media framework overview
Android media framework overviewAndroid media framework overview
Android media framework overview
 
Vue js 大型專案架構
Vue js 大型專案架構Vue js 大型專案架構
Vue js 大型專案架構
 
XPDDS17: PL011 UART Emulation in Xen on ARM - Bhupinder Thakur, Qualcomm Data...
XPDDS17: PL011 UART Emulation in Xen on ARM - Bhupinder Thakur, Qualcomm Data...XPDDS17: PL011 UART Emulation in Xen on ARM - Bhupinder Thakur, Qualcomm Data...
XPDDS17: PL011 UART Emulation in Xen on ARM - Bhupinder Thakur, Qualcomm Data...
 
Infrastructure Deployment with Docker & Ansible
Infrastructure Deployment with Docker & AnsibleInfrastructure Deployment with Docker & Ansible
Infrastructure Deployment with Docker & Ansible
 
Cypress for Testing
Cypress for TestingCypress for Testing
Cypress for Testing
 
Test api
Test apiTest api
Test api
 
Automação de Teste para REST, Web e Mobile
Automação de Teste para REST, Web e MobileAutomação de Teste para REST, Web e Mobile
Automação de Teste para REST, Web e Mobile
 
Empowering Your Java Applications with Quarkus. A New Era of Fast, Efficient,...
Empowering Your Java Applications with Quarkus. A New Era of Fast, Efficient,...Empowering Your Java Applications with Quarkus. A New Era of Fast, Efficient,...
Empowering Your Java Applications with Quarkus. A New Era of Fast, Efficient,...
 
Implementing a WebRTC endpoint in GStreamer: challenges, problems and perspec...
Implementing a WebRTC endpoint in GStreamer: challenges, problems and perspec...Implementing a WebRTC endpoint in GStreamer: challenges, problems and perspec...
Implementing a WebRTC endpoint in GStreamer: challenges, problems and perspec...
 
Unit testing
Unit testingUnit testing
Unit testing
 
Disco API - OpenJDK distributions as a service
Disco API - OpenJDK distributions as a serviceDisco API - OpenJDK distributions as a service
Disco API - OpenJDK distributions as a service
 
Introduction To Appium With Robotframework
Introduction To Appium With RobotframeworkIntroduction To Appium With Robotframework
Introduction To Appium With Robotframework
 
Asm bot mitigations v3 final- lior rotkovitch
Asm bot mitigations v3 final- lior rotkovitchAsm bot mitigations v3 final- lior rotkovitch
Asm bot mitigations v3 final- lior rotkovitch
 
Android audio system(audioflinger)
Android audio system(audioflinger)Android audio system(audioflinger)
Android audio system(audioflinger)
 
Practical Application of the API Security Top Ten: A Tester's Perspective
Practical Application of the API Security Top Ten: A Tester's PerspectivePractical Application of the API Security Top Ten: A Tester's Perspective
Practical Application of the API Security Top Ten: A Tester's Perspective
 
Robot Framework no DevTests #34
Robot Framework no DevTests #34Robot Framework no DevTests #34
Robot Framework no DevTests #34
 
Test Driven Development with Laravel
Test Driven Development with LaravelTest Driven Development with Laravel
Test Driven Development with Laravel
 
sc vector
sc vectorsc vector
sc vector
 
Selenium topic 1- Selenium Basic
Selenium topic 1-  Selenium BasicSelenium topic 1-  Selenium Basic
Selenium topic 1- Selenium Basic
 

Andere mochten auch

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
 

Andere mochten auch (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
 

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

Dependency injection - phpday 2010
Dependency injection - phpday 2010Dependency injection - phpday 2010
Dependency injection - phpday 2010Fabien Potencier
 
Dependency Injection IPC 201
Dependency Injection IPC 201Dependency Injection IPC 201
Dependency Injection IPC 201Fabien 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
 

Ähnlich wie Decouple Your Code For Reusability (International PHP Conference / IPC 2008) (20)

Dependency injection - phpday 2010
Dependency injection - phpday 2010Dependency injection - phpday 2010
Dependency injection - phpday 2010
 
Dependency Injection IPC 201
Dependency Injection IPC 201Dependency Injection IPC 201
Dependency Injection IPC 201
 
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
 

Mehr von Fabien Potencier

Mehr von 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
 

Kürzlich hochgeladen

Swan(sea) Song – personal research during my six years at Swansea ... and bey...
Swan(sea) Song – personal research during my six years at Swansea ... and bey...Swan(sea) Song – personal research during my six years at Swansea ... and bey...
Swan(sea) Song – personal research during my six years at Swansea ... and bey...Alan Dix
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsMaria Levchenko
 
Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationRadu Cotescu
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)Gabriella Davis
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Drew Madelung
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slidevu2urc
 
Slack Application Development 101 Slides
Slack Application Development 101 SlidesSlack Application Development 101 Slides
Slack Application Development 101 Slidespraypatel2
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerThousandEyes
 
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking MenDelhi Call girls
 
The Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxThe Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxMalak Abu Hammad
 
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024BookNet Canada
 
Boost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityBoost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityPrincipled Technologies
 
How to convert PDF to text with Nanonets
How to convert PDF to text with NanonetsHow to convert PDF to text with Nanonets
How to convert PDF to text with Nanonetsnaman860154
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Miguel Araújo
 
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...Igalia
 
The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024Rafal Los
 
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 3652toLead Limited
 
SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024Scott Keck-Warren
 
08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking MenDelhi Call girls
 
CNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of ServiceCNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of Servicegiselly40
 

Kürzlich hochgeladen (20)

Swan(sea) Song – personal research during my six years at Swansea ... and bey...
Swan(sea) Song – personal research during my six years at Swansea ... and bey...Swan(sea) Song – personal research during my six years at Swansea ... and bey...
Swan(sea) Song – personal research during my six years at Swansea ... and bey...
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed texts
 
Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organization
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slide
 
Slack Application Development 101 Slides
Slack Application Development 101 SlidesSlack Application Development 101 Slides
Slack Application Development 101 Slides
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
 
The Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxThe Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptx
 
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
 
Boost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityBoost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivity
 
How to convert PDF to text with Nanonets
How to convert PDF to text with NanonetsHow to convert PDF to text with Nanonets
How to convert PDF to text with Nanonets
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
 
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
 
The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024
 
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
 
SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024
 
08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men
 
CNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of ServiceCNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of Service
 

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/