Sitio web no optimizado para IE 6

Dependecy Injection En Php

posteado por Emiliano, categoría Php

16 mar
2010

Veremos qué es y como utilizar este patrón de diseño en PHP.

En la progrmación orientada a objetos, un programa central normalmente controla otros objetos, ya sea en un modulo, una librería o un framework. Con la inyección de dependencia, este patrón es invertido, ya que una referencia hacia una clase es incluida directamente en el objecto, el cual será facilmente testeable, estará desacoplado y tendrá modularidad.

La inyección de dependencia (Dependency Injection en inglés) es una técnica, o mejor dicho, un patrón de diseño de software en lenguajes orientados a objetos, para incluir o abastecer una dependencia externa (por ejemplo, una librería third-party) en alguna clase de nuestro proyecto, con lo cual, se le indica a esta clase que otras clases puede usar. La DI es una forma específica de inversión de control.

En resumén, DI significa darle a un objeto la instancia de otro objeto para que este último pueda ser utilizado.

Veamos un ejemplo en PHP.

Para manejar las variables de sesión de PHP crearemos una clase llamada SessionHandler:

<?php
class SessionHandler
{
  function __construct($cookieName = 'hasheado')
  {
    session_name($cookieName);
    session_start();
  }
 
  function setAttibute($key, $value)
  {
    $_SESSION[$key] = $value;
  }
 
  function getAttribute($key)
  {
    return $_SESSION[$key];
  }
 
  // ...
}
?>

Y una clase User para manejar la información pertinente al usuario:

<?php
class User
{
  protected $handler;
 
  function __construct()
  {
    $this->handler = new SessionHandler();
  }
 
  function setLanguage($language)
  {
    $this->handler->setAttribute('language', $language);
  }
 
  function getLanguage()
  {
    return $this->handler->getAttribute('language');
  }
 
  // ...
}

?>

El uso de estas clases es bastante sencillo:

<?php
$user = new User();
$user->setLanguage('es');
$user_language = $user->getLanguage();
?>

Hasta ahora todo el código luce correcto y bien. Hasta que necesitamos más flexibilidad. Por ejemplo, que pasa si quisieramos cambiar el nombre de la cookie de session. Repasemos algunas posibilidades:

Por ejemplo, podemos hardcodear el nombre de la cookie en el constructor de la clase User:

<?php
class User
{
  function __construct()
  {
    $this->handler = new SessionHandler('hasheado');
  }
 
  // ...
}
?>

También podríamos definir una constante fuera de la clase User:

<?php
class User
{
  function __construct()
  {
    $this->handler = new SessionHandler(HANDLER_SESSION_NAME);
  }
 
  // ...
}
define('HANDLER_SESSION_NAME', 'hasheado');
?>

O podríamos pasar el nombre de la sesión como un argumento del constructor:

<?php
class User
{
  function __construct()
  {
    $this->handler = new SessionHandler($sessionName);
  }
 
  // ...
}
$user = new User('hasheado');
?>

Como quizás ya te habras dado cuenta todas estas opciones son malas. Hardcodear el nombre de la sesión en la clase User no resuelve el problema de cambiar facilmente el nombre sin modificar la clase User. Usar una constante es una muy mala idea ya que ahora la clase User depende de esta constante. Y pasar el nombre de la sesión como un argumento es quizás la mejor opción, pero sigue viendose mal.

Además, todavía hay otro problema que no puede ser resuelto facilmente: Cómo podemos cambiar la clase SessionHandler para remplazarla por un objeto mock con propositos de testing, ó si queremos almacenar las sesiones en la base de datos o en memoria. Todo eso es imposible con la actual implementación, excepto si cambiamos la clase User.

Implementemos Dependency Injection. En vez de crear el objeto SessionHandler dentro de la clase User inyectaremos el objeto SessionHandler en el objeto User pasándoselo como un argumento en el constructor:

<?php
class User
{
  function __construct($handler)
  {
    $this->handler = $handler;
  }
 
  // ...
}
?>

Esto es Dependency Injection. Y usar la clase User ahora es dependiente del objeto SessionHandler:

<?php
$handler = new SessionHandler('hasheado');
$user = new User($handler);
?>

Ahora, configurar el objeto SessionHandler es mucho más simple, y remplazar esta clase también es bastante fácil. Y todo esto es posible sin tener que modificar la clase User.

Existen varias maneras de implementar Dependency Injection, como vimos anteriormente una de estas maneras es el Constructor Injector:

<?php
class User
{
  function __construct($handler)
  {
    $this->handler = $handler;
  }
 
  // ...
}
?>

Otra manera es el Setter Injector:

<?php
class User
{
  function setSessionHandler($handler)
  {
    $this->handler = $handler;
  }
 
  // ...
}
?>

Y aún otra manera es el Property Injector:

<?php
class User
{
  public$sessionHandler;
}
$user->sessionHandler = $handler;
?>

La manera más recomendada para implementar dependencias requeridas es Constructor Injection, y la mejor opción para implementar dependencias opcionales es Setter Injection.

Bien eso es todo, hoy en día la mayoría de los frameworks PHP más modernos usan altamente Dependency Injection para proveer un conjunto de componentes desacoplados pero cohesivos. Espero que les quede claro el concepto de Dependency Injection.

 

Fuente: Fabien Potencier's blog

Compártelo: technorati Dependecy Injection En Php digg Dependecy Injection En Php facebook Dependecy Injection En Php google Dependecy Injection En Php linkedin Dependecy Injection En Php

1 Comentario:


marcelog:

20 de Febrero de 2011 a las 02:52:36

Ding (http://marcelog.github.com/Ding) es un container con inversion of control y dependency injection que imita a spring(tm) de java en su funcionalidad, tambien implementa algunas annotations de jsr 250 y 330

Comentar este Artículo






Captcha ImageReload_original