Injection de dépendances en PHP avec Crafty
Par Clochix le lundi 7 juillet 2008, 23:59 - Technoweb - Lien permanent
Mes récentes, brèves mais fructueuses, incursions dans l'archipel de Java m'ont permis de pratiquer les patrons de conceptions inversion de contrôle (IoC) et injection de dépendances. Je viens de tomber sur une bibliothèque PHP, Crafty, permettant de faire de l'injection de dépendances en PHP. L'occasion d'en dire 2 mots...
Inversion de contrôle et injection de dépendances
Dans le cas d'une application web par exemple, l'approche "classique" consiste à écrire un programme qui démarre, charge un environnement, lit une requête d'un client, la traite, met en forme le résultat, le renvoie au client, attend la requête suivante, etc, avant de s'arrêter, idéalement en sauvegardant proprement son état et son environnement. L'application contrôle tout de A à Z. L'inversion de contrôle consiste à déléguer le plus gros des tâches à une application tierce, généralement un framework, et à juste fournir à cette application des objets à utiliser dans certains cas. C'est le framework qui décidera de les instancier et d'appeler leurs méthodes en fonction des besoins. C'est lui qui a le contrôle et utilise vos objets. Cela permet de se concentrer sur l'écriture des objets métiers et de déléguer le reste des traitements à un programme tiers. Idéalement,les objets pourront être utilisés quelque soit le framework sous-jacent.
L'injection de dépendances est un exemple d'inversion de contrôle. Si un objet A utilise un objet B, on laisse le framework qui contrôle l'exécution de A instancier B et le passer à A au moment de l'exécution. Un exemple classique est une connexion à une base de données. Si un objet à besoin d'une telle connexion, il n'a pas à la créer lui-même. C'est le framework qui la lui passera au moment opportun. Cela permet de ne plus gérer les dépendances entre objets au moment de l'écriture du code, mais de son exécution, ce qui rend les différentes briques fonctionnelles plus indépendantes les unes des autres, d'où un code plus ré-utilisable.
Crafty
Crafty est un programme qui prétend faciliter l'injection de dépendances en PHP. J'avoue que je ne l'ai pas testé, mais la documentation est intéressante.
Soit un objet O qui utilise des objets D1, D2, D3... Vous pouvez passer les différents objets dépendants au constructeur... Mais ca devient vite lourd s'il y en a beaucoup. Vous pouvez aussi définir des setters et les appeler:
class toto {
private $_obj1;
private $_obj2;
private $_obj3;
public function setObj1(titi $o) {
$this->_obj1 = $o;
}
public function setObj2(tata $o) {
$this->_obj2 = $o;
}
public function setObj3(tutu $o) {
$this->_obj3 = $o;
}
(...)
}
$plouf = new toto();
$plouf->setObj1(new titi());
$plouf->setObj2(new tata());
$plouf->setObj3(new tutu());
(...)
Crafty permet de remplacer les dernières lignes, c'est à dire l'instanciation des objets dont dépend l'objet principal et leur passage à cet objet, par un simple appel:
$plouf = $crafty->create('toto');
Enfin, pas si simple que cela car il faut bien évidemment lui expliquer quelles sont les dépendances entre les classes. On utilise pour cela des fichiers de configuration, qui peuvent être en XML, en YAML, ou en PHP, et qui décrivent l'ensemble des classes, les paramètres à passer à leurs constructeurs respectifs et les dépendances entre elles. Dans l'exemple ci-dessus, on indiquera que toto a besoin de titi, tata et tutu et que ces dépendances doivent lui être passées via des setters. Dernier point, un paramètre dans le fichier de configuration permet de préciser s'il faut créer de nouvelles instances des objets liés à chaque création d'un objet principal, ou si on utilise les mêmes.
Si mon exemple n'a aucun intérêt, je garde le lien vers Crafty pour le tester à l'occasion sur un "vrai" projet.
Ah, et pour l'essayer, il faut aller le chercher dans svn
Commentaires
Oui mais, dans la pratique, à partir du moment où on urilise un framework, est-ce que cela arrive souvent ce genre de besoins, hormis pour des objets métier ?
Pour l'instant, je crois que peu de frameworks PHP permettent de faire de l'injection de dépendances. Niko signale que ça arrive doucement dans Symfony. Et comme tu le dis, ça va servir pour aller dans une direction où l'on se focalisera davantage sur le développement d'objets métiers autonomes.
Et puis, franchement, ce genre de bibliothèque permet surtout de se sentir un peu moins amateur face à des javaïstes qui ne jurent que par leur Spring