39 votes

Comprendre la nécessité d'un cadre DI

Ce pourrait être une question naïve. Je suis présentement en train d'apprendre le framework Spring et l'injection de dépendance. Alors que le principe de base de la DI est plutôt facile à saisir, il n'est pas immédiatement évident pourquoi vous avez besoin d'élaborer un cadre pour la mettre en œuvre.

Considérez les points suivants:

public abstract class Saw
{
    public abstract void cut(String wood);
}

public class HandSaw extends Saw
{
    public void cut(String wood)
    {
        // chop it up
    }
}

public class ChainSaw extends Saw
{
    public void cut(String wood)
    {
        // chop it a lot faster
    }
}

public class SawMill
{
    private Saw saw;

    public void setSaw(Saw saw)
    {
        this.saw = saw;
    }

    public void run(String wood)
    {
        saw.cut("some wood");
    }
}

Ensuite, vous pouvez tout simplement faire:

Saw saw = new HandSaw();
SawMill sawMill = new SawMill();
sawMill.setSaw(saw);
sawMill.run();

Ce qui serait équivalent à:

<bean id="saw" class="HandSaw"/>

<bean id="sawMill" class="SawMill">
   <property name="saw" ref="saw"/>
</bean>

plus:

ApplicationContext context = new ClassPathXmlApplicationContext("sawmill.xml");
SawMill springSawMill = (SawMill)context.getBean("sawMill");
springSawMill.run();

Accordé, c'est une contrieved exemple, et plus complexes les relations d'objet, il peut être plus efficace pour ranger un fichier XML que l'écriture par programme, mais il doit sûrement y avoir plus que cela?

(Je sais que le framework Spring est plus que ça, mais je suis en train de penser à la nécessité d'un conteneur d'injection de dépendances.)

Dans le premier exemple il devrait également être facile à changer les dépendances au milieu du gué:

// gotta chop it faster
saw = new ChainSaw();
sawMill.setSaw(saw);
sawMill.run();

15voto

Ran Biron Points 3015

J'ai eu exactement la même question, et il a été répondu par ceci:
Certes, vous pourriez faire ce que vous avez décrit dans "Alors vous pourriez tout simplement faire:..." (appelons cela "classe A"). Toutefois, cela couple de la classe A à la Scie à main, ou de toutes les dépendances nécessaires à partir de la classe de la Scierie. Pourquoi Un être couplé à une Scie à main ou, si vous prenez un scénario plus réaliste, pourquoi ma logique métier à être couplé à la connexion JDBC mise en œuvre nécessaires pour la couche DAO?
La solution que j'ai proposé était alors ", puis déplacer les dépendances d'une étape" - ok, alors maintenant j'ai mon point de vue, couplée à la connexion JDBC, où je ne devrait traiter que de l'HTML (ou Swing, choisissez votre saveur).

Le DI-cadre, configuré par un fichier XML (ou JavaConfig) résout ce problème en vous permettant de dire que "le service". Vous ne se soucient pas comment il est initialisé, ce qu'il doit fonctionner, vous venez juste d'obtenir l'objet du service et de l'activer.

Aussi, vous avez une idée fausse qui circulent sur le "plus:" (où vous ne SawMill springSawMill = (SawMill)context.getBean("sawMill"); springSawMill.run();) - vous n'avez pas besoin d'obtenir de la scierie de la fève de contexte - la scierie bean devrait avons été injecté dans votre objet (classe A), par la DI-cadre. ainsi, au lieu de ...getBean(...), vous devriez juste aller "à la scierie.run()", sans se soucier d'où il vient, qui initialisé et comment. Pour tous les soins, il pourrait aller tout droit vers /dev/null, ou de sortie de test ou réel CnC moteur... Le point est que - vous n'avez pas de soins. Tout ce que vous aimez est votre tout petit peu de classe à Un qui devrait faire ce qu'il a contracté pour faire activer un moulin à scie.

15voto

Apocalisp Points 22526

L'injection de dépendance est une forme dégénérée de paramètre implicite, en passant, et le but est essentiellement le même, à résoudre ce qu'on appelle Les Configurations Problème:

Les configurations problème est de propager au moment de l'exécution des préférences dans un programme, permettant simultané de plusieurs ensembles de configuration à coexister en toute sécurité sous le statiquement la garantie de la séparation.

L'Injection de dépendance des cadres de compenser le manque de paramètres implicites, des fonctions Curryfiées, et des installations pratiques pour monades dans la langue.

12voto

duffymo Points 188155

Le printemps a trois caractéristiques qui sont tout aussi importants:

  1. l'injection de dépendance
  2. la programmation orientée aspects
  3. la bibliothèque de classes du framework à l'aide de l'obstination, l'accès à distance, web mvc, etc.

Je suis d'accord que c'est dur de voir un avantage à l'injection de dépendance lorsque vous comparez cela à un seul appel à nouveau. Dans ce cas, cette dernière va certainement regarder de plus simple, parce que c'est une seule ligne de code. Le printemps de configuration va toujours augmenter les lignes de code, il n'est donc pas un argument gagnant.

Il commence à chercher beaucoup mieux quand vous pouvez prendre un transversales inquiétudes, comme les transactions de vos classes et d'utiliser les aspects de les mettre en place de manière déclarative. La comparaison à un seul "nouveau" appel n'est pas ce que le Printemps a été créé pour.

Peut-être le meilleur résultat de l'utilisation, le Printemps est la façon dont elle recommande l'idiome utilise des interfaces, de superposition et de bons principes, comme la sécheresse. C'est vraiment juste la distillation de l'orienté objet meilleures pratiques de Rod Johnson utilisé dans sa consultation de concerts. Il a constaté que le code qu'il a construit au fil du temps, l'a aidé à se faire de l'argent de livrer des logiciels de meilleure qualité pour ses clients. Il a résumé son expérience dans "Expert 1:1 J2EE", et qui finit open source le code Source.

Je dirais d'acheter dans le cadre de la mesure que vous pensez que son expérience peut vous aider à mieux écrire le code, trop.

Je ne pense pas que vous pouvez obtenir la pleine valeur de Printemps jusqu'à ce que vous les combinez tous les trois de ces éléments.

6voto

matt b Points 73770

Accordé, c'est une contrieved exemple, et plus complexes les relations d'objet, il peut être plus efficace pour ranger un fichier XML que l'écriture par programme, mais il doit sûrement y avoir plus que cela?

Je pense qu'il est plus logique de mettre le "câblage" dans un fichier de configuration plutôt que de le faire manuellement dans le code pour plusieurs raisons:

  1. La configuration est à l'extérieur de votre code.
  2. Modifications de câblage (pour dire à votre sawmill utiliser un autre exemple de l' Saw) peut simplement être fait à l'externe (fichier XML et ne nécessitent pas de modification du code, re-compilation, de re-déploiement, etc.
  3. Lorsque vous avez des dizaines de classes, et plusieurs couches d'injection (par exemple: vous avez un site web Controller de la classe qui obtient un Service de la classe qui contient une logique d'entreprise, qui utilise un DAO pour obtenir de l' Saws à partir de la base de données, qui reçoit un DataSource injecté dans l'informatique, etc.), manuellement câblage des collaborateurs est fastidieux et nécessite que quelques dizaines de lignes de code qui ne font rien, mais de câblage.
  4. C'est un peu moins d'une claire "avantage", mais en ayant toutes le " câblage externe pour le code, je pense que ça aide à renforcer les développeurs les idées qui sont au cœur de l'injection de dépendance, en particulier, l'idée de codage de l'interface, pas de la mise en œuvre. Avec le manuel de câblage, il peut être facile de retomber dans les anciennes façons.

5voto

Jasper Bekkers Points 4949

En général, je ne me soucie pas de XML ou des DI basés sur Reflection car, dans mes cas d'utilisation, cela ajoute une complexité inutile. Au lieu de cela, je choisis généralement une forme de DI manuelle qui me semble plus naturelle et qui présente la plupart des avantages.

 public class SawDI{
	public Saw CreateSaw(){
		return new HandSaw();
	}

	public SawMill CreateSawMill(){
		SawMill mill = new SawMill();
		mill.SetSaw(CreateSaw());
		return mill;
	}
}

// later on

SawDI di = new SawDI();
SawMill mill = di.CreateSawMill();
 

Cela signifie que je centralise toujours le couplage et que je bénéficie de tous les avantages qui en découlent, sans dépendance vis-à-vis d’un cadre d’ID plus complexe ou des fichiers de configuration XML.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X