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


Risposte:


62

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

L'esempio più semplice di un modello IoC sarebbero le funzioni di callback in C. Ad esempio è possibile dichiarare la funzione:

void Iterator(void *list, Func* f)

Che ripete listsull'applicazione della ffunzione a ciascuno dei suoi elementi. La Iteratorfunzione non sa come verrà elaborato ogni elemento, basta fornire una funzione come argomento e li elabora.

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

In Dependency Injection ogni componente deve dichiarare un elenco di dipendenze richieste per eseguire la propria attività. In fase di esecuzione un componente speciale (generalmente) chiamato contenitore IoC esegue l'associazione tra questi componenti. Cerca di 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 Fooha un costruttore che richiede un argomento di tipo Booper eseguire alcune azioni.

È possibile creare un'istanza di classe Fooutilizzando un codice simile al seguente:

MyContainer.Create(typeof Foo)

MyContainer- è un contenitore IoC , che si occupa di ottenere l'istanza Booe passarlo al Foocostruttore.

In breve, IoC ti consente di disaccoppiare il tuo programma in parti separate. Questo va bene perché:

  • I componenti possono essere facilmente testati indipendentemente.
  • La complessità del programma può essere ridotta.
  • È possibile passare i componenti a un'altra implementazione.

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

Se vuoi vedere un buon esempio di utilizzo del mondo reale di IoC , dai un'occhiata a Mircosoft Composite UI Application Block e CompositeWPF

Spero che la mia spiegazione ti aiuti.

Saluti,
Aku


1
Cinque anni dopo, ma comunque ... Era una descrizione eccellente. Grazie.
Nick Hodges,

4
Non tanto menzionato da nessuna parte su IoC è il fatto che il codice diventa più difficile da leggere. La leggibilità è la priorità numero uno se si desidera scrivere un software eccezionale. Batte anche la testabilità. Puoi disaccoppiare il codice ben oltre la sua utilità.
Arne Evertsson,

Quindi, un codice che utilizza una soluzione basata su interfaccia per tutte le sue dipendenze si basa anche sulla progettazione IoC?
nikel,


4

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

Probabilmente 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 utilizzare le interfacce, perché in questo modo è possibile modificare la versione di un provider, repository, ecc. che si sta utilizzando semplicemente facendo riferimento alla configurazione.

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

Quindi, potresti avere ReadPeople (Lettore IStreamReader) pubblico e nella tua configurazione per il tuo contenitore IoC dirlo, ogni volta che ti aspetti che un IStreamReader usi SQLStreamReader.

Quindi, se cambi idea in un secondo momento, devi solo cambiarlo in un unico posto (l'installazione del tuo contenitore) e non importa quanti metodi richiedono un IStreamReader, otterrà sempre l'impostazione predefinita a cui hai detto al tuo contenitore servire.


3

Supponiamo che tu abbia un validatore per verificare se un'azienda è valida nel tuo sistema. Il tuo "BusinessValidator" può avere un campo di tipo AddressValidator che convalida l'indirizzo parte dell'azienda. Se si desidera testare BusinessValidator senza eseguire il codice esterno (ovvero il codice addressValidator), se si è utilizzato una sorta di IoC / DI nel proprio framework, è possibile "iniettare" un indirizzo falso Validator al suo posto e non doversi preoccupare di testare codice al di fuori dell'ambito della classe in esame.

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.