Terme technique pour désigner l'opposé de l'injection de dépendance?

12

Il s'agit plus d'une nomenclature (rédaction technique) que d'une question purement technique. J'essaie d'écrire une proposition de refactoring (et de me l'attribuer) centrée sur l'expansion de l'injection de dépendance dans notre application. Bien que nous utilisions Spring pour le câblage automatique des beans, il existe encore des cas qui instancient les beans en utilisant MyClass obj = new MyClass(...), qui pourraient être totalement injectés. Je voudrais que ma proposition utilise une nomenclature élégante et fasse référence au modèle de conception opposé à DI avec un terme approprié.

Le «couplage serré» est-il un terme adéquat qui représente un antonyme de DI?

amphibient
la source
1
Oui, le couplage décrit à la fois l'acte d'utiliser des noms de classe explicites dans d'autres classes et l'état résultant d'une base de code.
Kilian Foth
11
Non, le couplage étroit ne décrit que la propriété du code résultant, pas l'opposé de DI. Vous pouvez utiliser DI et avoir toujours un couplage serré pour des raisons complètement différentes.
Doc Brown
1
Convenu que DI et couplage serré ne sont pas opposés .
Eric King
@EricKing montre. +1 au fait.
candied_orange
1
"Aspiration de dépendance" .
SeldomNeedy

Réponses:

30

Non. Un couplage serré est bien plus que ce dont traite l'injection de dépendance.

L'injection de dépendance externalise une décision de mise en œuvre. Cela va un long chemin à découpler, mais le couplage est plus que cela.

Un bon antonyme pour l'injection de dépendances est le codage en dur d'une dépendance . Lorsque vous construisez (utilisez new ou utilisez directement une usine) à l'intérieur d'un objet de comportement, vous avez fusionné deux préoccupations différentes. Un localisateur de service permet de découpler mais vous laisse couplé au localisateur de service lui-même.

Le couplage est plus que la simple séparation de la construction et du comportement. Si j'ai 101 méthodes qui doivent être appelées dans un ordre particulier de la classe A à la classe B, je suis étroitement couplé. Peu importe à quel point la construction et le comportement sont merveilleusement séparés.

Le couplage est une mesure de l'interdépendance des deux objets. Tout ce qui contribue à rendre difficile la modification de l'un sans impacter l'autre contribue au couplage. L'injection de dépendance aide à cela, mais ce n'est pas tout cela.

candied_orange
la source
Oui, le codage en dur (une dépendance), par opposition à l'injection (au moment de l'exécution) est exactement ce que j'allais suggérer, vous étiez juste un peu plus rapide que moi.
Doc Brown
7
@DocBrown J'aimerais parfois que cet endroit ne mette pas autant l'accent sur la rapidité. J'aimerais savoir comment vous le dites.
candied_orange
Bonne réponse - l'injection de dépendance n'implique pas de découplage. Croire autrement mène sur une mauvaise route
Ant P
1
@CandiedOrange Peut-être que quelqu'un devrait suggérer dans la méta que les réponses restent cachées pendant un certain temps. Et / ou que les votes soient cachés au public pendant des Nheures ... Ou jusqu'à ce qu'une réponse soit sélectionnée. Je sais que je ne suis pas entièrement objectif lorsqu'une réponse a déjà 10 votes et les 5 autres réponses n'en ont pas!
svidgen
1
@svidgen recherche "l'arme la plus rapide de l'ouest" sur meta. Le problème a déjà une longue histoire.
candied_orange
6

À strictement parler, l' injection de dépendance ne s'oppose vraiment que PAS à l' injection de dépendance - et donc à toute stratégie de gestion des dépendances qui n'est pas l' injection de dépendance.

Le couplage [indésirable], bien qu'il ne s'agisse pas exactement d'un problème orthogonal, peut se produire ou être atténué de toute façon. Ces deux éléments sont couplés à DependencyClass:

public DependencyInjectedConstructor(DependencyClass dep) {
  dep.do();
}

public DependencyLookupConstructor() {
  var dep = new DependencyClass();
  dep.do();
}

DependencyLookupConstructorest couplé à un particulier DependencyClassdans ce cas. Mais, ils sont tous deux couplés à DependencyClass. Le vrai mal, s'il y en a un ici, n'est pas nécessairement le couplage, c'est qu'il DependencyLookupConstructordoit changer si DependencyClasssoudainement besoin de ses propres dépendances injectées 1 .

Cependant, ce constructeur / classe est encore plus faiblement couplé:

public DependencyLocatingConstructor() {
  var dep = ServiceLocator.GetMyDoer();
  dep.do();
}

Si vous travaillez en C #, la volonté ci - dessus permettra à votre ServiceLocatorretourner quoi que ce soit quand GetMyDoer()est invoqué, tant qu'il a peut do()ce l' DependencyLocatingConstructora do(). Vous bénéficiez de la validation de la signature au moment de la compilation sans même être couplé à une interface complète 2 .

Alors, choisissez votre poison.

Mais fondamentalement, s'il y a un «opposé» concret à l'injection de dépendance, ce serait autre chose dans le domaine des «stratégies de gestion de la dépendance». Entre autres, si vous avez utilisé l'un des éléments suivants dans la conversation, je le reconnais comme n'étant PAS une injection de dépendance:

  • Modèle de localisateur de service
  • Localisateur / emplacement de dépendance
  • Construction directe objet / dépendance
  • Dépendance cachée
  • "Pas d'injection de dépendance"

1. Ironiquement, certains des problèmes que DI résout à des niveaux plus élevés sont en quelque sorte le résultat de [l'utilisation excessive] de DI dans les niveaux inférieurs. J'ai eu le plaisir de travailler sur des bases de code avec une complexité inutile partout en raison de l'adaptation à la poignée d'endroits où cette complexité a réellement aidé ... Je suis certes biaisé par une mauvaise exposition.

2. L'utilisation de l'emplacement du service vous permet également de spécifier facilement différentes dépendances du même type par leur rôle fonctionnel à partir du code appelant , tout en restant largement indépendant de la façon dont la dépendance est créée. Supposons que vous ayez besoin de résoudre Userou IUserà des fins différentes: par exemple, Locator.GetAdministrator()contre Locator.GetAuthor()- ou autre chose. Mon code peut demander ce dont il a besoin fonctionnellement sans même savoir quelles interfaces il prend en charge.

svidgen
la source
2
Le salut pour DependencyInjectedConstructor(DependencyClass dep)est que DependencyClass pourrait être une interface ou une classe abstraite. C'est pourquoi cela me rend triste que les codeurs C # utilisent un préfixe d'interface, comme dans IDependency. En tant que client, ce n'est vraiment pas mon affaire de savoir ce qu'est la dépendance. Tant que je ne le construis pas, tout ce que je dois savoir, c'est comment lui parler. Ce que c'est, c'est le problème de quelqu'un d'autre.
candied_orange
Points d' être, DI encore les couples vous à cette interface, et il n'a pas besoin que d'utiliser DependencyClassune interface abstraite du tout. Il suffit que la logique de construction / configuration / localisation existe «ailleurs». ... Eh bien, et plus pertinemment à la question, le fait est que DI n'est pas "l'opposé du couplage serré" :)
svidgen
En fait ... Je suis peut-être légèrement hors limites en disant que DI vous couple nécessairement à une interface, même en C #. Bien que je les ai évités en C #, j'ai l'impression de pouvoir également accepter des dynamicparamètres. (Mais pas les varparamètres, si la mémoire sert.) Donc, avec DI en C #, je pense que je dois soit coder contre une interface, soit je dois totalement renoncer à la validation au moment de la compilation.
svidgen
Les objets sont couplés aux interfaces. Que vous utilisiez ou non le mot-clé d'interface. Voilà ce qu'est une bonne interface. Tout ce à quoi vous devez être couplé. Ce que vous résumez, ce sont les détails de mise en œuvre et les éléments supplémentaires dont vous n'avez pas besoin. Nous pouvons formaliser cela en utilisant le mot-clé interface pour permettre au client de dire au monde: "Tout ce dont j'ai besoin, c'est ceci". Mais nous n'avons pas à le faire. Heck nous pouvons faire la frappe de canard, bien dans certaines langues.
candied_orange
Je ne suis pas sûr que nous soyons en désaccord total. Mais, pour clarifier ... Les objets sont couplés en interne à leurs propres interfaces, oui. Mais, l'interface elle-même n'impose un couplage de dépendance que si l'interface est explicitement nommée. En C #, l'utilisation de dynamicou varet l'obtention d'un objet à partir d'un localisateur vous permettent d'ignorer l'interface et d'utiliser n'importe quelle classe dont do()vous avez besoin, que cette classe implémente une IDoerinterface ou non. En d'autres termes, si nous avons A-> B <-C, DI dissocie A de C, mais cela nécessite que A et C soient couplés à B, et empêche l'utilisation de D, même si D le fera do().
svidgen
2

Je ne sais pas s'il existe une terminologie industrielle spécifique et largement acceptée, mais les alternatives qui viennent à l'esprit incluent la création d'instances internes , la création de dépendances internes , les dépendances locales ou les dépendances de portée locale .

mcknz
la source
2
J'aime instance creation mais ce n'est pas assez précis. DI crée des instances mais au moyen du contrôleur et non au niveau de l'application. peutinternal instance creation
amphibie
1

J'irais avec l' encapsulation des dépendances . Cela exprime que la dépendance est enfermée plutôt que de visiter et de repartir.

Martin Maat
la source