Dependency Injection in php: Introduzione

Quando ti trovi di fronte ad un progetto che utilizza di un buon numero di classi e istanze, serve un piano d’attacco. Non puoi semplicemente cominciare a scrivere,  altrimenti è molto probabile che, al momento della verità (Il testing), arrivino i problemi. Lo dico con certezza perchè io stesso, fino a qualche tempo fa, ero uno di quelli che iniziava subito a scrivere codice e che poi si ritrovava con mille tab aperte in eclipse per cercare di fixare il problema.

La dependency injection è l’arte di semplificare la creazione e la configurazione delgi oggetti e recentemente, dopo aver spopolato in ambiente Java, ha cominciato a prendere piede in ambiente php; in questi articoli cercherò di riportare ciò che ho imparato a riguardo.

Pensate di avere un oggetto che dovere utilizzare in diversi punti dell’applicazione e che per essere utilizzato ha bisogno di un minimo di configurazione, ad esempio:

/**
*   Nota : pensiamo che il Device non
*   l'abbiamo scritto noi, ma che stiamo utilizzando
*   classi di terze parti altrimenti avremmo potuto
*   modificare il costruttore del device e
*   scrivere new Device($logger,$request)
*/

$device = new Device();
$logger = new XmlLogger();
$logger->prepare('path/to/file.xml');
$device->setLogger($logger);
$device->setRequest(HttpRequest::create()  );
$response = $device->doYourWork();

Prima di riuscire a fare il suo lavoro, il device ha bisogno di alcune righe di preparazione e questo ogni volta che in un punto diverso dell’esecuzione avete bisogno di usare una istanza di device! Diciamo che Device, in questo caso, ha due dipendenze: XmlLogger e HttpRequest.

Premesso che eviterò di usare stati globali come la peste (per maggiori informazioni leggete qui) e quindi qualsiasi forma di Singleton, scrivere quel codice di configurazione ogni volta che si vuole chiamare doYourWork() potrebbe essere una grossa seccatura, specialmente se Device fosse più complesso.

Una prima soluzione ci è data dalla Dependency injection: scriviamo un Container:

class DeviceContainer
{
public function getDevice()
{
   $this->device = new Device();
   $logger = new XmlLogger();
   $logger->prepare('path/to/file.xml');
   $this->device->setLogger($logger);
   $this->device->setRequest(HttpRequest::create()  );
   return $this->device;

}
}

Ora, ogni volta che avremo bisogno di utilizzare il Device, dobbiamo solamente chiamare il metodo getDevice() della classe container ed otterremo una istanza correttamente configurata :

class DeviceUserA
{
   function work()
   {
       $container = new DeviceContainer();
       $device = $container->getDevice();
       $device->doYourWork();
    }

}

Questa soluzione è ancora poco flessibile perchè potreste necessitare all’interno della vostra applicazione di diversi tipi di device ognuno con una configurazione diversa. Dobbiamo modificare il nostro DeviceContainer:

class DeviceContainer
{
public function getDeviceA()
{
   if (null !== $this->device_a)
      return $this->device_a
   $this->device_a = new DeviceA();
   $logger = new XmlLogger();
   $logger->prepare('path/to/file.xml');
   $this->device_a->setLogger($logger);
   $this->device_a->setRequest(HttpRequest::create()  );
   return $this->device_a;

}
public function getDeviceB()
{
   if (null !== $this->device_b)
      return $this->device_b

   $this->device_b = new DeviceB();

   $dsn = 'mysql:dbname=testdb;host=127.0.0.1';
   $user = 'dbuser';
   $password = 'dbpass';
   $connection = new PDO($dns,$user,$password);
   $logger = new MysqlLogger($connection);

   $this->device_b->setLogger($logger);
   $this->device_b->setRequest(HttpRequest::create()  );
   return $this->device_b;

}

}

Potete notare che ogni metodo getDeviceX() ha due righe di codice che consentono di non reistanziare l’oggetto ogni volta
ma di riutilizzare istanze già create dal container.

Per questo articolo è tutto, nel prossimo vedremo come scrivere un container che funzioni in ogni situazione (o quasi) senza bisogno di modificare la classe container.

Ora torno a lavorare a qoo framework, non vedo l’ora di pubblicarlo ed essere criticato😉 .

2 risposte a “Dependency Injection in php: Introduzione

  1. Pingback: Dependency Injection in PHP parte 2: Container | Digital Riot

  2. Long live dependency injection!

Lascia un commento

Inserisci i tuoi dati qui sotto o clicca su un'icona per effettuare l'accesso:

Logo WordPress.com

Stai commentando usando il tuo account WordPress.com. Chiudi sessione / Modifica )

Foto Twitter

Stai commentando usando il tuo account Twitter. Chiudi sessione / Modifica )

Foto di Facebook

Stai commentando usando il tuo account Facebook. Chiudi sessione / Modifica )

Google+ photo

Stai commentando usando il tuo account Google+. Chiudi sessione / Modifica )

Connessione a %s...