Version plus courte du reste de la question: J'ai un problème et un conteneur IOC est un outil. Le problème ressemble à quelque chose de CIO pourrait être capable de résoudre, mais je n'ai pas lu assez les instructions de l'outil pour savoir à coup sûr. Je suis curieux si j'ai choisi le mauvais outil ou quel chapitre du manuel d'instructions, je pourrais pouvoir passer à l'aide. P>
Je travaille sur une bibliothèque de contrôles de formulaires Windows. Au cours de la dernière année, j'ai trébuché dans des tests unitaires et je suis passionné d'améliorer la qualité de nos tests automatisés. Les contrôles de test sont difficiles et il n'y a pas beaucoup d'informations à ce sujet en ligne. L'une des méchantes choses est la séparation de la logique d'interaction de la colle d'interface utilisateur qui appelle cela conduit à chaque contrôle ayant plusieurs dépendances supplémentaires que je ne considérerais normalement sainement pour une classe. Créer des faux pour ces éléments lors du test de leur intégration avec le contrôle est assez fastidieux et je suis à la recherche de CIO pour une solution. P>
Il y a un obstacle que je ne suis pas sûr de savoir comment surmonter. Pour configurer le conteneur, vous devez disposer d'un code bootstrapper qui fonctionne avant le reste de l'application. Dans une application, il existe une place très claire pour ce truc. Dans une bibliothèque, ce n'est pas si clair. P>
La première solution qui vous vient à l'esprit consiste à créer une classe qui fournit une instance statique du conteneur et définit le conteneur dans son initialisateur de type. Cela fonctionnerait pour le temps d'exécution, mais dans l'environnement de test, je ne suis pas sûr à quel point cela fonctionnerait bien. Les tests sont autorisés à exécuter en parallèle et de nombreux tests nécessiteront différentes dépendances. L'état partagé statique sera donc un cauchemar. Cela me conduit à croire que la création de conteneurs devrait être une méthode d'instance, mais j'ai alors un problème de poulet et d'œuf en tant que contrôle qu'il faudrait construire son conteneur avant de pouvoir se créer. L'initialiseur de type du contrôle vous vient à l'esprit, mais mes tests ne seront pas en mesure de modifier ce comportement. Cela m'a amené à penser à rendre le conteneur lui-même une dépendance du contrôle dans lequel les constructeurs visibles par l'utilisateur fournissent la mise en œuvre par défaut d'exécution, mais cela laisse jusqu'à mes tests pour configurer leurs propres conteneurs. Je n'ai pas donné à cette pensée, mais cela semble que cela se produirait au même niveau d'effort que ce que j'ai maintenant: des tests qui doivent initialiser 3-5 dépendances par test. P>
Normalement j'essayerais beaucoup de choses pour voir ce qui fait mal. Je suis sous quelques érables sévères pour le moment, je n'ai pas beaucoup de temps pour expérimenter en tant que code d'écriture; Je n'obtiens que de brefs moments pour y penser et je n'ai pas mis beaucoup à papier. Je suis sûr que quelqu'un d'autre a eu un problème similaire, alors ce serait bien si je n'avais pas à réinventer la roue. P>
Quelqu'un d'autre a-t-il attaqué ce problème? Y a-t-il quelques exemples de stratégies qui répondront à ces besoins? Suis-je juste une novice et surcharge des choses en raison de mon inexpérience? Si c'est ce dernier, j'aimerais toute ressource que vous souhaitez partager pour résoudre mon ignorance. P>
J'aimerais répondre à la réponse de Mark Semonan, mais il nécessitera plus de caractères que le champ de commentaire le permet. P>
Je joue déjà avec des modèles de modèle de présentation. La vue de ce cas est la classe de contrôle public et chacune dispose d'une ou de plusieurs classes de contrôleur. Lorsque certains événements d'interface utilisateur sont déclenchés sur le contrôle, la seule logique qu'elle effectue est de décider quelles méthodes de contrôleur doivent être appelées. p>
L'expression courte d'une exploration de cette conception est que mes cours de contrôleur sont étroitement couplés à leurs points de vue. Sur la base de la déclaration selon laquelle DI conteneurs travaille avec un code couplé de manière lâche, je lis un "mauvais outil pour le travail". Je pourrais peut-être concevoir une architecture plus lâchée, à quel point un conteneur DI peut être plus facile à utiliser. Mais cela nécessitera un effort significatif et ce serait une refonte du code expédié; Je vais devoir expérimenter avec de nouvelles choses avant la pointe des pieds autour des trucs plus anciens. C'est une question pour un autre jour. P>
Pourquoi est-ce que je veux même injecter des types fortement couplés plutôt que d'utiliser des défauts locaux? Certaines des coutures sont destinées à être des points d'extensibilité pour les utilisateurs avancés. Je dois tester divers scénarios impliquant des implémentations incorrectes et également vérifier que je réponds à mes contrats; Des objets graves sont un excellent ajustement. P>
Pour la conception actuelle, la suggestion de Chris Ballard de "Pauvre Man's Di" est ce que j'ai suivi de plus en plus et que mes types fortement couplés, ce n'est que beaucoup de configuration fastidieuse. J'ai eu cette vision que je serais en mesure de repousser tout ce Tedium dans une méthode de configuration de conteneurs di conteneur, mais plus j'essaie de justifier cette approche, plus je suis convaincu que j'essaie de suspendre des images avec un Sledgehammer. < / p>
J'attendrai 24 heures environ pour voir si la discussion progresse plus avant d'accepter. P>
3 Réponses :
Selon la complexité de votre cadre, vous pouvez vous éloigner avec une injection de dépendance basée sur le codage à base de codage, avec un constructeur par défaut sans paramètre (qui utilise la mise en œuvre du béton normal) mais avec un second constructeur pour injecter la dépendance à des fins de test de l'unité, par exemple .
private IMyDependency dependency; public MyClass(IMyDependency dependency) { this.dependency = dependency; } public MyClass() : this(new MyDefaultImplementation()) { }
Cette stratégie est également appelée " Injection de dépendance du pauvre homme ".
@adamjford: et Bastard Injection - avoir une recherche ...
Injection de dépendance (inversion du contrôle) est un ensemble de principes et de modèles que vous pouvez utiliser pour Vous devrez trouver un moyen de découpler votre rendu de l'interface utilisateur de la logique UI. Il y a beaucoup de modèles de présentation forts> qui décrivent comment faire cela: Une fois que vous avez un bon découplage, di (et conteneurs) peut être utilisé pour composer des collaborateurs. P>
Étant donné que la bibliothèque Mais en réalité, cette APRAPACH a été souillée par erreur et trop interdépendante: One Lib Config a dû savoir des propriétés des autres pour éviter les doublons. P>
Ma conclusion: Utilisez l'injection de la dépendance de l'homme de @chris Ballard "ou manipulez toutes les dépendances dans un grand module de configutille bouleversement étroitement couplé de l'application principale. p>
Les formulaires Windows FWIW ne sont pas la technologie la plus simple sur laquelle mettre en place un code UI couplé de manière lâche. Cependant, vous trouverez peut-être la discussion suivante utile: Stackoverflow.com/Questtions/2128588/...
Choisir une réponse à accepter était difficile. Mark Semelann est philosophiquement correct. Cependant, mes contraintes de temps ne permettent pas de tenter de redéfinir et i> J'essaie de tirer de nouvelles fonctionnalités dans le code hérité. J'adopte que la suggestion de Chris Ballard de Pauvre Man's DI tout en laissant les constructeurs par défaut utilisent des paramètres par défaut d'exécution. Je ne prétends pas que c'est juste, mais c'est ce que j'ai choisi.