Injection de dépendance en PHP

L’injection de dépendance a fait l’objet de discussions fréquentes au sein de nombreux développeurs d’entreprise au cours des dernières années. Beaucoup craignaient de perdre trop de temps à la construction de leur architecture applicative sans faire de vrai travail. Dans cet article, je vais expliquer pourquoi les développeurs PHP devraient envisager de tirer parti de l'injection de dépendance lors de la construction de projets volumineux et évolutifs..


Qu'est-ce que l'injection de dépendance??

Avant de creuser le sujet, définissons avec précision ce qu'est l'injection de dépendance. Imaginons que vous travailliez actuellement sur un site Web "Question and Answers", similaire à Stack Overflow. Vous voudriez probablement créer une classe, appelée Question, qui contiendrait un membre de type Auteur. Dans le passé, les programmeurs auraient créé le Auteur objet directement dans le Question constructeur, comme ceci:

classe Author private $ firstName; private $ lastName; fonction publique __construct ($ firstName, $ lastName) $ this-> firstName = $ firstName; $ this-> lastName = $ lastName;  fonction publique getFirstName () return $ this-> firstName;  fonction publique getLastName () return $ this-> lastName;  class Question private $ author; question privée $; fonction publique __construct ($ question, $ authorFirstName, $ authorLastName) $ this-> author = new Author ($ authorFirstName, $ authorLastName); $ this-> question = $ question;  fonction publique getAuthor () return $ this-> author;  fonction publique getQuestion () return $ this-> question; 

Bien que de nombreux programmeurs appellent peut-être ce bon code, celui-ci pose de nombreux problèmes:

  • Les informations de l'auteur transmises au Question constructeur n'a rien à faire à l'intérieur Questionla portée. Le nom d'un auteur doit figurer à l'intérieur du Auteur classe parce que cela n'a rien à voir avec la question, elle-même.
  • le Auteur la classe est étroitement liée à la Question classe. Si nous ajoutons un nouveau paramètre à AuteurLe constructeur de, nous devons ensuite modifier chaque classe où nous créons un Auteur objet - un processus fastidieux et long, en particulier dans les grandes applications.
  • Unité testant le Question classe crée le comportement indésirable de devoir tester la Auteur classe aussi bien.

L'injection de dépendances atténue ces problèmes en insérant les dépendances via le constructeur de la classe dépendante ("Constructor Injection"). Le résultat est un code hautement maintenable, qui pourrait ressembler à ceci:

classe Author private $ firstName; private $ lastName; fonction publique __construct ($ firstName, $ lastName) $ this-> firstName = $ firstName; $ this-> lastName = $ lastName;  fonction publique getFirstName () return $ this-> firstName;  fonction publique getLastName () return $ this-> lastName;  class Question private $ author; question privée $; fonction publique __construct ($ question, Author $ author) $ this-> author = $ author; $ this-> question = $ question;  fonction publique getAuthor () return $ this-> author;  fonction publique getQuestion () return $ this-> question; 

Avantages de l'injection de dépendance

Vous devez utiliser l’injection de dépendance pour les projets à long terme..

J'ai travaillé sur de nombreux projets commerciaux au cours de ma carrière. Certains d'entre eux sont très bien écrits; Cependant, je dois dire que la plupart d'entre eux ont une qualité de code considérablement médiocre. On m'a récemment assigné à travailler sur une telle base de code…

Une entreprise a demandé l'application en 2009. Le budget du projet avait été correctement planifié, mais le responsable du projet souhaitait que l'application soit construite très rapidement pour impressionner son patron. Au moins, c'est ce que mon collègue m'a dit. Écrire une application rapidement peut sembler génial pour réduire les coûts, mais cela signifie également que les développeurs ont sauté dans le code sans planification adéquate..

Les développeurs ont rapidement écrit du code, en créant les classes nécessaires pour exécuter les fonctionnalités nécessaires. Les caractéristiques ont changé au fur et à mesure que le projet évoluait et, le projet étant mal planifié (et chaque classe étant étroitement couplée), le projet est devenu difficile à développer.

Actuellement, il est difficile de travailler sur ce projet. La modification d'une classe simple entraîne une cascade d'autres modifications dans les autres classes, car tout est couplé, ce qui génère de nombreux bogues. Chaque fois que quelque chose est modifié, le développeur doit poursuivre et corriger les bogues..

L'application est également impossible au test unitaire, ce qui dégrade la qualité du code.

Chaque fonctionnalité doit être testée manuellement, perdant ainsi un temps précieux qui pourrait être passé ailleurs. En fait, pour réduire le coût des tests manuels, nous avons créé un logiciel permettant de tester l'infrastructure de l'application. Oui, nous avons dû créer un nouveau logiciel afin de tester le produit réel.

L'entreprise a appris qu'essayer d'écrire rapidement un logiciel entraînait des coûts inattendus. Au début, la société gagnait beaucoup d’argent parce qu’elle demandait beaucoup, mais au bout de trois ans, elle perdait de l’argent avec cette demande. La somme d'argent qu'ils ont retirée ne couvre pas les dépenses d'entretien élevées et continues. Ils ont également perdu beaucoup de bons développeurs expérimentés, qui avaient perdu tout désir de travailler sur le projet..

Si l'application utilisait l'injection de dépendance, les développeurs auraient pu tester correctement l'ensemble de l'application, ce qui aurait permis de réduire les coûts de maintenance et le débogage. La société se serait concentrée sur la création de nouvelles fonctionnalités durables, au lieu de perdre de la qualité logicielle chaque fois qu'une nouvelle fonctionnalité était introduite. Ils auraient également gardé les membres de leur équipe senior et évité de perdre de l'argent en trouvant et en embauchant de nouveaux employés (ce qui est difficile au début dans ma ville).


Commencer avec un budget limité

Bien que l’injection de dépendance vous aide à rédiger un meilleur code, elle peut également nécessiter plus de temps et d’efforts pour le faire correctement. Cela peut s'avérer être un problème si vous avez besoin d'un code de travail pour une démonstration..

Si tout ce dont vous avez besoin est une preuve de concept, alors je vous suggère de ne pas perdre de temps avec l'injection de dépendance et une architecture appropriée.

Sautez et commencez à coder. Vous pouvez faire les choses correctement une fois le projet approuvé et disposer du financement nécessaire. En fait, une fois que vous avez les fonds nécessaires, jetez votre démo et recommencez à zéro. Sinon, votre application se retrouvera dans une corbeille à spaghetti.


Code de démarrage malpropre

Ainsi, vous avez commencé à passer vos dépendances dans les constructeurs de classe, mais au fur et à mesure que le projet se développe, vous vous retrouvez avec de nombreux niveaux d'objets qui doivent être créés au démarrage de votre application. En fonction de la taille de votre application, la création de tous les objets pour lancer votre application peut être un processus très long et nuire aux performances de votre application (ainsi qu'à du code désordonné). Voici un exemple:

/ * Veuillez noter que la nature de l'application n'est pas importante ici. Je voulais seulement montrer à quel point un tel code est difficile à maintenir / terrible: * / $ filePath = "/ chemin / vers / fichier"; $ fileBuilderFactory = new ConcreteFileBuilderFactory (); $ filesXmlBuilderFactory = new ConcreteFilesXmlBuilderFactory ($ fileBuilderFactory); $ softwaresRetrieverCriteriaBuilderFactory = new ConcreteSoftwaresRetrieverCriteriaBuilderFactory ($ filesXmlBuilderFactory); $ softwareRetrieverCriteriaBuilderFactory = new ConcreteSoftwaresSoftwareRetrieverCriteriaBuilderFactory ($ filesXmlBuilderFactory); $ filesJsonBuilderFactory = new ConcreteFilesJsonBuilderFactory ($ fileBuilderFactory); $ objectBuildderFactory = new ConcreteSoftwaresSoftwareObjectBuilderFactory (); $ softwaresSoftwareBuilderFactory = new ConcreteSoftwaresSoftwareBuilderFactory ($ objectBuildderFactory); $ xmlSoftwareRepository = new XmlSoftwareRepository ($ softwaresSoftwareBuilderFactory); $ softwaresBuilderFactory = new ConcreteSoftwaresBuilderFactory ($ xmlSoftwareRepository, $ softwareRetrieverCriteriaBuilderFactory, $ filesJsonBuilderFactory); $ xmlSoftwaresRepository = new XmlSoftwaresRepository ($ softwaresBuilderFactory); $ softwareToHashMap = new ConcreteSoftwareToHashMap (); $ softwaresToHashMap = new ConcreteSoftwaresToHashMap ($ softwareToHashMap); $ jsonSoftwaresService = new JsonSoftwaresService ($ softwaresToHashMap); $ di = new DependencyInjection ($ softwaresRetrieverCriteriaBuilderFactory, $ xmlSoftwaresRepository, $ jsonSoftwaresService);

Ce code de démarrage est plutôt petit. Si vous construisez une application volumineuse, votre code de démarrage peut devenir beaucoup plus lourd que cela. Inutile de dire que cela rend difficile la maintenance du code.

Pour résoudre ce problème, nous avons besoin d’une application d’injection de dépendance qui lit un fichier XML et crée tous les objets nécessaires au lancement de l’application. Les objets seraient alors sérialisés et écrits dans un fichier. Le code de démarrage lirait alors simplement ce fichier et créerait directement les objets. Cela rend votre code de démarrage aussi simple que:

 $ objectFilePath = "/ chemin / vers / sérialisé / objet / fichier"; $ di = unserialize (file_get_contents ($ objectFilePath));

Logiciel d'injection de dépendance Open Source

La plupart des entreprises n'ont pas beaucoup de budget pour créer des outils, tels qu'un cadre d'injection de dépendance. Cependant, vous pouvez trouver de nombreuses solutions libres et open source sur le Web. Symfony2 utilise un composant DI très solide basé sur Java Spring. Cependant, je couvrirai la programmation d'une solution d'injection de dépendance dans un avenir proche, si cela vous intéresse. Restez à l'écoute!


Développements PHP et injection de dépendance

Je ne veux pas généraliser, mais, en raison de sa popularité, de nombreux développeurs PHP sont des passionnés qui aiment mixer PHP et HTML..

Normalement, ces développeurs ne planifient pas leur projet. ils veulent juste écrire du code rapidement pour "faire avancer les choses".

Je crois que le recrutement de ces types de développeurs est la pire chose qu'un gestionnaire puisse faire. En soulignant l’importance de l’injection de dépendance, vous pouvez désintéresser ces "pirates" de votre entreprise, tout en incitant de bons développeurs à travailler pour votre entreprise. En d’autres termes, votre projet attirera de bons développeurs seniors, ce qui est la ressource la plus importante qu’une société de développement logiciel puisse acquérir.!


Quand utiliser l'injection de dépendance

L'injection de dépendance est très utile lorsque vous travaillez sur des projets à long terme.

D'après mes expériences, l'injection de dépendance est très utile lorsque vous travaillez sur des projets à long terme - des projets activement développés et maintenus sur une longue période. Cela réduit considérablement vos coûts et attire les meilleurs développeurs. Mais, comme je l’ai déjà mentionné, si vous avez besoin d’une application de démonstration pour obtenir un contrat ou un financement, je vous recommande de creuser dans le code. Si vous suivez ce chemin, sachez toutefois que la démo devra être jetée une fois le contrat et / ou le financement acquis..


L'heure du conte!

J'adore les histoires de développeurs qui veulent faire ce qu'il faut, mais leurs collègues veulent renoncer aux meilleures pratiques et faire avancer un projet le plus rapidement possible. Quelles sont vos pensées sur l'injection de dépendance? Une complication excessive ou une exigence pour toute application durable?