Question

Je comprends les avantages de l’injection de dépendance elle-même. Prenons le printemps par exemple. Je comprends également les avantages des autres fonctionnalités de Spring, telles que l'AOP, des aides de différents types, etc. Je me demande simplement quels sont les avantages de la configuration XML, tels que:

<bean id="Mary" class="foo.bar.Female">
  <property name="age" value="23"/>
</bean>
<bean id="John" class="foo.bar.Male">
  <property name="girlfriend" ref="Mary"/>
</bean>

comparé au vieux code Java tel que:

Female mary = new Female();
mary.setAge(23);
Male john = new Male();
john.setGirlfriend(mary);

qui est plus facile à déboguer, à vérifier l'heure de la compilation et qui peut être compris par tous ceux qui ne connaissent que Java. Alors, quel est l'objectif principal d'un framework d'injection de dépendance? (ou un morceau de code qui montre ses avantages.)

MISE À JOUR:
En cas de

IService myService;// ...
public void doSomething() {  
  myService.fetchData();
}

Comment le framework IoC peut-il déterminer quelle implémentation de myService je souhaite injecter s’il en existe plusieurs? S'il n'y a qu'une seule implémentation d'une interface donnée et que je laisse le conteneur IoC décider automatiquement de l'utiliser, elle sera interrompue après l'apparition d'une seconde implémentation. Et s'il n'y a intentionnellement qu'une seule implémentation possible d'une interface, vous n'avez pas besoin de l'injecter.

Il serait vraiment intéressant de voir un petit élément de configuration pour IoC qui montre ses avantages. J'utilise Spring depuis un certain temps et je ne peux pas fournir un tel exemple. Et je peux montrer des lignes simples qui démontrent les avantages de hibernate, dwr et d’autres frameworks que j’utilise.

MISE À JOUR 2:
Je me rends compte que la configuration d'IoC peut être changée sans recompiler. Est-ce vraiment une si bonne idée? Je peux comprendre quand quelqu'un veut changer les informations d'identification de la base de données sans recompiler - il n'est peut-être pas développeur. Dans votre pratique, à quelle fréquence quelqu'un d'autre que le développeur modifie-t-il la configuration d'IoC? Je pense que les développeurs ne font aucun effort pour recompiler cette classe particulière au lieu de changer de configuration. Et pour les non-développeurs, vous voudrez probablement lui simplifier la vie et fournir un fichier de configuration plus simple.

MISE À JOUR 3:

  

Configuration externe du mappage entre les interfaces et leurs implémentations concrètes

Pourquoi est-il si bon de le rendre extra-normal? Vous ne faites pas tout votre code externe, alors que vous pouvez le faire - il suffit de le placer dans le fichier ClassName.java.txt, de le lire et de le compiler manuellement à la volée - wow, vous avez évité la recompilation. Pourquoi devrait-on éviter la compilation?!

  

Vous gagnez du temps de codage car vous fournissez des mappages de manière déclarative, et non dans un code de procédure

Je comprends que l’approche déclarative permet parfois de gagner du temps. Par exemple, je déclare une seule fois un mappage entre une propriété de bean et une colonne de base de données et hibernate utilise ce mappage lors du chargement, de l’enregistrement, de la création de code SQL basé sur HSQL, etc. C’est là que l’approche déclarative fonctionne. Dans le cas de Spring (dans mon exemple), la déclaration comportait plus de lignes et avait la même expressivité que le code correspondant. S'il existe un exemple où une telle déclaration est plus courte que le code, j'aimerais la voir.

  

Le principe d'inversion de contrôle facilite les tests unitaires car vous pouvez remplacer les implémentations réelles par de fausses (comme remplacer la base de données SQL par une en mémoire)

Je comprends bien l’inversion des avantages en matière de contrôle (je préfère appeler le modèle de conception décrit ici sous le nom d’Injection de dépendance, car IoC est plus général. Il existe de nombreux types de contrôle et nous n’en inversons qu’un - le contrôle de l’initialisation). . Je demandais pourquoi quelqu'un a jamais besoin d'autre chose qu'un langage de programmation pour cela. Je peux certainement remplacer les vraies implémentations par des fausses utilisant du code. Et ce code exprimera la même chose que la configuration: il initialisera simplement les champs avec de fausses valeurs.

mary = new FakeFemale();

Je comprends les avantages de l’ID. Je ne comprends pas quels avantages sont ajoutés par la configuration XML externe par rapport à la configuration de code qui fait la même chose. Je ne pense pas que la compilation devrait être évitée - je compile tous les jours et je suis toujours en vie. Je pense que la configuration de DI est un mauvais exemple d’approche déclarative. La déclaration peut être utile si est déclarée une seule fois ET est utilisée à plusieurs reprises de différentes manières - comme hibernate cfg, où le mappage entre la propriété de bean et la colonne de base de données est utilisé pour enregistrer, charger, construire des requêtes de recherche, etc. La configuration de Spring DI peut être facilement traduite en configuration du code, comme au début de cette question, ne peut-il pas? Et il n’est utilisé que pour l’initialisation du bean, n’est-ce pas? Ce qui signifie qu'une approche déclarative n'ajoute rien ici, n'est-ce pas?

Lorsque je déclare un mappage de veille prolongée, je lui donne simplement quelques informations, et cela fonctionne sur cette base. Je ne lui dis pas quoi faire. En cas de printemps, ma déclaration indique au printemps exactement ce qu'il faut faire - alors pourquoi le déclarer, pourquoi ne pas le faire?

DERNIÈRE MISE À JOUR:
Les gars, beaucoup de réponses me disent sur l'injection de dépendance, ce que je sais, c'est bien. La question concerne le but de la configuration DI au lieu de l'initialisation du code - j'ai tendance à penser que l'initialisation du code est plus courte et plus claire. La seule réponse que j’ai eu jusqu’à présent à ma question est que cela évite la recompilation, lorsque la configuration change. Je suppose que je devrais poser une autre question, car c’est un grand secret pour moi, pourquoi la compilation devrait être évitée dans ce cas.

Était-ce utile?

La solution

Pour moi, l'une des principales raisons d'utiliser un IoC (et d'utiliser une configuration externe) concerne les deux zones de:

  • Test
  • Maintenance de la production

Test

Si vous divisez vos tests en 3 scénarios (ce qui est assez normal dans le développement à grande échelle):

  1. Test unitaire
  2. Test d'intégration
  3. Test de la boîte noire

Ce que vous voudrez faire concerne les deux derniers scénarios de test (intégration et boîte noire) et ne recompile aucune partie de l'application.

Si l'un de vos scénarios de test vous demande de modifier la configuration (par exemple, utilisez un autre composant pour imiter une intégration bancaire ou effectuez une charge de performances), cela peut être facilement géré (cela fait partie des avantages de la configuration de l'ID côté d'un IoC si.

En outre, si votre application est utilisée sur plusieurs sites (avec une configuration de serveur et de composant différente) ou si la configuration change dans l'environnement en direct, vous pouvez utiliser les étapes de test ultérieures pour vérifier que l'application gérera ces modifications.

Production

En tant que développeur, vous n'avez pas (et ne devriez pas) contrôler l'environnement de production (en particulier lorsque votre application est distribuée à plusieurs clients ou sur des sites distincts), c'est pour moi le véritable avantage d'utiliser à la fois un IoC et la configuration externe, car il incombe au support infrastructure / production d’ajuster et d’ajuster l’environnement réel sans avoir à revenir aux développeurs et à les tester (un coût plus élevé lorsque tout ce qu’ils veulent, c’est de déplacer un composant).

Résumé

Les principaux avantages de la configuration externe d'un IoC proviennent du fait de donner à d'autres (non-développeurs) le pouvoir de configurer votre application. D'après mon expérience, cela n'est utile que dans un nombre limité de circonstances:

  • L'application est distribuée sur plusieurs sites / clients où les environnements seront différents.
  • Contrôle du développement limité / entrée sur l'environnement de production et la configuration.
  • Tests de scénarios.

En pratique, j'ai constaté que même si vous développiez un environnement dont vous maîtrisez l'environnement, il est préférable de laisser au fil du temps une autre personne capable de modifier la configuration:

  • Lorsque vous développez, vous ne savez pas quand cela changera (l'application est tellement utile que votre société la vend à quelqu'un d'autre).
  • Je ne veux pas être obligé de changer le code à chaque demande d'un léger changement qui aurait pu être traité en configurant et en utilisant un bon modèle de configuration.

Remarque: L'application fait référence à la solution complète (pas seulement à l'exécutable), donc à tous les fichiers nécessaires à l'exécution de l'application .

Autres conseils

L'injection de dépendance est un style de codage qui tire son origine du constat que la délégation d'objet est généralement un modèle de conception plus utile que l'héritage d'objet (c'est-à-dire que la relation objet-une est plus utile que la relation objet-une relation). Un autre ingrédient est toutefois nécessaire au fonctionnement de DI, à savoir la création d'interfaces d'objet. En combinant ces deux puissants modèles de conception, les ingénieurs en logiciel ont rapidement compris qu'ils pouvaient créer du code flexible à couplage lâche, d'où le concept de Dependency Injection. Cependant, ce n'est que lorsque la réflexion sur les objets est devenue disponible dans certains langages de haut niveau que DI a réellement pris son envol. Le composant de réflexion est au cœur de la plupart des systèmes DI actuels, car les aspects vraiment intéressants de la DI nécessitent la capacité de sélectionner par programme des objets, de les configurer et de les injecter dans d'autres objets à l'aide d'un système externe indépendant des objets eux-mêmes.

Un langage doit prendre en charge à la fois les techniques de programmation normales orientées objet et les interfaces et la réflexion d'objets (par exemple, Java et C #). Bien que vous puissiez construire des programmes utilisant des modèles DI dans les systèmes C ++, son manque de réflexion dans le langage lui-même l’empêche de prendre en charge les serveurs d’application et autres plates-formes DI et limite donc l’expressivité des modèles DI.

Points forts d'un système construit à l'aide de modèles DI:

  1. Le code DI est beaucoup plus facile à réutiliser car la fonctionnalité "dépendante" est extrapolée dans des interfaces bien définies, permettant à des objets séparés dont la configuration est gérée par une plate-forme d'application appropriée d'être insérés à volonté dans d'autres objets.
  2. Le code DI est beaucoup plus facile à tester. La fonctionnalité exprimée par l'objet peut être testée dans une boîte noire en construisant des objets 'simulatoires' mettant en oeuvre les interfaces attendues par votre logique d'application.
  3. Le code DI est plus flexible. C'est un code naturellement mal couplé - à l'extrême. Cela permet au programmeur de choisir la manière dont les objets sont connectés en fonction exclusivement de leurs interfaces requises à une extrémité et de leurs interfaces exprimées à l'autre.
  4. La configuration externe (XML) des objets DI signifie que d’autres peuvent personnaliser votre code dans des directions imprévues.
  5. La configuration externe est également un motif de séparation des préoccupations, car tous les problèmes d'initialisation et de gestion de l'interdépendance des objets peuvent être traités par le serveur d'applications.
  6. Notez que la configuration externe n’est pas nécessaire pour utiliser le modèle DI. Pour les interconnexions simples, un petit objet générateur est souvent suffisant. Il y a un compromis en flexibilité entre les deux. Un objet générateur n'est pas une option aussi flexible qu'un fichier de configuration visible de l'extérieur. Le développeur du système DI doit soupeser les avantages de la flexibilité par rapport à la commodité, en veillant à ce que le contrôle fin et précis de la construction d’objet telle qu’exprimée dans un fichier de configuration augmente la confusion et les coûts de maintenance.

Certainement, le code DI semble plus lourd, les inconvénients d'avoir tous ces fichiers XML configurant les objets à injecter dans d'autres objets semblent difficiles. C’est pourtant l’intérêt des systèmes DI. Votre capacité à combiner et faire correspondre des objets de code sous forme d'une série de paramètres de configuration vous permet de construire des systèmes complexes en utilisant un code tiers avec un minimum de codage.

L'exemple fourni dans la question ne fait qu'effleurer la surface du pouvoir expressif qu'une bibliothèque d'objets DI correctement factorisée peut fournir. Avec un peu de pratique et beaucoup d’autodiscipline, la plupart des praticiens en DI constatent qu’ils peuvent construire des systèmes dont la couverture de test du code de l’application est de 100%. Ce seul point est extraordinaire. Ce n'est pas une couverture de test à 100% d'une petite application de quelques centaines de lignes de code, mais une couverture de test à 100% d'applications comprenant des centaines de milliers de lignes de code. Je suis incapable de décrire tout autre modèle offrant ce niveau de testabilité.

Vous avez raison de dire qu’une application de 10 lignes de code est plus facile à comprendre que plusieurs objets plus une série de fichiers de configuration XML. Cependant, comme pour la plupart des modèles de conception puissants, les gains sont constatés à mesure que vous continuez d’ajouter de nouvelles fonctionnalités au système.

En résumé, les applications à grande échelle basées sur les ID sont à la fois plus faciles à déboguer et à comprendre. Bien que la configuration XML ne soit pas "compilée au moment de la compilation", tous les services d'application dont cet auteur est au courant fourniront au développeur des messages d'erreur s'il tente d'injecter un objet ayant une interface incompatible dans un autre objet. Et la plupart proposent une fonctionnalité de vérification qui couvre toutes les configurations d'objets connues. Ceci s’effectue facilement et rapidement en vérifiant que l’objet A à injecter implémente l’interface requise par l’objet B pour toutes les injections d’objets configurés.

C’est une question un peu lourde de sens, mais j’ai tendance à être d’accord pour dire qu’un nombre considérable de configurations XML ne représente pas vraiment un avantage. J'aime que mes applications soient aussi légères que possible sur les dépendances, y compris les lourds cadres.

Ils simplifient souvent le code, mais ils ont également une surcharge de complexité qui rend le traçage des problèmes assez difficile (j'ai vu de tels problèmes de première main, et en Java, je serais beaucoup plus à l'aise avec.) .

Cela dépend un peu du style et de ce avec quoi vous êtes à l'aise ... aimez-vous utiliser votre propre solution et avez-vous l'avantage de la connaître de fond en comble ou de miser sur des solutions existantes qui pourraient s'avérer difficiles lorsque le la configuration n'est pas juste Tout est un compromis.

Cependant, la configuration XML est un peu ma bête noire ... J'essaie de l'éviter à tout prix.

Chaque fois que vous pouvez modifier votre code en données, vous faites un pas dans la bonne direction.

Tout coder en tant que données signifie que votre code est plus général et réutilisable. Cela signifie également que vos données peuvent être spécifiées dans une langue qui leur convient parfaitement.

De plus, un fichier XML peut être lu dans une interface utilisateur graphique ou un autre outil et facilement manipulé de manière pragmatique. Comment feriez-vous cela avec l'exemple de code?

Je suis constamment en train de factoriser ce que la plupart des gens implémentent sous forme de code dans les données, cela rend le code laissé BEAUCOUP plus propre. Je trouve inconcevable que les gens créent un menu sous forme de code plutôt que sous forme de données - il devrait être évident que le faire sous forme de code est tout simplement faux en raison de son comportement standard.

La raison de l’utilisation d’un conteneur DI est qu’il n’est pas nécessaire d’avoir un milliard de propriétés préconfigurées dans votre code, qui sont simplement des accesseurs et des setters. Voulez-vous vraiment coder en dur tous ceux qui ont un nouveau X ()? Bien sûr, vous pouvez avoir un paramètre par défaut, mais le conteneur DI permet la création de singletons, ce qui est extrêmement facile et vous permet de vous concentrer sur les détails du code, et non sur la tâche diverse de son initialisation.

Par exemple, Spring vous permet d'implémenter l'interface InitializingBean et d'ajouter une méthode afterPropertiesSet (vous pouvez également spécifier un "init-method" pour éviter de coupler votre code à Spring). Ces méthodes vous permettront de vous assurer que toute interface spécifiée en tant que champ dans votre instance de classe est configurée correctement au démarrage. Vous n'avez ainsi plus besoin de vérifier à zéro vos getters et setters (en supposant que vous permettez à vos singletons de rester thread-safe ).

De plus, il est beaucoup plus facile de faire des initialisations complexes avec un conteneur DI au lieu de les faire vous-même. Par exemple, j'aide à utiliser XFire (pas CeltiXFire, nous utilisons uniquement Java 1.4). L'application utilisait Spring, mais elle utilisait malheureusement le mécanisme de configuration services.xml de XFire. Lorsqu’un ensemble d’éléments devait déclarer qu’il comptait zéro ou plusieurs instances au lieu d’une ou plusieurs instances, je devais remplacer le code XFire fourni pour ce service particulier.

Certains paramètres par défaut XFire sont définis dans le schéma Spring Beans. Donc, si nous utilisions Spring pour configurer les services, les beans auraient pu être utilisés. Au lieu de cela, ce qui s'est passé, c'est que j'ai dû fournir une instance d'une classe spécifique dans le fichier services.xml au lieu d'utiliser les beans. Pour ce faire, je devais fournir le constructeur et configurer les références déclarées dans la configuration XFire. Le vrai changement que je devais faire nécessitait de surcharger une seule classe.

Mais, grâce au fichier services.xml, j'ai dû créer quatre nouvelles classes, en définissant leurs valeurs par défaut en fonction de leurs valeurs par défaut dans les fichiers de configuration Spring de leurs constructeurs. Si nous avions pu utiliser la configuration Spring, j'aurais simplement pu dire:

<bean id="base" parent="RootXFireBean">
    <property name="secondProperty" ref="secondBean" />
</bean>

<bean id="secondBean" parent="secondaryXFireBean">
    <property name="firstProperty" ref="thirdBean" />
</bean>

<bean id="thirdBean" parent="thirdXFireBean">
    <property name="secondProperty" ref="myNewBean" />
</bean>

<bean id="myNewBean" class="WowItsActuallyTheCodeThatChanged" />

Au lieu de cela, cela ressemblait davantage à ceci:

public class TheFirstPointlessClass extends SomeXFireClass {
    public TheFirstPointlessClass() {
        setFirstProperty(new TheSecondPointlessClass());
        setSecondProperty(new TheThingThatWasHereBefore());
    }
}

public class TheSecondPointlessClass extends YetAnotherXFireClass {
    public TheSecondPointlessClass() {
        setFirstProperty(TheThirdPointlessClass());
    }
}

public class TheThirdPointlessClass extends GeeAnotherXFireClass {
    public TheThirdPointlessClass() {
        setFirstProperty(new AnotherThingThatWasHereBefore());
        setSecondProperty(new WowItsActuallyTheCodeThatChanged());
    }
}

public class WowItsActuallyTheCodeThatChanged extends TheXFireClassIActuallyCareAbout {
    public WowItsActuallyTheCodeThatChanged() {
    }

    public overrideTheMethod(Object[] arguments) {
        //Do overridden stuff
    }
}

Le résultat net est donc que quatre classes Java supplémentaires, pour la plupart inutiles, ont dû être ajoutées à la base de code pour obtenir l'effet qu'une classe supplémentaire et des informations simples sur les conteneurs de dépendances ont été obtenues. Ce n’est pas l’exception qui confirme la règle, c’est la règle ... le traitement des codes bizarres dans le code est beaucoup plus propre lorsque les propriétés sont déjà fournies dans un conteneur DI et que vous les modifiez simplement pour les adapter à une situation particulière. , ce qui arrive le plus souvent.

j'ai votre réponse

Il existe évidemment des compromis dans chaque approche, mais les fichiers de configuration XML externalisés sont utiles pour le développement d’entreprise dans lesquels les systèmes de compilation sont utilisés pour compiler le code et non votre IDE. En utilisant le système de construction, vous souhaiterez peut-être injecter certaines valeurs dans votre code, par exemple la version de la construction (il peut être pénible de devoir mettre à jour manuellement chaque fois que vous compilez). La douleur est plus grande lorsque votre système de compilation extrait le code d’un système de contrôle de version. La modification de valeurs simples au moment de la compilation nécessiterait de modifier un fichier, de le valider, de le compiler, puis de l'inverser à chaque changement. Ce ne sont pas des modifications que vous souhaitez enregistrer dans votre contrôle de version.

Autres cas d'utilisation utiles concernant le système de construction et les configurations externes:

  • styles de styles / feuilles de style injectés pour une base de code unique pour différentes versions
  • injecter différents ensembles de contenu dynamique (ou leurs références) pour votre base de code unique
  • contexte de localisation par injection pour différentes versions / clients
  • remplacement d'un URI de service Web par un serveur de sauvegarde (lorsque le serveur principal tombe en panne)

Mise à jour: Tous les exemples ci-dessus portaient sur des choses qui ne nécessitaient pas nécessairement de dépendances sur des classes. Mais vous pouvez facilement créer des cas où un objet complexe et une automatisation sont nécessaires - par exemple:

  • Imaginez que vous disposiez d'un système dans lequel il surveillait le trafic de votre site Web. Selon le nombre d'utilisateurs simultanés, il active / désactive un mécanisme de journalisation. Peut-être que lorsque le mécanisme est désactivé, un objet de talon est mis à sa place.
  • Imaginez que vous disposiez d'un système de téléconférence Web dans lequel, en fonction du nombre d'utilisateurs, vous souhaitiez désactiver la possibilité d'effectuer le P2P en fonction du nombre de participants

Vous n'avez pas besoin de recompiler votre code chaque fois que vous modifiez quelque chose dans la configuration. Cela simplifiera le déploiement et la maintenance du programme. Par exemple, vous pouvez échanger un composant avec un autre avec un seul changement dans le fichier de configuration.

Vous pouvez insérer une nouvelle implémentation pour votre petite amie. Ainsi, une nouvelle femme peut être injectée sans recompiler votre code.

<bean id="jane" class="foo.bar.HotFemale">
  <property name="age" value="19"/>
</bean>
<bean id="mary" class="foo.bar.Female">
  <property name="age" value="23"/>
</bean>
<bean id="john" class="foo.bar.Male">
  <property name="girlfriend" ref="jane"/>
</bean>

(Ce qui précède suppose que Female et HotFemale implémentent la même interface GirlfFriend)

Dans le monde .NET, la plupart des frameworks IoC fournissent à la fois une configuration XML et un code.

StructureMap et Ninject, par exemple, utilisent des interfaces fluentes pour configurer les conteneurs. Vous n'êtes plus obligé d'utiliser des fichiers de configuration XML. Spring, qui existe également dans .NET, s'appuie fortement sur les fichiers XML puisqu'il s'agit de son interface de configuration principale historique, mais il est toujours possible de configurer les conteneurs à l'aide d'un programme.

Facilité de combinaison de configurations partielles dans une configuration complète finale.

Par exemple, dans les applications Web, le modèle, la vue et les contrôleurs sont généralement spécifiés dans des fichiers de configuration distincts. Utilisez l’approche déclarative, vous pouvez charger, par exemple:

  UI-context.xml
  Model-context.xml
  Controller-context.xml

Ou chargez avec une interface utilisateur différente et quelques contrôleurs supplémentaires:

  AlternateUI-context.xml
  Model-context.xml
  Controller-context.xml
  ControllerAdditions-context.xml

Faire la même chose en code nécessite une infrastructure permettant de combiner des configurations partielles. Pas impossible à faire dans le code, mais certainement plus facile à faire en utilisant un framework IoC.

Souvent, le point important est qui modifie la configuration après l'écriture du programme. Avec la configuration en code, vous supposez implicitement que la personne qui la modifie a les mêmes compétences et accès au code source, etc. que l’auteur en avait.

Dans les systèmes de production, il est très pratique d'extraire un sous-ensemble de paramètres (par exemple, l'âge dans votre exemple) dans un fichier XML et de permettre, par exemple, à L’administrateur système ou le personnel du support technique peut modifier la valeur sans lui donner le pouvoir total sur le code source ou d’autres paramètres - ou tout simplement pour les isoler de la complexité.

D'un point de vue printanier, je peux vous donner deux réponses.

Tout d'abord, la configuration XML n'est pas le seul moyen de définir la configuration. La plupart des choses peuvent être configurées à l'aide d'annotations et les tâches à effectuer avec XML sont la configuration d'un code que vous n'écrivez pas, comme un pool de connexions que vous utilisez depuis une bibliothèque. Spring 3 inclut une méthode pour définir la configuration DI en utilisant Java, similaire à la configuration DI roulée à la main dans votre exemple. Donc, utiliser Spring ne signifie pas que vous devez utiliser un fichier de configuration basé sur XML.

Deuxièmement, Spring est bien plus qu’un cadre de développement intégré. Il a beaucoup d'autres fonctionnalités, y compris la gestion des transactions et AOP. La configuration XML de Spring combine tous ces concepts. Souvent, dans le même fichier de configuration, je spécifie les dépendances de bean, les paramètres de transaction et l'ajout de beans de portée de session qui gèrent réellement à l'aide de AOP en arrière-plan. Je trouve que la configuration XML offre un meilleur endroit pour gérer toutes ces fonctionnalités. Je pense également que la configuration basée sur les annotations et la configuration XML sont plus efficaces que la configuration basée sur Java.

Mais je vois ce que vous dites et rien n’empêche de définir la configuration de l’injection de dépendance en Java. Je le fais normalement moi-même lors de tests unitaires et lorsque je travaille sur un projet suffisamment petit pour ne pas avoir ajouté de cadre DI. Normalement, je ne spécifie pas de configuration en Java car pour moi, c’est le code de plomberie que j’essaie d’éviter d’écrire lorsque j’ai choisi d’utiliser Spring. Toutefois, c’est une préférence, cela ne signifie pas que la configuration XML est supérieure à la configuration basée sur Java.

Spring possède également un chargeur de propriétés. Nous utilisons cette méthode pour définir des variables dépendant de l’environnement (par exemple, développement, test, acceptation, production, etc.). Ce pourrait être par exemple la file d'attente à écouter.

S'il n'y a pas de raison que la propriété change, il n'y a pas non plus de raison de la configurer de cette manière.

Votre cas est très simple et n’a donc pas besoin d’un conteneur IoC (Inversion of Control) comme Spring. Par contre, lorsque vous programmez des interfaces et non des implémentations, (ce qui est une bonne pratique en POO), vous pouvez avoir un code comme celui-ci:

IService myService;
// ...
public void doSomething() {
  myService.fetchData();
}

(notez que myService est de type IService - une interface et non une implémentation concrète). Il peut maintenant être pratique de laisser votre conteneur IoC fournir automatiquement la bonne instance concrète d'IService lors de l'initialisation - lorsque vous avez plusieurs interfaces et plusieurs implémentations, il peut être fastidieux de le faire à la main. Les principaux avantages d’un conteneur IoC (infrastructure d’injection de dépendance) sont les suivants:

  • Configuration externe du mappage entre les interfaces et leurs implémentations concrètes
  • Le conteneur IoC traite des problèmes complexes tels que la résolution de graphiques de dépendance complexes, la gestion de la durée de vie des composants, etc.
  • Vous gagnez du temps de codage car vous fournissez des mappages de manière déclarative, et non dans un code de procédure
  • Le principe d'inversion de contrôle facilite les tests unitaires car vous pouvez remplacer les implémentations réelles par de fausses (comme remplacer la base de données SQL par une en mémoire)

L’initialisation dans un fichier de configuration XML simplifiera votre travail de débogage / adaptation avec un client sur lequel votre application est déployée sur leurs ordinateurs. (Car il ne nécessite pas de recompilation + remplacement de fichiers binaires)

Le " principe d'Hollywood " ;: don 'est l'une des raisons les plus intéressantes. Appelez-nous, nous vous appellerons. Un composant n'est pas obligé de rechercher les autres composants et services lui-même; au lieu de cela, ils lui sont fournis automatiquement. En Java, cela signifie qu'il n'est plus nécessaire d'effectuer des recherches JNDI dans le composant.

Il est également beaucoup plus facile de tester un composant isolément: au lieu de lui donner une implémentation réelle des composants dont il a besoin, vous utilisez simplement des simulacres (éventuellement générés automatiquement).

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top