Quali sono i vantaggi dell'utilizzo di Dependency Injection e IoC Container?


62

Sto programmando di fare un discorso su Dependency Injection e IoC Containers e sto cercando alcuni buoni argomenti per usarlo.

Quali sono i vantaggi più importanti dell'utilizzo di questa tecnica e di questi strumenti?


1
Vedi qui e qui per le risposte StackOverflow e qui per un buon articolo completo su IoC. E se vuoi argomenti contro di esso per il confronto, vai qui su SO.
Jesse C. Slicer,

14
non essere un calcio ... ma se non sai perché DI / IOC dovrebbe essere usato, perché ne parli? perdere una scommessa? ;-)
Steven A. Lowe,

2
@Steven, il suo capo avrebbe potuto chiedergli di farlo.

1
@Steven, uso già DI tutto il tempo (alcuni direbbero troppo spesso MrGreen), sto solo cercando dei buoni argomenti per convincere altre persone a usarlo.
Andy Lowry,

2
Le persone raramente parlano dell'abuso di DI. Se ritardi ogni singola decisione, creerai l'equivalente OO del codice spaghetti. Avere un design coerente richiede che, ad un certo punto, venga presa una vera decisione.
Macneil,

Risposte:


47

La cosa più importante, per me, è semplificare il rispetto del principio della responsabilità singola .

DI / IoC mi semplifica la gestione delle dipendenze tra oggetti. A sua volta, ciò mi rende più semplice interrompere la funzionalità coerente nel proprio contratto (interfaccia). Di conseguenza, il mio codice è stato molto più modulare da quando ho appreso di DI / IoC.

Un altro risultato di questo è che posso vedere molto più facilmente la mia strada verso un design che supporta il principio aperto-chiuso . Questa è una delle tecniche più stimolanti per la fiducia (seconda solo ai test automatizzati). Dubito di poter sposare abbastanza le virtù del principio aperto-chiuso.

DI / IoC è una delle poche cose nella mia carriera di programmatore che è stata un "punto di svolta". C'è un enorme divario nella qualità tra il codice che ho scritto prima e dopo aver appreso DI / IoC. Vorrei sottolineare questo ancora. ENORME miglioramento della qualità del codice.


3
Perché il principio aperto-chiuso è un grosso problema? Se ritieni di dover modificare un'API / un'interfaccia, perché non dovresti?
Arne Evertsson,

@ArneEvertsson Ascolta Robert C. Martin che parla del principio aperto-chiuso. Sarai illuminato.
Alternatex,

@AmeEvertsson Open-Closed è molto importante quando il tuo codice viene fornito (ad esempio come prodotto commerciale) come modulo da usare per gli altri, in quanto rende il tuo codice più adattabile in uso senza che ti si riporti per cambiarlo
James Ellis-Jones

2
DI non semplifica la gestione delle dipendenze poiché è notevolmente più complessa della semplice creazione di una dipendenza da una classe concreta. Fornisce tuttavia flessibilità, ma a meno che non si eseguano test di unità "adeguati", tale flessibilità spesso non sarà necessaria. Entrambi i principali vantaggi descritti si applicano anche a Service Locator, che è più semplice.
James Ellis-Jones,

1
Ho votato in negativo questa risposta anni fa; ecco alcune osservazioni: 1) In pratica, l'uso estensivo di DI tende a funzionare contro SRP, perché i programmatori continuano semplicemente ad aggiungere metodi ai loro "controller", "servizi", "DAO" iniettati, ecc., invece di creare nuove classi per nuova funzionalità. È quello che normalmente vedi accadere nei progetti Java e C # .NET che usano un framework DI o un contenitore. 2) Il principio aperto-chiuso era proprio l'illusione di Bertrand Meyer sull'utilità dell'eredità di classe (implementazione); se lo cerchi nel suo libro di oltre 1400 pagine vedrai cosa intendo: è davvero sciocco.
Rogério,

9

Gli esempi che mi hanno davvero aperto gli occhi hanno visto come è stato possibile testare facilmente gli oggetti creati in questo modo. Prima di ciò, ho avuto problemi nel tentativo di isolare oggetti per un test unitario. Spesso scrivevo test per interagire con un sistema molto più grande. Questo è stato davvero difficile perché il sistema nel suo insieme era molto meno prevedibile e molto più incline a cambiare i singoli componenti.


3

I vantaggi delle iniezioni di dipendenza sono:

  1. Il tuo codice è pulito e più leggibile.
  2. I codici sono liberamente accoppiati.
  3. Più riutilizzabili poiché le implementazioni sono configurate nel file XML, può essere utilizzato in un contesto diverso.
  4. Il codice può essere facilmente testabile con diverse implementazioni simulate.

1

Penso che i benefici effettivi siano più politici che tecnici. DI è semplicemente un'alternativa al modello di Service Locator , niente di più. Di per sé, non rende più facile seguire principi come SRP o OCP o disaccoppiare i livelli. Altri intervistati qui stanno confondendo concetti e tecniche diversi, IMO.

È possibile raggiungere gli stessi obiettivi in ​​termini di elevata coesione e basso accoppiamento utilizzando Localizzatori di servizi o semplicemente istanziando le dipendenze direttamente ogni volta che è applicabile (il più delle volte).

Ora, so che molti non saranno d'accordo con questa opinione. Sarò felice di discutere esempi concreti.


2
Ma invocare direttamente un localizzatore di servizi o creare un'istanza di una dipendenza concreta di solito collega le tue dipendenze, o almeno da dove provengono le tue dipendenze. Questo sembra sconfiggere lo scopo di DI. Devi ancora iniettare anche il localizzatore di servizi.
Matt H

L'uso di un Service Locator non consente di cablare nulla tranne l'uso della stessa classe di Service Locator, che normalmente non viene "iniettata". L'istanza di una classe di implementazione concreta va perfettamente bene nei casi in cui non è necessaria una configurazione esterna (ad esempio, i programmatori di solito istanziano direttamente la classe ArrayList invece di utilizzare DI - che sarebbe eccessivo).
Rogério,

1
Si menziona "accoppiamento basso" e in seguito si afferma che un localizzatore di servizio non ha alcun impatto sul livello di accoppiamento di un'applicazione. Lo stesso per l'istanza dei collaboratori direttamente sul codice, non riesco a pensare a un modo più perfetto per accoppiare un oggetto con le sue dipendenze. In che modo test unitario di entrambi gli scenari? Rispettosamente, sono completamente in disaccordo con tutto ciò che hai detto.
Clint Eastwood,

@Jonathan Dovresti leggere l' articolo che ha introdotto DI allora; l'autore conclude dicendo che DI e ServiceLocator sono "approssimativamente equivalenti", con un "leggero vantaggio" per quest'ultimo. L'accoppiamento che conta è tra un componente e altri componenti che possono avere implementazioni multiple; un ServiceLocator è un servizio di infrastruttura con una sola implementazione, quindi va bene. Nota ho scritto "istanze delle dipendenze ogni volta che è applicabile "; ovviamente, se hai bisogno di separare la configurazione dall'uso, non lo faresti.
Rogério,

1
@Jonathan Per quanto riguarda i test unitari, è un mito che l'istanza di collaboratori impedisca la creazione di tali test; ci sono noti strumenti di derisione che svolgono il compito di isolare una classe dalle implementazioni delle dipendenze, indipendentemente dal fatto che vengano iniettate o meno.
Rogério,

-1

Quando si utilizza DI per esporre oggetti interni a scopo di test, il modello è stato abusato.


1
cosa intendi con "oggetti interni"? in OOP reale (si noti che probabilmente solo l'1% dei programmatori sa cosa significa veramente), ci sono oggetti che comunicano tra loro tramite l'invio di messaggi (ovvero invocazioni di metodi). In tal senso, ogni oggetto deve avere una sola responsabilità, non ci sono oggetti "più importanti" di altri ... ognuno ha un unico compito e collaborano per raggiungere la funzionalità fornita da tutto il sistema. È importante testare ogni oggetto in modo isolato, quindi sappiamo che non ci siamo persi nessun caso, ecco di cosa è bravo DI.
Clint Eastwood,

Ho dimenticato.
Thomas-Peter,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.