Quels sont les avantages d'utiliser Dependency Injection et IoC Containers?

62

Je prévois de faire un exposé sur l’injection de dépendance et les conteneurs IoC, et j’espère trouver de bons arguments pour l’utiliser.

Quels sont les principaux avantages de l’utilisation de cette technique et de ces outils?

Andy Lowry
la source
1
Voir ici et ici pour les réponses StackOverflow et ici pour un bon article complet sur IoC. Et si vous voulez des arguments contre la comparaison, rendez-vous à SO.
Jesse C. Slicer
14
ne pas être un crétin ... mais si vous ne savez pas pourquoi DI / CIO devrait être utilisé, pourquoi en parlez-vous? perdre un pari? ;-)
Steven A. Lowe
2
@ Steven, son patron lui aurait peut-être demandé de le faire.
1
@ Steven, j'utilise déjà DI tout le temps (certains diraient trop souvent :-D), je cherche juste de bons arguments pour inciter d'autres personnes à l'utiliser.
Andy Lowry
2
Les gens parlent rarement de la surutilisation de DI. Si vous retardez chaque décision, vous créez l'équivalent OO du code spaghetti. Avoir une conception cohérente nécessite qu’à un moment donné, une vraie décision soit prise.
Macneil

Réponses:

47

Le plus important pour moi est de faciliter le respect du principe de responsabilité unique .

DI / IoC simplifie la gestion des dépendances entre les objets. En retour, cela me facilite la tâche de casser une fonctionnalité cohérente dans son propre contrat (interface). En conséquence, mon code a été beaucoup plus modularisé depuis que j'ai découvert DI / IoC.

Un autre résultat est que je peux beaucoup plus facilement me rendre à une conception qui prend en charge le principe d'ouverture / fermeture . C'est l'une des techniques les plus inspirantes de confiance (juste après les tests automatisés). Je doute que je puisse épouser suffisamment les vertus du principe ouvert-fermé.

DI / IoC est l’un des rares éléments de ma carrière de programmeur à avoir «changé la donne». Il y a un énorme écart de qualité entre le code que j'ai écrit avant et après l'apprentissage de DI / IoC. Permettez-moi de souligner cela un peu plus. Amélioration énorme de la qualité du code.

Quentin Starin
la source
3
Pourquoi le principe d'ouverture-fermeture est-il si important? Si vous estimez avoir besoin de changer une API / interface, pourquoi pas vous?
Arne Evertsson
@ArneEvertsson Écoutez Robert C. Martin parler du principe d'ouverture-fermeture. Vous serez éclairé.
Alternatex
@AmeEvertsson Open-Closed est très important lorsque votre code est fourni (par exemple, en tant que produit commercial) en tant que module destiné à être utilisé par d'autres utilisateurs, car il rend votre code plus adaptable dans son utilisation sans qu'il ne vous soit demandé de le modifier
James Ellis-Jones
2
DI ne simplifie pas la gestion des dépendances car il est beaucoup plus complexe que de créer une dépendance à une classe concrète. Il offre cependant une certaine flexibilité, mais à moins que vous ne fassiez des tests unitaires «appropriés», cette flexibilité ne sera souvent pas nécessaire. Les deux avantages clés décrits s'appliquent également à Service Locator, qui est plus simple.
James Ellis-Jones
1
J'ai voté contre cette réponse il y a des années; Voici quelques remarques: 1) En pratique, une utilisation intensive de DI tend à contrer SRP, car les programmeurs continuent simplement d’ajouter des méthodes à leurs "contrôleurs", "services", "DAO", etc. injectés, au lieu de créer de nouvelles classes pour nouvelle fonctionnalité. C'est ce que vous voyez normalement dans les projets Java et C # .NET qui utilisent un framework ou un conteneur DI. 2) Le principe ouvert-fermé était juste l'illusion de Bertrand Meyer sur l'utilité de l'héritage de classe (implémentation); si vous le recherchez dans son livre de plus de 1400 pages, vous verrez ce que je veux dire - c'est vraiment idiot.
Rogério
9

Les exemples qui m'ont réellement ouvert les yeux ont montré comment il était possible de tester facilement les objets créés de cette manière. Avant cela, j'avais de la difficulté à isoler des objets pour un test unitaire. J'écrivais souvent des tests pour interagir avec un système beaucoup plus grand. C'était vraiment difficile parce que le système dans son ensemble était beaucoup moins prévisible et beaucoup plus susceptible de changer que les composants individuels.

Winston Ewert
la source
3

Les avantages des injections de dépendance sont les suivants:

  1. Votre code est propre et plus lisible.
  2. Les codes sont faiblement couplés.
  3. Plus réutilisable que les implémentations sont configurées dans le fichier XML, il peut être utilisé dans un contexte différent.
  4. Le code peut être facilement testable avec différentes implémentations factices.
Solaimani SA
la source
1

Je pense que les avantages réels sont plus politiques que techniques. DI est simplement une alternative au modèle Service Locator , rien de plus. En soi, cela ne facilite pas le respect de principes tels que SRP ou OCP, ni le découplage des couches. D'autres personnes interrogées ici confondent différents concepts et techniques, IMO.

Vous pouvez atteindre les mêmes objectifs en matière de cohésion élevée et de couplage faible en utilisant des localisateurs de services ou en instanciant simplement des dépendances directement, le cas échéant (ce qui est le plus souvent le cas).

Maintenant, je sais que beaucoup seront en désaccord avec cette opinion. Je serai heureux de discuter des exemples concrets.

Rogério
la source
2
Mais invoquer directement un localisateur de service ou instancier une dépendance concrète fixe généralement vos dépendances, ou du moins la provenance de vos dépendances. Cela semble aller à l'encontre de l'objectif de DI. Vous devez également injecter le localisateur de services.
Matt H
L'utilisation d'un localisateur de service ne cable rien, sauf l'utilisation de la classe de localisateur de service elle-même, qui n'est normalement pas "injectée". L'instanciation d'une classe d'implémentation concrète convient parfaitement dans les cas où vous n'avez pas besoin de configuration externe (par exemple, les programmeurs instancient généralement directement la classe ArrayList au lieu d'utiliser DI, ce qui entraînerait une surcharge).
Rogério
1
Vous parlez de "couplage faible" et plus tard, vous dites qu'un localisateur de service n'a aucun impact sur le niveau de couplage d'une application. De même pour instancier des collaborateurs directement sur le code, je ne vois pas de moyen plus parfait de coupler un objet à ses dépendances. Comment testez-vous les deux scénarios? Je suis respectueusement complètement en désaccord avec tout ce que vous avez dit.
Clint Eastwood
@ Jonathan Vous devriez lire l' article qui a ensuite présenté DI ; l'auteur conclut en affirmant que DI et ServiceLocator sont "à peu près équivalents", avec un "léger avantage" pour ce dernier. Le couplage qui importe est entre un composant et d'autres composants pouvant avoir plusieurs implémentations; un ServiceLocator est un service d'infrastructure avec une seule implémentation, donc ça va. Notez que j'ai écrit "instancier des dépendances chaque fois que cela est applicable "; Bien sûr, si vous devez séparer la configuration de l’utilisation, vous ne le feriez pas.
Rogério
1
@ Jonathan En ce qui concerne les tests unitaires, l'instanciation de collaborateurs empêche la création de tels tests. il existe des outils de moquage bien connus qui isolent une classe des implémentations de dépendance, qu'elles soient injectées ou non.
Rogério
-1

Lorsque DI est utilisé pour exposer des objets internes à des fins de test, le motif a été utilisé de manière abusive.

Thomas-Peter
la source
1
qu'entendez-vous par "objets intérieurs"? dans la réalité OOP (notez que seulement 1% des programmeurs savent ce que cela signifie réellement), il existe des objets qui communiquent les uns avec les autres par l'envoi de messages (par exemple, des invocations de méthodes). En ce sens, chaque objet doit avoir une responsabilité unique, il n'y a pas d'objets "plus importants" que les autres ... chacun d'entre eux a un devoir unique et ils coopèrent pour réaliser la fonctionnalité fournie par l'ensemble du système. Il est important de tester chaque objet de manière isolée pour que nous sachions que nous n'avons manqué aucun cas, c'est pourquoi DI est vraiment doué.
Clint Eastwood
J'ai oublié.
thomas-peter