Foros del Web » Programando para Internet » PHP » Frameworks y PHP orientado a objetos »

Patron IoC e inyeccion de dependencia

Estas en el tema de Patron IoC e inyeccion de dependencia en el foro de Frameworks y PHP orientado a objetos en Foros del Web. Podrían explicarme para que sirven estos patrones y con que fin se usan .. con alguno ejemplo simple en PHP Lo publico acá porque hay ...
  #1 (permalink)  
Antiguo 06/11/2012, 09:00
Avatar de HiToGoRoShi  
Fecha de Ingreso: abril-2008
Mensajes: 849
Antigüedad: 16 años
Puntos: 31
Patron IoC e inyeccion de dependencia

Podrían explicarme para que sirven estos patrones y con que fin se usan .. con alguno ejemplo simple en PHP

Lo publico acá porque hay gurus en patrones de diseño

Estoy haciendo un trabajo en .NET, y nos mandaron a investigar esto pero no logro comprender bien su uso , yo se que dirán porque publicas esto acá, si lo tuyo es .NET ... pero los patrones de diseno son ambiguos no?, da igual en que lenguaje lo use
  #2 (permalink)  
Antiguo 06/11/2012, 11:35
Avatar de GatorV
$this->role('moderador');
 
Fecha de Ingreso: mayo-2006
Ubicación: /home/ams/
Mensajes: 38.567
Antigüedad: 18 años
Puntos: 2135
Respuesta: Patron IoC e inyeccion de dependencia

El patrón de inyeccion de dependencias lo que busca es desacoplar aún más tu sistema, que tus clases no sean concretas, si no abstractas, y que cambien su comportamiento de forma dinámica dependiendo de los componentes bajo los que este atado.

Es decir, que tu clase, no sepa exactamente con que clase va a trabajar, si no que tenga una interfaz que solo garantice el contrato de funcionamiento de la clase.

Un ejemplo muy típico es un logger, el log recibe como parámetro (o como dependencia) un writer donde va a escribir las entradas del log, el writer como tal es una interfaz, y tiene muchas implementaciones (writer de memoria, en un archivo, por mail, una base de datos, etc), cada writer tiene su tarea específica, y el log no se preocupa por eso, el log lo que hace es crear la entrada y enviarla al writer que tenga especificado en su dependencia.

IoC es esto mismo, o sea tu clase no sabe con que componentes va a trabajar, simplemente sabe las dependencias que necesita (usando Interfaz), y el como se comporta, se hace al momento de usar tu aplicación (normalmente usando un archivo de configuración) donde se describe el comportamiento de la aplicación y es cuando se crean las instancias concretas de cada clase y se inyectan a los componentes que necesitan.

Saludos.
  #3 (permalink)  
Antiguo 06/11/2012, 12:35
Avatar de HiToGoRoShi  
Fecha de Ingreso: abril-2008
Mensajes: 849
Antigüedad: 16 años
Puntos: 31
Respuesta: Patron IoC e inyeccion de dependencia

tu que eres lobo en zf este implementa estos patrones? ... podrias darme un ejemplo simple no mas en codigo?

Gracias
  #4 (permalink)  
Antiguo 06/11/2012, 12:36
Avatar de GatorV
$this->role('moderador');
 
Fecha de Ingreso: mayo-2006
Ubicación: /home/ams/
Mensajes: 38.567
Antigüedad: 18 años
Puntos: 2135
Respuesta: Patron IoC e inyeccion de dependencia

Así es ZF2 implementa mucho IoC y DI, usando el ServiceManager.

Saludos.
  #5 (permalink)  
Antiguo 07/11/2012, 21:28
Avatar de HiToGoRoShi  
Fecha de Ingreso: abril-2008
Mensajes: 849
Antigüedad: 16 años
Puntos: 31
Respuesta: Patron IoC e inyeccion de dependencia

Veamos si entendi para poder hacer mi tarea correctamente ....

Inyeccion de depedencia y IoC lo que intenta hacer es desacoplar la logica de tu proyecto, cosa que asi si en un futuro tu logica de negocio cambia ya no vas a tener que modificar todo, sino solo tu repositorio.

Lo cual e visto lo mismo con factory ... que me parecen casi identico
  #6 (permalink)  
Antiguo 07/11/2012, 22:13
Avatar de pablofmorales  
Fecha de Ingreso: abril-2008
Ubicación: Buenos Aires, Argentina, Argentina
Mensajes: 222
Antigüedad: 16 años, 1 mes
Puntos: 37
Respuesta: Patron IoC e inyeccion de dependencia

Cita:
Iniciado por HiToGoRoShi Ver Mensaje
Podrían explicarme para que sirven estos patrones y con que fin se usan .. con alguno ejemplo simple en PHP

Lo publico acá porque hay gurus en patrones de diseño

Estoy haciendo un trabajo en .NET, y nos mandaron a investigar esto pero no logro comprender bien su uso , yo se que dirán porque publicas esto acá, si lo tuyo es .NET ... pero los patrones de diseno son ambiguos no?, da igual en que lenguaje lo use
Arriba Gatarov explica que son y para que sirven. Este patron es una pata de los principio de SOLID

un ejemplo en php simple con un logger en PHP seria algo como

Código PHP:
<?php
class Logger 
{
   public function 
write($message)
  {
      
error_log($message);
  }
}

class 
Login
{
   private 
$_logger;
   public function 
setLogger($logger)
   {
      
$this->_logger $logger;
   }

   public function 
authenticate($user$password)
   {
      if (
$user == 'test' && $password == 'passwd') {
         return 
true;
      } else {
          
$this->_logger->write('User can not be found');
          return 
false;
      }
   }
}

$logger = new Logger();
$login = new Login();
$login->setLogger($logger);

$login->authenticate('Juan''Password');
Si en algun momento queremos cambiar nuestra clase logger por Monolog por ejemplo cambiamos solo cuando hacemos la inyeccion por ejemplo


Código PHP:
$logger = new Monolog();
$login = new Login();
$login->setLogger($logger);

$login->authenticate('Juan''Password'); 
Y todo funciona bien :D
__________________
blog
  #7 (permalink)  
Antiguo 08/11/2012, 10:44
Avatar de HiToGoRoShi  
Fecha de Ingreso: abril-2008
Mensajes: 849
Antigüedad: 16 años
Puntos: 31
Respuesta: Patron IoC e inyeccion de dependencia

Okey, voy a poner mi ejemplo ...

Tengo mis carpetas así

Model
--datos
--------UsuarioMemory
--------UsuarioXML
--entities
--------Usuario
--interfaces
--------IUsuarioService
--UsuarioModel

Lo que e aplicado es la inyección de dependencia ... ya que mi aplicativo puede consumir ya sea de una base de datos, un XML, o de la memoria sin tener que cambiar su lógica de negocio, solo debe cambiar su repositorio, es decir la dependencia inyectada.

Las clases

model/Entities/Usuario
Código PHP:
Ver original
  1. class Usuario {
  2.     private $_id;
  3.     private $_nombre;
  4.     private $_apellido;
  5.     private $_dni;
  6.    
  7.     public function get_id() { return $this->_id; }
  8.     public function get_nombre() { return $this->_nombre; }
  9.     public function get_apellido() { return $this->_apellido; }
  10.     public function get_dni() { return $this->_dni; }
  11.     public function set_id($x) { $this->_id = $x; }
  12.     public function set_nombre($x) { $this->_nombre = $x; }
  13.     public function set_apellido($x) { $this->_apellido = $x; }
  14.     public function set_dni($x) { $this->_dni = $x; }
  15. }

model/Datos/UsuarioXML
Código PHP:
Ver original
  1. <?php
  2. class UsuarioXML {
  3.    
  4.     private $_sxe;
  5.    
  6.     public function __construct(){
  7.         $this->_sxe = new SimpleXMLElement('usuario.xml', NULL, TRUE);
  8.     }
  9.     public function listar(){
  10.         $usuarios = array();
  11.         foreach($this->_sxe as $u){
  12.             $usuario = new Usuario();
  13.            
  14.             $usuario->set_id((int)$u->id);
  15.             $usuario->set_nombre((string)$u->nombre);
  16.             $usuario->set_apellido((string)$u->apellido);
  17.             $usuario->set_dni((string)$u->dni);
  18.            
  19.             $usuarios[] = $usuario;
  20.         }
  21.        
  22.         return $usuarios;
  23.     }
  24.     public function registrar(Usuario $usuario){
  25.         $u = $this->_sxe->addChild('usuario');
  26.        
  27.         $u->addChild('id', $this->_sxe->count() + 1);
  28.         $u->addChild('nombre', $usuario->get_nombre());
  29.         $u->addChild('apellido', $usuario->get_apellido());
  30.         $u->addChild('dni', $usuario->get_dni());
  31.        
  32.         $this->save();
  33.     }
  34.     public function actualizar(Usuario $usuario){
  35.         foreach($this->_sxe as $u){
  36.             if($u->id == $usuario->get_id()){
  37.                 $u->nombre   = $usuario->get_nombre();
  38.                 $u->apellido = $usuario->get_apellido();
  39.                 $u->dni      = $usuario->get_dni();
  40.                 break;
  41.             }
  42.         }
  43.        
  44.         $this->save();
  45.     }
  46.     public function eliminar($id){
  47.         $i = 0;
  48.         foreach($this->_sxe as $k => $u){
  49.             if($u->id == $id){
  50.                 $dom =dom_import_simplexml($u);
  51.                 $dom->parentNode->removeChild($dom);
  52.                 break;
  53.             }
  54.             $i++;
  55.         }
  56.         $this->save();
  57.     }
  58.     public function obtener($id){
  59.         $usuario = new Usuario();
  60.         foreach($this->_sxe as $u){
  61.             if($u->id == $id){     
  62.                 $usuario->set_id((int)$u->id);
  63.                 $usuario->set_nombre((string)$u->nombre);
  64.                 $usuario->set_apellido((string)$u->apellido);
  65.                 $usuario->set_dni((string)$u->dni);
  66.                 break;
  67.             }
  68.         }
  69.        
  70.         return $usuario;
  71.     }
  72.     private function save(){
  73.         $fo = fopen('usuario.xml','w');
  74.         fwrite($fo, $this->_sxe->asXML());
  75.         fclose($fo);
  76.     }
  77. }

model/interfaces/IUsuarioService
Código PHP:
Ver original
  1. interface IUsuarioService {
  2.     public function setInjection($rp);
  3.    
  4.     public function listar();
  5.     public function registrar(Usuario $usuario);
  6.     public function actualizar(Usuario $usuario);
  7.     public function eliminar($id);
  8.     public function obtener($id);
  9. }


model/UsuarioModel
Código PHP:
Ver original
  1. class UsuarioModel implements IUsuarioService {
  2.  
  3.     private $_Repossitory;
  4.  
  5.     public function setInjection($rp){
  6.         $this->_Repossitory = $rp;
  7.     }
  8.  
  9.     public function listar(){
  10.         return $this->_Repossitory->listar();
  11.     }
  12.     public function registrar(Usuario $usuario){
  13.         $this->_Repossitory->registrar($usuario);
  14.     }
  15.     public function actualizar(Usuario $usuario){
  16.         $this->_Repossitory->actualizar($usuario);
  17.     }
  18.     public function eliminar($id){
  19.         $this->_Repossitory->eliminar($id);
  20.     }
  21.     public function obtener($id){
  22.         return $this->_Repossitory->obtener($id);
  23.     }
  24.  
  25. }

Y ahora lo implemento asi
Código PHP:
Ver original
  1. $um = new UsuarioModel();
  2. $um->setInjection(new UsuarioXML());
  3.  
  4. $usuarios = $um->listar();

En caso que nuestro proyecto ya no requiera el uso de los XML, simplemente cambiar su repositorio a UsuarioDB, o UsuarioTXT, o UsuarioMemoria

Esta bien lo que planteo?
  #8 (permalink)  
Antiguo 08/11/2012, 11:28
Avatar de GatorV
$this->role('moderador');
 
Fecha de Ingreso: mayo-2006
Ubicación: /home/ams/
Mensajes: 38.567
Antigüedad: 18 años
Puntos: 2135
Respuesta: Patron IoC e inyeccion de dependencia

Exacto, esa es la idea, que puedas cambiar todo el funcionamiento desde un "bootstrap" o un archivo de configuración, en Java se usa mucho los .properties para describir el comportamiento de la aplicación.
  #9 (permalink)  
Antiguo 08/11/2012, 13:08
Avatar de HiToGoRoShi  
Fecha de Ingreso: abril-2008
Mensajes: 849
Antigüedad: 16 años
Puntos: 31
Respuesta: Patron IoC e inyeccion de dependencia

aja, y actualmente todo los frameworks apuntan a eso ... lo que no tengo claro cual es la diferencia de IoC con inyeccion de dependencia, ya que por definicion me suena a lo mismo
  #10 (permalink)  
Antiguo 08/11/2012, 13:44
Avatar de GatorV
$this->role('moderador');
 
Fecha de Ingreso: mayo-2006
Ubicación: /home/ams/
Mensajes: 38.567
Antigüedad: 18 años
Puntos: 2135
Respuesta: Patron IoC e inyeccion de dependencia

IoC es simplemente un paradigma de diseño, la idea es invertir el control en lugar de dependencias fijas a interfaces, ej:
Código PHP:
Ver original
  1. class Auto {
  2.       public function __construct()
  3.       {
  4.               $this->motor = new Motor4cil();
  5.               $this->puertas = new 2Puertas();
  6.               $this->llantas = new LlantasDeInvierno();
  7.       }
  8. }

A usar interfaces abstractas:
Código PHP:
Ver original
  1. class Auto
  2. {
  3.          public function setMotor(InterfaceMotor $motor)
  4.          {
  5.                  $this->motor = $motor;
  6.          }
  7.  
  8.          // etc
  9. }
  10.  
  11. // Luego en algún bootstrap
  12. $auto = new Auto();
  13. $motor = Motor::factory('config.motor');
  14. $auto->setMotor($motor);

Es decir el control es invertido, ya no lo tiene la clase Auto, si no lo tiene el archivo de configuración donde se describe el comportamiento de la aplicación.

Van de la mano porque necesitas hacer tu diseño se comporte en base a inyeccion de dependencias, y luego va más alla al usar IoC.

Saludos.
  #11 (permalink)  
Antiguo 08/11/2012, 14:00
Avatar de masterpuppet
Software Craftsman
 
Fecha de Ingreso: enero-2008
Ubicación: Montevideo, Uruguay
Mensajes: 3.550
Antigüedad: 16 años, 3 meses
Puntos: 845
Respuesta: Patron IoC e inyeccion de dependencia

La linea es fina, demasiado para mi gusto, dejo una referencia http://martinfowler.com/articles/injection.html y cito:

Cita:
As a result I think we need a more specific name for this pattern. Inversion of Control is too generic a term, and thus people find it confusing. As a result with a lot of discussion with various IoC advocates we settled on the name Dependency Injection.
IMO, IoC es una técnica o practica y DI es una forma de conseguirlo al igual que lo es ServiceLocator(para algunos anti-pattern).

Saludos.
__________________
http://es.phptherightway.com/
thats us riders :)

Etiquetas: dependencia, patron, php
Atención: Estás leyendo un tema que no tiene actividad desde hace más de 6 MESES, te recomendamos abrir un Nuevo tema en lugar de responder al actual.
Respuesta




La zona horaria es GMT -6. Ahora son las 07:36.