Cos'è l'inversione del controllo e quando dovrei usarlo?

63

Sto progettando un nuovo sistema e voglio sapere quale inversione di controllo (IOC) è, e soprattutto, quando usarla.

Deve essere implementato con interfacce o può essere fatto con le classi?

    
posta Jedi Master Spooky 05.09.2008 - 05:32
fonte

4 risposte

61

IoC (vedi Inversion of Control su Wikipedia) è applicabile nei casi in cui un componente non è in grado di eseguire completamente un'attività perché non ha alcune informazioni o funzionalità necessarie.

L'esempio più semplice di uno schema IoC è rappresentato dalle funzioni di callback in C. Ad esempio è possibile dichiarare la funzione:

void Iterator(void *list, Func* f)

Che itera su list applicando la funzione f a ciascun elemento. La funzione Iterator non sa come verrà elaborato ciascun elemento, fornisci semplicemente una funzione come argomento e le elabora.

Come mostra l'esempio precedente, IoC ti consente di disaccoppiare il tuo programma in componenti separati che non si conoscono l'un l'altro. Una delle versioni più comuni di IoC è Iniezione di dipendenza .

In Iniezione di dipendenza ogni componente deve dichiarare un elenco di dipendenze richieste per eseguire l'attività. Durante il runtime, un componente speciale (in genere) chiamato Contenitore IoC esegue il binding tra questi componenti. Prova a fornire valori per le dipendenze dei componenti pubblicati.

Ecco un esempio in pseudo-codice:

class Foo 
{ 
   <Require Boo>Constructor(Boo boo){ boo.DoSomething } 
}

In questo esempio, la classe Foo ha un costruttore che richiede un argomento di tipo Boo per eseguire qualche azione.

Potresti creare un'istanza di classe Foo usando un codice simile a questo:

MyContainer.Create(typeof Foo)

MyContainer - è un contenitore IoC , che si occupa di ottenere l'istanza di Boo e di passarla al costruttore di Foo .

In breve, IoC ti consente di disaccoppiare il tuo programma in parti separate. Ciò è positivo perché:

  • I componenti possono essere facilmente testati in modo indipendente.
  • La complessità del programma può essere ridotta.
  • È possibile cambiare i componenti in un'altra implementazione.

Tuttavia, in alcuni casi, IoC può rendere il codice più difficile da comprendere.

Se vuoi vedere un buon esempio di utilizzo di IoC nel mondo reale, dai un'occhiata a Mircosoft Blocco di applicazioni dell'interfaccia utente combinata e CompositeWPF

Spero che la mia spiegazione ti aiuti.

Saluti,
AKU

    
risposta data 05.09.2008 - 05:44
fonte
18

Da quando mi sono occupato di questo da solo, e ho conservato tutti i segnalibri, il seguente ho trovato inestimabile per l'apprendimento di IOC / DI.

Martin Fowlers Articolo originale su IOC / DI

Alcuni concetti da conoscere prima

Un'eccellente raccolta di tutorial IOC / DI

Prenota su IOC / DI Da Manning Press

Fonte e spiegazione su come creare il tuo CIO personale - Perché leggere il codice sorgente è sempre il migliore modo per capire un concetto.

    
risposta data 05.09.2008 - 06:08
fonte
4

Ehi JMS, fondamentalmente IoC / DI ti consentirà di definire quale implementazione stai usando una volta e di mantenere una copia statica del tuo contenitore per fare riferimento ogni volta che vuoi farvi riferimento.

Probabilmente la Wikipedia ti aiuterà, ma volevo fare riferimento alla tua seconda parte - sì, l'iniezione di dipendenza può essere fatta per le classi (cioè, ogni volta che questo tipo di classe deve essere passato a un metodo, usa questa classe), ma è meglio usare le interfacce, perché in questo modo puoi cambiare la versione di un provider, repository, ecc. che stai usando semplicemente rinviandola nella tua configurazione.

Ad esempio, supponiamo che tu abbia un'interfaccia per leggere uno stream e che tu abbia implementato XMLStreamReader e SQLStreamReader. Quindi puoi passare il riferimento all'interfaccia ai tuoi metodi e poi nel tuo contenitore IoC dirgli quale usare.

Quindi, potresti avere Public List ReadPeople (lettore IStreamReader) e nella tua configurazione per il tuo contenitore IoC comunicarlo, ogni volta che ti aspetti che IStreamReader usi SQLStreamReader.

Quindi se cambi idea in seguito, devi solo cambiarlo in un unico punto (la configurazione del tuo contenitore) e non importa quanti metodi richiedono un IStreamReader, otterrà sempre il valore predefinito che hai detto il tuo contenitore da pubblicare.

    
risposta data 05.09.2008 - 06:00
fonte
3

Supponiamo che tu abbia un validatore per verificare se un'azienda è o meno valida nel tuo sistema. Il tuo "BusinessValidator" potrebbe avere un campo di tipo AddressValidator che convalida la parte di indirizzo dell'attività. Se si desidera testare BusinessValidator senza eseguire codice esterno (ovvero il codice addressValidator), se nel proprio framework è stato utilizzato qualche tipo di IoC / DI è possibile "inserire" un mock addressValidator nella propria posizione e non doversi preoccupare dei test codice al di fuori dell'ambito della classe in esame.

    
risposta data 05.09.2008 - 06:48
fonte

Leggi altre domande sui tag