J'utilise Dependency Injection (DI) depuis un certain temps, injectant soit dans un constructeur, une propriété ou une méthode. Je n'ai jamais ressenti le besoin d'utiliser un conteneur d'inversion de contrôle (IoC). Cependant, plus je lis, plus je ressens de pression de la part de la communauté pour utiliser un conteneur IoC.
J'ai joué avec des conteneurs .NET comme StructureMap , NInject , Unity et Funq . Je n'arrive toujours pas à voir comment un conteneur IoC va bénéficier / améliorer mon code.
J'ai aussi peur de commencer à utiliser un conteneur au travail parce que beaucoup de mes collègues verront du code qu'ils ne comprennent pas. Beaucoup d'entre eux peuvent être réticents à apprendre de nouvelles technologies.
Veuillez me convaincre que je dois utiliser un conteneur IoC. Je vais utiliser ces arguments lorsque je parlerai à mes collègues développeurs au travail.
Réponses:
Wow, je ne peux pas croire que Joel favoriserait ceci:
sur ceci:
Beaucoup de gens ne réalisent pas que votre chaîne de dépendances peut devenir imbriquée, et il devient rapidement difficile de les câbler manuellement. Même avec des usines, la duplication de votre code n'en vaut pas la peine.
Les conteneurs IoC peuvent être complexes, oui. Mais pour ce cas simple, j'ai montré que c'est incroyablement facile.
D'accord, justifions cela encore plus. Supposons que vous ayez des entités ou des objets de modèle que vous souhaitez lier à une interface utilisateur intelligente. Cette interface utilisateur intelligente (nous l'appellerons Shindows Morms) souhaite que vous implémentiez INotifyPropertyChanged afin qu'il puisse effectuer le suivi des modifications et mettre à jour l'interface utilisateur en conséquence.
"OK, ça ne semble pas si difficile", alors vous commencez à écrire.
Vous commencez par ceci:
..et finir avec ceci :
C'est du code de plomberie dégoûtant, et je maintiens que si vous écrivez du code comme ça à la main, vous volez votre client . Il existe une façon de travailler meilleure et plus intelligente.
Jamais entendu ce terme, travailler plus intelligemment, pas plus dur?
Eh bien, imaginez qu'un gars intelligent de votre équipe est venu et a dit: "Voici un moyen plus simple"
Si vous rendez vos propriétés virtuelles (calmez-vous, ce n'est pas si grave), nous pouvons automatiquement intégrer ce comportement de propriété. (Cela s'appelle AOP, mais ne vous inquiétez pas pour le nom, concentrez-vous sur ce qu'il va faire pour vous)
Selon l'outil IoC que vous utilisez, vous pouvez faire quelque chose qui ressemble à ceci:
Pouf! Tout ce manuel INotifyPropertyChanged BS est maintenant généré automatiquement pour vous, sur chaque configurateur de propriété virtuelle de l'objet en question.
Est-ce magique? OUI ! Si vous pouvez faire confiance au fait que ce code fait son travail, vous pouvez ignorer en toute sécurité toute cette propriété enveloppant mumbo-jumbo. Vous avez des problèmes commerciaux à résoudre.
Quelques autres utilisations intéressantes d'un outil IoC pour faire de l'AOP:
la source
Je suis avec toi, Vadim. Les conteneurs IoC prennent un concept simple, élégant et utile, et en font quelque chose que vous devez étudier pendant deux jours avec un manuel de 200 pages.
Personnellement, je suis perplexe sur la façon dont la communauté IoC a pris un bel article élégant de Martin Fowler et l'a transformé en un tas de cadres complexes, généralement avec des manuels de 200 à 300 pages.
J'essaie de ne pas porter de jugement (HAHA!), Mais je pense que les personnes qui utilisent des conteneurs IoC sont (A) très intelligentes et (B) manquent d'empathie pour les personnes qui ne sont pas aussi intelligentes qu'eux. Tout est parfaitement logique pour eux, ils ont donc du mal à comprendre que de nombreux programmeurs ordinaires trouveront les concepts déroutants. C'est la malédiction du savoir . Les gens qui comprennent les conteneurs IoC ont du mal à croire qu'il y a des gens qui ne le comprennent pas.
L'avantage le plus précieux de l'utilisation d'un conteneur IoC est que vous pouvez avoir un commutateur de configuration en un seul endroit qui vous permet de basculer entre, disons, le mode test et le mode production. Par exemple, supposons que vous ayez deux versions de vos classes d'accès à la base de données ... une version qui s'est connectée de manière agressive et a fait beaucoup de validation, que vous avez utilisée pendant le développement, et une autre version sans journalisation ou validation qui était incroyablement rapide pour la production. C'est agréable de pouvoir basculer entre eux en un seul endroit. D'un autre côté, il s'agit d'un problème assez trivial, facile à gérer de manière plus simple sans la complexité des conteneurs IoC.
Je crois que si vous utilisez des conteneurs IoC, votre code devient, franchement, beaucoup plus difficile à lire. Le nombre d'endroits que vous devez regarder pour comprendre ce que le code essaie de faire augmente d'au moins un. Et quelque part dans le ciel, un ange crie.
la source
Vraisemblablement, personne ne vous oblige à utiliser un cadre de conteneur DI. Vous utilisez déjà DI pour découpler vos classes et améliorer la testabilité, vous bénéficiez donc de nombreux avantages. Bref, vous privilégiez la simplicité, ce qui est généralement une bonne chose.
Si votre système atteint un niveau de complexité où la DI manuelle devient une corvée (c'est-à-dire augmente la maintenance), pesez cela par rapport à la courbe d'apprentissage d'équipe d'un cadre de conteneur DI.
Si vous avez besoin de plus de contrôle sur la gestion de la durée de vie des dépendances (c'est-à-dire si vous ressentez le besoin d'implémenter le modèle Singleton), regardez les conteneurs DI.
Si vous utilisez un conteneur DI, utilisez uniquement les fonctionnalités dont vous avez besoin. Ignorez le fichier de configuration XML et configurez-le en code si cela est suffisant. Tenez-vous à l'injection du constructeur. Les bases de Unity ou StructureMap peuvent être condensées en quelques pages.
Il y a un excellent article de blog de Mark Seemann à ce sujet: Quand utiliser un conteneur DI
la source
À mon avis, l'avantage numéro un d'un IoC est la possibilité de centraliser la configuration de vos dépendances.
Si vous utilisez actuellement l'injection de dépendances, votre code pourrait ressembler à ceci
Si vous avez utilisé une classe IoC statique, contrairement aux fichiers de configuration, à mon humble avis, les plus confus, vous pourriez avoir quelque chose comme ceci:
Ensuite, votre classe Static IoC ressemblerait à ceci, j'utilise Unity ici.
la source
Les conteneurs IoC sont également utiles pour charger des dépendances de classe profondément imbriquées. Par exemple, si vous disposiez du code suivant à l'aide de l'injection de dépendances.
Si vous aviez toutes ces dépendances chargées dans le conteneur IoC, vous pourriez résoudre le service client et toutes les dépendances enfants seront automatiquement résolues.
Par exemple:
la source
Je suis un fan de la programmation déclarative (regardez le nombre de questions SQL auxquelles je réponds), mais les conteneurs IoC que j'ai examinés semblent trop mystérieux pour leur propre bien.
... ou peut-être que les développeurs de conteneurs IoC sont incapables d'écrire une documentation claire.
... ou bien les deux sont vrais à un degré ou à un autre.
Je ne pense pas que le concept d'un conteneur IoC soit mauvais. Mais l'implémentation doit être à la fois suffisamment puissante (c'est-à-dire flexible) pour être utile dans une grande variété d'applications, mais simple et facile à comprendre.
C'est probablement six d'un et une demi-douzaine de l'autre. Une application réelle (pas un jouet ou une démo) est forcément complexe, représentant de nombreux cas d'angle et des exceptions aux règles. Soit vous encapsulez cette complexité en code impératif, soit en code déclaratif. Mais vous devez le représenter quelque part.
la source
L'utilisation d'un conteneur consiste principalement à passer d'un style d'initialisation et de configuration impératif / scripté à un style déclaratif . Cela peut avoir quelques effets bénéfiques différents:
Bien sûr, il peut y avoir des difficultés:
la source
Il me semble que vous avez déjà construit votre propre conteneur IoC (en utilisant les différents modèles décrits par Martin Fowler) et vous demandez pourquoi l'implémentation de quelqu'un d'autre est meilleure que la vôtre.
Donc, vous avez un tas de code qui fonctionne déjà. Et vous vous demandez pourquoi vous voudriez le remplacer par l'implémentation de quelqu'un d'autre.
Avantages pour envisager un conteneur IoC tiers
Les inconvénients
Alors, pesez vos avantages contre vos inconvénients et prenez une décision.
la source
Je pense que la plupart de la valeur d'un IoC est obtenue en utilisant DI. Puisque vous le faites déjà, le reste de l'avantage est progressif.
La valeur que vous obtiendrez dépendra du type d'application sur laquelle vous travaillez:
Pour les locataires multiples, le conteneur IoC peut prendre en charge une partie du code d'infrastructure pour charger différentes ressources client. Lorsque vous avez besoin d'un composant spécifique au client, utilisez un sélecteur personnalisé pour gérer la logique et ne vous en faites pas à partir de votre code client. Vous pouvez certainement le créer vous-même, mais voici un exemple de la façon dont une IoC peut vous aider.
Avec de nombreux points d'extensibilité, l'IoC peut être utilisé pour charger des composants à partir de la configuration. C'est une chose courante à construire mais les outils sont fournis par le conteneur.
Si vous souhaitez utiliser AOP pour certaines préoccupations transversales, l' IoC fournit des crochets pour intercepter les appels de méthode. Cela se fait moins souvent ad-hoc sur des projets, mais l'IoC le facilite.
J'ai déjà écrit des fonctionnalités comme celle-ci, mais si j'ai besoin de ces fonctionnalités maintenant, je préfère utiliser un outil prédéfini et testé s'il correspond à mon architecture.
Comme mentionné par d'autres, vous pouvez également configurer de manière centralisée les classes que vous souhaitez utiliser. Bien que cela puisse être une bonne chose, cela a un coût de mauvaise direction et de complication. Les composants de base pour la plupart des applications ne sont pas beaucoup remplacés, de sorte que le compromis est un peu plus difficile à faire.
J'utilise un conteneur IoC et j'apprécie la fonctionnalité, mais je dois admettre que j'ai remarqué le compromis: mon code devient plus clair au niveau de la classe et moins clair au niveau de l'application (c'est-à-dire la visualisation du flux de contrôle).
la source
Je suis un dépendant du CIO. J'ai du mal à justifier l'utilisation d'IOC pour DI dans la plupart des cas de nos jours. Les conteneurs IOC sacrifient la vérification du temps de compilation et, en retour, vous offrent une configuration "facile", une gestion complexe de la durée de vie et la découverte à la volée des dépendances lors de l'exécution. Je trouve que la perte de vérification du temps de compilation et la magie / exceptions qui en résultent ne valent pas les cloches et les sifflets dans la grande majorité des cas. Dans les applications de grande entreprise, il peut être très difficile de suivre ce qui se passe.
Je n'achète pas l'argument de la centralisation car vous pouvez également centraliser très facilement la configuration statique en utilisant une fabrique abstraite pour votre application et en reportant religieusement la création d'objet à la fabrique abstraite, c'est-à-dire faire une DI appropriée.
Pourquoi ne pas faire une DI statique sans magie comme ceci:
Votre configuration de conteneur est votre implémentation d'usine abstraite, vos enregistrements sont des implémentations de membres abstraits. Si vous avez besoin d'une nouvelle dépendance singleton, ajoutez simplement une autre propriété abstraite à la fabrique abstraite. Si vous avez besoin d'une dépendance transitoire, ajoutez simplement une autre méthode et injectez-la en tant que Func <>.
Avantages:
Je recommande aux sceptiques de faire un prochain projet de champ vert et de vous demander honnêtement à quel moment vous avez besoin du conteneur. Il est facile de prendre en compte un conteneur IOC plus tard, car vous remplacez simplement une implémentation d'usine par un module de configuration de conteneur IOC.
la source
Le plus grand avantage de l'utilisation de conteneurs IoC pour moi (personnellement, j'utilise Ninject) a été d'éliminer le passage des paramètres et d'autres types d'objets d'état global.
Je ne programme pas pour le Web, le mien est une application console et, à de nombreux endroits, profondément dans l'arborescence d'objets, j'ai besoin d'avoir accès aux paramètres ou aux métadonnées spécifiés par l'utilisateur qui sont créés sur une branche complètement distincte de l'arborescence d'objets. Avec IoC, je dis simplement à Ninject de traiter les paramètres comme un singleton (car il n'y en a toujours qu'une seule), demande les paramètres ou le dictionnaire dans le constructeur et hop ... ils apparaissent comme par magie quand j'en ai besoin!
Sans utiliser un conteneur IoC, je devrais transmettre les paramètres et / ou les métadonnées à travers 2, 3, ..., n objets avant qu'il ne soit réellement utilisé par l'objet qui en avait besoin.
Les conteneurs DI / IoC présentent de nombreux autres avantages, comme d'autres personnes l'ont expliqué ici.Le passage de l'idée de créer des objets à la demande d'objets peut être époustouflant, mais l'utilisation de DI a été très utile pour moi et mon équipe, alors vous pouvez peut-être l'ajouter à votre arsenal!
la source
Les frameworks IoC sont excellents si vous voulez ...
... jetez la sécurité de type. De nombreux (tous?) Frameworks IoC vous obligent à exécuter le code si vous voulez être certain que tout est correctement connecté. "Hey! J'espère que j'ai tout configuré pour que mes initialisations de ces 100 classes n'échouent pas en production, levant des exceptions de pointeur nul!"
... jonchent votre code de globaux (les frameworks IoC sont tous destinés à changer les états globaux).
... écrivez du code pourri avec des dépendances peu claires qu'il est difficile de refactoriser car vous ne saurez jamais ce qui dépend de quoi.
Le problème avec l'IoC est que les personnes qui les utilisent écrivaient du code comme celui-ci
ce qui est évidemment imparfait car la dépendance entre Foo et Bar est câblée. Ensuite, ils ont réalisé qu'il serait préférable d'écrire du code comme
ce qui est également imparfait, mais moins évident. Dans Haskell, le type de
Foo()
serait,IO Foo
mais vous ne voulez vraiment pas laIO
partie-et devrait être un signe d'avertissement que quelque chose ne va pas avec votre conception si vous l'avez.Pour s'en débarrasser (la partie IO), obtenez tous les avantages des frameworks IoC et aucun de ses inconvénients, vous pouvez utiliser une fabrique abstraite à la place.
La bonne solution serait quelque chose comme
ou peut-être
et injecter (mais je n'appellerais pas cela injecter) Bar.
Aussi: voir cette vidéo avec Erik Meijer (inventeur de LINQ) où il dit que DI est pour les gens qui ne connaissent pas les mathématiques (et je ne pourrais pas être plus d'accord): http://www.youtube.com/watch?v = 8Mttjyf-8P4
Contrairement à M. Spolsky, je ne pense pas que les gens qui utilisent les frameworks IoC soient très intelligents - je crois simplement qu'ils ne connaissent pas les mathématiques.
la source
IBar
, il l'est en faitIO IBar
). Et oui, dans l'exemple Haskell Je ne peux pas obtenir de référence nulle.J'ai constaté que la mise en œuvre correcte de l'injection de dépendance tend à forcer les programmeurs à utiliser une variété d'autres pratiques de programmation qui aident à améliorer la testabilité, la flexibilité, la maintenabilité et l'évolutivité du code: des pratiques telles que le principe de responsabilité unique, les séparations de préoccupations et le codage contre les API. J'ai l'impression d'être obligé d'écrire des classes et des méthodes plus modulaires et plus petites, ce qui rend le code plus facile à lire, car il peut être pris en morceaux de petite taille.
Mais il a également tendance à créer des arborescences de dépendances assez grandes, qui sont beaucoup plus faciles à gérer via un framework (surtout si vous utilisez des conventions) qu'à la main. Aujourd'hui, je voulais tester quelque chose très rapidement dans LINQPad, et je me suis dit que ce serait trop compliqué de créer un noyau et de le charger dans mes modules, et j'ai fini par écrire ceci à la main:
Rétrospectivement, il aurait été plus rapide d'utiliser le framework IoC, car les modules définissent à peu près tout cela par convention.
Après avoir passé un certain temps à étudier les réponses et les commentaires sur cette question, je suis convaincu que les personnes opposées à l'utilisation d'un conteneur IoC ne pratiquent pas l'injection de véritable dépendance. Les exemples que j'ai vus sont des pratiques qui sont souvent confondues avec l'injection de dépendance. Certaines personnes se plaignent de difficultés à "lire" le code. Si cela est fait correctement, la grande majorité de votre code devrait être identique lorsque vous utilisez DI à la main comme lorsque vous utilisez un conteneur IoC. La différence devrait résider entièrement dans quelques "points de lancement" au sein de l'application.
En d'autres termes, si vous n'aimez pas les conteneurs IoC, vous ne faites probablement pas l'injection de dépendances comme cela est censé être fait.
Un autre point: l'injection de dépendances ne peut vraiment pas être faite à la main si vous utilisez la réflexion n'importe où. Bien que je déteste ce que fait la réflexion pour coder la navigation, vous devez reconnaître qu'il y a certains domaines où cela ne peut vraiment pas être évité. ASP.NET MVC, par exemple, tente d'instancier le contrôleur via une réflexion sur chaque demande. Pour faire l'injection de dépendances à la main, vous devez faire de chaque contrôleur une "racine de contexte", comme ceci:
Comparez maintenant cela avec le fait de permettre à un framework DI de le faire pour vous:
À l'aide d'un cadre DI, notez que:
ISimpleWorkflowInstanceMerger
, je peux tester qu'elle est utilisée de la manière que j'anticipe, sans avoir besoin d'une connexion à la base de données ou quoi que ce soit.ISimpleWorkflowInstanceMerger
interface. Cela me permet de diviser l'application en modules séparés et de maintenir une véritable architecture à plusieurs niveaux, ce qui rend les choses beaucoup plus flexibles.Une application Web typique aura plusieurs contrôleurs. Toute la douleur de faire DI à la main dans chaque contrôleur s'accumulera vraiment à mesure que votre application se développera. Si vous avez une application avec une seule racine de contexte, qui n'essaie jamais d'instancier un service par réflexion, ce n'est pas un problème aussi important. Néanmoins, toute application qui utilise l'injection de dépendance deviendra extrêmement coûteuse à gérer une fois qu'elle atteindra une certaine taille, à moins que vous n'utilisiez un cadre quelconque pour gérer le graphique de dépendance.
la source
Chaque fois que vous utilisez le mot-clé "new", vous créez une dépendance de classe concrète et une petite alarme devrait retentir dans votre tête. Il devient plus difficile de tester cet objet isolément. La solution consiste à programmer des interfaces et à injecter la dépendance afin que l'objet puisse être testé unitaire avec tout ce qui implémente cette interface (par exemple, des simulations).
Le problème est que vous devez construire des objets quelque part. Un modèle d'usine est une façon de déplacer le couplage hors de vos POXO (Plain Old "insérez votre langage OO ici" Objets). Si vous et vos collègues écrivez tous du code comme celui-ci, un conteneur IoC est la prochaine "amélioration incrémentielle" que vous pouvez apporter à votre base de code. Il déplacera tout ce méchant code passe-partout Factory de vos objets propres et de votre logique métier. Ils l'obtiendront et l'adoreront. Heck, donnez une conférence sur pourquoi vous l'aimez et obtenez tout le monde enthousiasmé.
Si vos collègues ne font pas encore DI, alors je vous suggère de vous concentrer sur cela en premier. Passez le mot sur la façon d'écrire du code propre facilement testable. Le code DI propre est la partie difficile, une fois que vous y êtes, le déplacement de la logique de câblage d'objet des classes Factory vers un conteneur IoC devrait être relativement trivial.
la source
Parce que toutes les dépendances sont clairement visibles, il favorise la création de composants qui sont couplés de manière lâche et en même temps facilement accessibles et réutilisables dans l'application.
la source
Vous n'avez pas besoin d' un conteneur IoC.
Mais si vous suivez rigoureusement un modèle DI, vous constaterez qu'en avoir un supprimera une tonne de code redondant et ennuyeux.
C'est souvent le meilleur moment pour utiliser une bibliothèque / un framework, de toute façon - quand vous comprenez ce qu'il fait et que vous pourriez le faire sans la bibliothèque.
la source
Il se trouve que je suis en train de retirer le code DI local et de le remplacer par un IOC. J'ai probablement supprimé bien plus de 200 lignes de code et l'ai remplacé par environ 10. Oui, j'ai dû apprendre un peu comment utiliser le conteneur (Winsor), mais je suis ingénieur travaillant sur les technologies Internet dans le 21e siècle, donc je suis habitué à cela. J'ai probablement passé environ 20 minutes à regarder les procédures. Cela valait bien mon temps.
la source
Tandis que vous continuez à découpler vos classes et à inverser vos dépendances, les classes restent petites et le "graphique des dépendances" continue de grossir. (Ce n'est pas mauvais.) L'utilisation des fonctionnalités de base d'un conteneur IoC rend le câblage de tous ces objets trivial, mais le faire manuellement peut devenir très lourd. Par exemple, que se passe-t-il si je veux créer une nouvelle instance de "Foo" mais qu'il a besoin d'un "Bar". Et un "Bar" a besoin d'un "A", "B" et "C". Et chacun d'eux a besoin de 3 autres choses, etc etc. (oui, je ne peux pas trouver de bons faux noms :)).
L'utilisation d'un conteneur IoC pour créer votre graphique d'objet à votre place réduit la complexité d'une tonne et le pousse dans une configuration unique. Je dis simplement "créez-moi un" Foo "" et il comprend ce qui est nécessaire pour en construire un.
Certaines personnes utilisent les conteneurs IoC pour beaucoup plus d'infrastructures, ce qui est bien pour les scénarios avancés, mais dans ces cas, je conviens que cela peut obscurcir et rendre le code difficile à lire et à déboguer pour les nouveaux développeurs.
la source
Idem sur l'unité. Devenez trop gros et vous pouvez entendre les grincements dans les chevrons.
Cela ne me surprend jamais lorsque les gens commencent à parler de la netteté du code IoC sont les mêmes types de gens qui ont dit à un moment donné que les modèles en C ++ étaient la manière élégante de revenir dans les années 90, mais aujourd'hui, ils les décriront comme des arcanes . Bah!
la source
Dans le monde .NET, l'AOP n'est pas trop populaire, donc pour DI un framework est votre seule vraie option, que vous en écriviez vous-même ou que vous utilisiez un autre framework.
Si vous avez utilisé AOP, vous pouvez effectuer une injection lorsque vous compilez votre application, ce qui est plus courant en Java.
L'ID présente de nombreux avantages, tels qu'un couplage réduit, ce qui facilite les tests unitaires, mais comment allez-vous l'implémenter? Voulez-vous utiliser la réflexion pour le faire vous-même?
la source
Ça fait presque 3 ans, hein?
50% de ceux qui se sont prononcés en faveur des cadres IoC ne comprennent pas la différence entre IoC et IoC Frameworks. Je doute qu'ils sachent que vous pouvez écrire du code sans être déployé sur un serveur d'applications
Si nous prenons le framework Java Spring le plus populaire, c'est la configuration IoC déplacée de XMl dans le code et qui ressemble maintenant à ceci
`@Configuration classe publique AppConfig {
} `Et nous avons besoin d'un cadre pour faire cela, pourquoi exactement?
la source
Honnêtement, je ne trouve pas qu'il y ait de nombreux cas où des conteneurs IoC sont nécessaires, et la plupart du temps, ils ajoutent simplement une complexité inutile.
Si vous l'utilisez uniquement pour simplifier la construction d'un objet, je dois vous demander si vous instanciez cet objet à plusieurs endroits? Un singleton ne conviendrait-il pas à vos besoins? Modifiez-vous la configuration au moment de l'exécution? (Changement de type de source de données, etc.).
Si oui, alors vous pourriez avoir besoin d'un conteneur IoC. Sinon, vous déplacez simplement l'initialisation de l'endroit où le développeur peut facilement la voir.
Qui a dit qu'une interface vaut mieux que l'héritage de toute façon? Imaginons que vous testiez un service. Pourquoi ne pas utiliser le constructeur DI et créer des simulations des dépendances en utilisant l'héritage? La plupart des services que j'utilise n'ont que quelques dépendances. Faire des tests unitaires de cette façon empêche de maintenir une tonne d'interfaces inutiles et signifie que vous n'avez pas besoin d'utiliser Resharper pour trouver rapidement la déclaration d'une méthode.
Je crois que pour la plupart des implémentations, dire que les conteneurs IoC suppriment le code inutile est un mythe.
Tout d'abord, il y a la configuration du conteneur en premier lieu. Il vous reste alors à définir chaque objet à initialiser. Donc, vous ne sauvegardez pas le code lors de l'initialisation, vous le déplacez (sauf si votre objet est utilisé plus d'une fois. Est-ce mieux en tant que Singleton?). Ensuite, pour chaque objet que vous avez initialisé de cette manière, vous devez créer et maintenir une interface.
Quelqu'un a un avis là dessus?
la source
ShippingCostCalculator
ouProductUIPresentation
, ou toute autre stratégie / implémentation, dans la même base de code exacte , en déployant un seul fichier XML modifié.Vous auriez besoin d'un conteneur IoC si vous aviez besoin de centraliser la configuration de vos dépendances afin qu'elles puissent être facilement échangées en masse. Cela a plus de sens dans TDD, où de nombreuses dépendances sont permutées, mais où il y a peu d'interdépendance entre les dépendances. Cela se fait au prix d'obscurcir le flux de contrôle de la construction des objets dans une certaine mesure, il est donc important d'avoir une configuration bien organisée et raisonnablement documentée. Il est également bon d'avoir une raison de le faire, sinon, c'est de la dorure à l'abstraction . Je l'ai vu si mal fait qu'il a été traîné jusqu'à être l'équivalent d'une instruction goto pour les constructeurs.
la source
Voici pourquoi. Le projet s'appelle IOC-with-Ninject. Vous pouvez le télécharger et l'exécuter avec Visual Studio. Cet exemple utilise Ninject mais TOUTES les «nouvelles» instructions sont au même endroit et vous pouvez complètement changer la façon dont votre application s'exécute en changeant le module de liaison à utiliser. L'exemple est configuré pour que vous puissiez vous lier à une version simulée des services ou à la version réelle. Dans les petits projets qui peuvent ne pas avoir d'importance, mais dans les grands projets, c'est une grosse affaire.
Juste pour être clair, les avantages tels que je les vois: 1) TOUTES les nouvelles instructions au même endroit à la racine du code. 2) Code totalement re-factorisé avec un changement. 3) Points supplémentaires pour `` facteur cool '' car c'est ... eh bien: cool. : p
la source
Je vais essayer de comprendre pourquoi le CIO pourrait ne pas être bon pour moi.
Comme pour tout le reste, le conteneur IOC (ou comme le dirait Einstein I = OC ^ 2) est un concept que vous devez décider vous-même si vous en avez besoin ou non dans votre code. Le tollé récent sur la mode à propos d'IOC n'est que cela, la mode. Ne tombez pas dans la mode, c'est le premier. Il existe une myriade de concepts que vous pouvez implémenter dans votre code. Tout d'abord, j'utilise l'injection de dépendance depuis que j'ai commencé la programmation et j'ai appris le terme lui-même quand il a été popularisé sous ce nom. Le contrôle de la dépendance est un sujet très ancien et il a été traité jusqu'à présent de milliers de milliards de façons, en fonction de ce qui se découplait de quoi. Découpler tout de tout est un non-sens. Le problème avec le conteneur IOC est qu'il essaie d'être aussi utile qu'Entity Framework ou NHibernate. Bien que l'écriture d'un mappeur relationnel-objet soit tout simplement indispensable dès que vous devez coupler une base de données avec votre système, le conteneur IOC n'est pas toujours nécessaire. Ainsi, lorsque le conteneur IOC est utile:
1: Ce n'est pas si souvent que vous avez autant de dépendances dans votre code, ou que vous les connaissez au début de la conception. La pensée abstraite est utile lorsque la pensée abstraite est due.
2: Le couplage de votre code avec un code tiers est un problème HuGe. Je travaillais avec du code qui a plus de 10 ans et qui suivait à l'époque des concepts sophistiqués et avancés ATL, COM, COM + et ainsi de suite. Il n'y a rien que vous puissiez faire avec ce code maintenant. Ce que je dis, c'est qu'un concept avancé donne un avantage apparent, mais il est annulé à long terme avec l'avantage obsolète lui-même. Cela avait simplement rendu tout cela plus cher.
3: Le développement logiciel est déjà assez difficile. Vous pouvez l'étendre à des niveaux méconnaissables si vous autorisez un concept avancé à rogner dans votre code. Il y a un problème avec IOC2. Même s'il s'agit de découpler des dépendances, il découplera également le flux logique. Imaginez que vous avez trouvé un bug et que vous devez définir une pause pour examiner la situation. L'IOC2, comme tout autre concept avancé, rend cela plus difficile. La correction d'un bogue dans un concept est plus difficile que la correction d'un bogue dans un code plus simple, car lorsque vous corrigez un bogue, un concept doit être à nouveau respecté. (Juste pour vous donner un exemple, C ++ .NET change constamment la syntaxe à tel point que vous devez bien réfléchir avant de refactoriser une ancienne version de .NET.) Quel est donc le problème avec IOC? Le problème réside dans la résolution des dépendances. La logique de résolution est généralement cachée dans l'IOC2 lui-même, écrit peut-être d'une manière inhabituelle que vous devez apprendre et maintenir. Votre produit tiers sera-t-il disponible dans 5 ans? Microsoft ne l'était pas.
Le syndrome "Nous savons comment" est écrit un peu partout concernant IOC2. Ceci est similaire aux tests d'automatisation. Terme de fantaisie et solution parfaite à première vue, vous mettez simplement tous vos tests à exécuter pendant la nuit et voyez les résultats le matin. Il est vraiment pénible d'expliquer entreprise après entreprise ce que signifient vraiment les tests automatisés. Les tests automatisés ne sont certainement pas un moyen rapide de réduire le nombre de bogues que vous pouvez introduire du jour au lendemain pour augmenter la qualité de votre produit. Mais, la mode rend cette notion énormément dominante. IOC2 souffre du même syndrome. On pense que vous devez l'implémenter pour que votre logiciel soit bon. Tous les entretiens récents, on m'a demandé si j'implémentais IOC2 et l'automatisation. C'est un signe de mode: l'entreprise avait une partie du code écrite en MFC qu'elle n'abandonnera pas.
Vous devez apprendre IOC2 comme tout autre concept logiciel. La décision d'utiliser ou non l'IOC2 appartient à l'équipe et à l'entreprise. Cependant, au moins TOUS les arguments ci-dessus doivent être mentionnés avant que la décision ne soit prise. Ce n'est que si vous voyez que le côté positif l'emporte sur le côté négatif que vous pouvez prendre une décision positive.
Il n'y a rien de mal avec IOC2, sauf qu'il ne résout que les problèmes qu'il résout et présente les problèmes qu'il présente. Rien d'autre. Cependant, aller à l'encontre de la mode est très difficile, ils ont la bouche en sueur, les adeptes de tout. C'est étrange comme aucun d'eux n'est là quand le problème de leur fantaisie devient apparent. De nombreux concepts dans l'industrie du logiciel ont été défendus parce qu'ils génèrent du profit, des livres sont écrits, des conférences ont lieu, de nouveaux produits sont fabriqués. C'est la mode, généralement de courte durée. Dès que les gens trouvent autre chose, ils l'abandonnent complètement. IOC2 est utile mais il montre les mêmes signes que beaucoup d'autres concepts disparus que j'ai vus. Je ne sais pas si elle survivra. Il n'y a pas de règle pour cela. Vous pensez que si elle est utile, elle survivra. Non, ça ne marche pas comme ça. Une grande entreprise riche suffit et le concept peut mourir en quelques semaines. Nous verrons. NHibernate a survécu, EF est arrivé deuxième. Peut-être que l'IOC2 survivra aussi. N'oubliez pas que la plupart des concepts en développement logiciel n'ont rien de spécial, ils sont très logiques, simples et évidents, et il est parfois plus difficile de se souvenir de la convention d'appellation actuelle que de comprendre le concept lui-même. La connaissance d'IOC2 fait-elle d'un développeur un meilleur développeur? Non, car si un développeur n'a pas été en mesure de proposer un concept de nature similaire à IOC2, il lui sera difficile de comprendre quel problème IOC2 résout, son utilisation semblera artificielle et il ou elle pourra commencer à l'utiliser. par souci d'être une sorte de politiquement correct. N'oubliez pas que la plupart des concepts en développement logiciel n'ont rien de spécial, ils sont très logiques, simples et évidents, et il est parfois plus difficile de se souvenir de la convention d'appellation actuelle que de comprendre le concept lui-même. La connaissance d'IOC2 fait-elle d'un développeur un meilleur développeur? Non, car si un développeur n'a pas été en mesure de proposer un concept de nature similaire à IOC2, il lui sera difficile de comprendre quel problème IOC2 résout, son utilisation semblera artificielle et il ou elle pourra commencer à l'utiliser. par souci d'être une sorte de politiquement correct. N'oubliez pas que la plupart des concepts en développement logiciel n'ont rien de spécial, ils sont très logiques, simples et évidents, et il est parfois plus difficile de se souvenir de la convention d'appellation actuelle que de comprendre le concept lui-même. La connaissance d'IOC2 fait-elle d'un développeur un meilleur développeur? Non, car si un développeur n'a pas été en mesure de proposer un concept de nature similaire à IOC2, il lui sera difficile de comprendre quel problème IOC2 résout, son utilisation semblera artificielle et il ou elle pourra commencer à l'utiliser. par souci d'être une sorte de politiquement correct. La connaissance d'IOC2 fait-elle d'un développeur un meilleur développeur? Non, car si un développeur n'a pas été en mesure de proposer un concept de nature similaire à IOC2, il lui sera difficile de comprendre quel problème IOC2 résout, son utilisation semblera artificielle et il ou elle pourra commencer à l'utiliser. par souci d'être une sorte de politiquement correct. La connaissance d'IOC2 fait-elle d'un développeur un meilleur développeur? Non, car si un développeur n'a pas été en mesure de proposer un concept de nature similaire à IOC2, il lui sera difficile de comprendre quel problème IOC2 résout, son utilisation semblera artificielle et il ou elle pourra commencer à l'utiliser. par souci d'être une sorte de politiquement correct.
la source
Personnellement, j'utilise IoC comme une sorte de carte de structure de mon application (Ouais, je préfère également StructureMap;)). Il est facile de remplacer mes implémentations d'interface habituelles par des implémentations Moq pendant les tests. Créer une configuration de test peut être aussi simple que de faire un nouvel appel init à mon framework IoC, en remplaçant la classe qui est ma limite de test par une maquette.
Ce n'est probablement pas ce pour quoi l'IoC est là, mais c'est ce que je me retrouve à utiliser le plus.
la source
IOC CONTAINER RÉSOUD UN PROBLÈME QUE VOUS POURRIEZ PAS AVOIR MAIS C'EST UN BON PROBLÈME À AVOIR
http://kozmic.net/2012/10/23/ioc-container-solves-a-problem-you-might-not-have-but-its-a-nice-problem-to-have/
la source
vous n'avez pas besoin d'un cadre pour réaliser l'injection de dépendance. Vous pouvez également le faire par les principaux concepts java. http://en.wikipedia.org/wiki/Dependency_injection#Code_illustration_using_Java
la source
Je me rends compte que c'est un poste assez ancien, mais il semble encore raisonnablement actif, et j'ai pensé apporter quelques points qui n'ont pas encore été mentionnés dans d'autres réponses.
Je dirai que je suis d'accord avec les avantages de l'injection de dépendance, mais je préfère construire et gérer les objets moi-même, en utilisant un modèle similaire à celui décrit par Maxm007 dans sa réponse. J'ai trouvé deux problèmes principaux avec l'utilisation de conteneurs tiers:
1) Le fait de disposer d'une bibliothèque tierce pour gérer la durée de vie de vos objets de manière "automagique" peut se prêter à des résultats inattendus. Nous avons constaté que, en particulier dans les grands projets, vous pouvez avoir beaucoup plus de copies d'un objet que vous attendez, et plus que si vous gériez manuellement les cycles de vie. Je suis sûr que cela varie en fonction du cadre utilisé, mais le problème existe néanmoins. Cela peut également être problématique si votre objet contient des ressources, des connexions de données, etc., car l'objet peut parfois vivre plus longtemps que prévu. Donc, inévitablement, les conteneurs IoC ont tendance à augmenter l'utilisation des ressources et l'empreinte mémoire d'une application.
2) Les conteneurs IoC, à mon avis, sont une forme de "programmation en boîte noire". J'ai constaté en particulier que nos développeurs moins expérimentés ont tendance à en abuser. Il permet au programmeur de ne pas avoir à réfléchir à la façon dont les objets doivent être liés les uns aux autres ou à les découpler, car il leur fournit un mécanisme dans lequel ils peuvent simplement saisir n'importe quel objet de leur choix. Par exemple, il peut y avoir une bonne raison de conception pour laquelle ObjectA ne devrait jamais connaître ObjectB directement, mais plutôt que de créer une usine ou un pont ou un localisateur de service, un programmeur inexpérimenté dira simplement "pas de problème, je vais simplement récupérer ObjectB du conteneur IoC ". Cela peut en fait conduire à un couplage d'objet accru, ce que l'IoC est censé aider à prévenir.
la source
L'injection de dépendances dans un projet ASP.NET peut être effectuée avec quelques lignes de code. Je suppose qu'il y a un avantage à utiliser un conteneur lorsque vous avez une application qui utilise plusieurs frontaux et a besoin de tests unitaires.
la source