Étant donné un constructeur qui n'aura jamais, jamais besoin d'utiliser des implémentations différentes de plusieurs objets qu'il initialise, est-il toujours pratique d'utiliser DI? Après tout, nous pourrions toujours vouloir faire un test unitaire.
La classe en question initialise quelques autres classes dans son constructeur et les classes qu'elle utilise sont assez spécifiques. Il n'utilisera jamais une autre implémentation. Sommes-nous justifiés d'éviter d'essayer de programmer sur une interface?
Réponses:
Cela dépend du degré de certitude que "jamais, jamais" est correct (pendant la durée d'utilisation de votre application).
En général:
la source
Bien que l'avantage du codage par rapport à une interface soit assez évident, vous devez vous demander ce qui est exactement gagné en ne le faisant pas.
La question suivante est: fait-il partie de la responsabilité de la classe en question de choisir les implémentations ou non? Cela peut ou non être le cas et vous devez agir en conséquence.
En fin de compte, il est toujours possible qu'une contrainte maladroite sorte de nulle part. Vous souhaiterez peut-être exécuter le même morceau de code simultanément, et la possibilité d'injecter l'implémentation pourrait aider à la synchronisation. Ou après avoir profilé votre application, vous découvrirez peut-être que vous souhaitez une stratégie d'allocation différente de l'instanciation ordinaire. Ou des préoccupations transversales surgissent et vous n'avez pas de support AOP à portée de main. Qui sait?
YAGNI suggère que lors de l'écriture de code, il est important de ne rien ajouter de superflu. L'une des choses que les programmeurs ont tendance à ajouter à leur code sans même s'en rendre compte, ce sont les hypothèses superflues. Comme "cette méthode pourrait être utile" ou "cela ne changera jamais". Les deux ajoutent de l'encombrement à votre conception.
la source
Cela dépend de divers paramètres mais voici quelques raisons pour lesquelles vous pouvez toujours vouloir utiliser DI:
Bottom line: vous pouvez probablement vivre sans DI dans ce cas, mais il y a des chances que l'utilisation de DI aboutisse à un code plus propre.
la source
Lorsque vous concevez un programme ou une fonctionnalité, une partie du processus de réflexion devrait être de savoir comment vous allez le tester. L'injection de dépendance est l'un des outils de test et doit être considérée comme faisant partie du mélange.
Les avantages supplémentaires de l'injection de dépendances et de l'utilisation d'interfaces au lieu de classes sont également bénéfiques lorsqu'une application est étendue, mais ils peuvent également être adaptés ultérieurement au code source plus facilement et en toute sécurité en utilisant la recherche et le remplacement. - même sur de très gros projets.
la source
De nombreuses réponses à cette question peuvent être débattues comme «vous en aurez peut-être besoin parce que…» comme YAGNI si vous ne voulez pas faire de test.
Si vous demandez quelles raisons, à côté des unités, doivent être programmées sur une interface
Oui , l'injection de dépendance en vaut la peine en dehors de UnitTesting si vous avez besoin d'une inversion de contrôle . Par exemple, si une implémentation d'un module a besoin d'un autre module qui n'est pas accessible dans sa couche.
Exemple: si vous avez les modules
gui
=>businesslayer
=>driver
=>common
.Dans ce scénario
businesslayer
peut utiliserdriver
maisdriver
ne peut pas utiliserbusinesslayer
.Si
driver
vous avez besoin de fonctionnalités de niveau supérieur, vous pouvez implémenter cette fonctionnalité dansbusinesslayer
laquelle implémente une interface encommon
couche.driver
il suffit de connaître l'interface encommon
couche.la source
Oui, vous êtes - tout d'abord, oubliez les tests unitaires comme une raison de concevoir votre code autour des outils de test unitaire, ce n'est jamais une bonne idée de plier la conception de votre code pour l'adapter à une contrainte artificielle. Si vos outils vous obligent à le faire, procurez-vous de meilleurs outils (par exemple, Microsoft Fakes / Moles qui vous offrent beaucoup plus d'options pour créer des objets fictifs).
Par exemple, diviseriez-vous vos classes en méthodes uniquement publiques simplement parce que les outils de test ne fonctionnent pas avec des méthodes privées? (Je sais que la sagesse qui prévaut est de prétendre que vous n'avez pas besoin de tester des méthodes privées, mais je pense que c'est une réaction à la difficulté de le faire avec les outils actuels, pas une véritable réaction au fait de ne pas avoir besoin de tester des particuliers).,
Dans l'ensemble, cela se résume à quel type de TDDer vous êtes - le "mockist" comme Fowler les décrit , doit changer le code en fonction des outils qu'ils utilisent, tandis que les testeurs "classiques" créent des tests qui sont plus d'intégration dans la nature (c.-à-d. tester la classe en tant qu'unité, pas chaque méthode) donc il y a moins besoin d'interfaces, surtout si vous utilisez les outils qui peuvent se moquer des classes concrètes.
la source
L' injection de dépendance rend également plus clair que votre objet A dépendances.
Lorsque quelqu'un d'autre va utiliser votre objet naïvement (sans regarder le constructeur), il trouvera qu'il devra configurer des services, des connexions, etc. Ce n'était pas évident car ils n'avaient pas à les transmettre au constructeur . La transmission des dépendances rend plus clair ce qui est nécessaire.
Vous cachez également potentiellement le fait que votre classe peut violer SRP. Si vous passez de nombreuses dépendances (plus de 3), votre classe en fait peut-être trop et doit être refactorisée. Mais si vous les créez dans le constructeur, cette odeur de code sera masquée.
la source
Je suis d'accord avec les deux camps ici et la question est toujours ouverte à un débat à mon avis. YAGNI exige que je ne m'attaque pas à changer mon code pour l'adapter à la supposition. Les tests unitaires ne sont pas un problème ici parce que je crois fermement que la dépendance ne changera jamais. Mais si j'avais fait des tests unitaires comme prévu au départ, je ne serais jamais arrivé à ce point de toute façon. Comme j'aurais fini par me frayer un chemin dans DI.
Permettez-moi de proposer une autre alternative pour mon scénario en particulier
Avec un modèle d'usine, je peux localiser les dépendances en un seul endroit. Lors des tests, je peux changer l'implémentation en fonction du contexte, et c'est assez bien. Cela ne va pas à l'encontre de YAGNI en raison des avantages d'abstraction de plusieurs constructions de classe.
la source