2009-02-26 19 views

risposta

9

Leggi l'eccellente article di Martin Fowler.

Inoltre, dai un'occhiata allo wikipedia article.

Dependency Injection è l'esempio più noto di inversione del controllo, che in breve si trasforma il codice da questo:

public class FileReader { } 
public class Application { 
    // inflexible concrete dependency 
    private FileReader fileReader = new FileReader(); 
} 

A:

public interface Reader {} 
public class FileReader implements Reader {} 
public class Application { 
    // flexible abstract dependency injected in 
    private Reader reader; 

    public Application(Reader reader) { // constructor injection 
     this.reader = reader; 
    } 
    public void setReader(Reader reader) { // setter injection 
     this.reader = reader; 
    } 
} 
+1

toolkit == quickDraw. – duffymo

+0

(soffia il fumo dalla canna) – toolkit

+0

eh? è uno scherzo? –

4

No, CIO non è DDD o TDD .

Martin Fowler's article è una buona introduzione.

+0

Accettare il 100%, ma l'IOC è quasi obbligatorio per un buon TDD. ;-) –

+0

Siamo spiacenti, posto sbagliato. Significa aggiungere ad altra risposta. –

+0

No, ero sul posto, quindi sto solo aggiungendo commenti dimostrando che sono un totale dolt oggi. –

1

Per la tua domanda su cos'è CIO, Wikipedia ha un fairly extensive explanation.

Per quanto riguarda i tutorial o gli esempi il tutorial this lo copre abbastanza bene e ha un sacco di codice exmaple.

+0

+1, solo per la citazione di DeMarco. – duffymo

12

IOC, o inversione del controllo, è, nella maggior parte delle app, invertire il percorso attraverso il codice dall'interfaccia utente al database. Questa non è una risposta completa, ma è uno dei modi più semplici per capovolgere il concetto.

Se si desidera imparare IOC, entrare in TDD, poiché è molto più semplice eseguire i test di impostazione dopo l'inversione.

Esempio:

tipico flusso della maggior parte delle applicazioni .NET che ho visto è qualcosa di simile:

UserCollection col = BusinessLayer.Class.GetLoggedInUsers(); 
//Business logic 
return col; 

quindi business è simile a questo:

UserTable table = DataLayer.Class.GetLoggedInUsers(); 
return table; 

ecc Questo è tutto pseudocodice. Per utilizzare IOC in questo esempio, si aggiunge un'interfaccia per la classe del livello dati, come IUserRepository. Puoi usare i generici e io consiglierei sotto il cofano.

È quindi possibile fare qualcosa del genere:

IUserRepository repository = SetUpRepository(); 
UserCollection col = BusinessLayer.Class.GetUsers(repository); 

Perché è importante? Per i test, è possibile creare un repository fittizio e alimentarlo alla business class. Il mock contiene dati sempre uguali, il che significa che stai esercitando il tuo codice, non testando end-to-end.

Se si desidera C#, ecco un esempio di base su weblogs.asp.net:

0

Se si capisce DIP (Dipendenza Inversion Principle), CIO è la torta. Suggerisco di imparare i principi orientati agli oggetti prima di apprendere i modelli. I principi fondamentali possono essere impilati come lego per realizzare qualsiasi modello.Brandon Joyce

7

Per parlare in gergo, l'inversione di controllo è uno schema che supporta, tra le altre cose, il principio di responsabilità singola.

Per ottenere il motivo per cui tutto ciò è utile, è necessario un po 'di esposizione, quindi portami con me.

La singola responsabilità significa fondamentalmente che la classe deve essere il più indipendente possibile da altre parti del sistema, per ridurre al minimo l'impatto del cambiamento di una parte sull'altra. (Puoi anche ricollegarlo al fatto che la modifica dell'implementazione non dovrebbe innescare la ricompilazione di tutti i file nei tuoi progetti, come nel caso della modifica dei file .h in un progetto C/C++, ad esempio). L'effetto collaterale è che si finisce con un sacco di piccoli oggetti che fanno solo una cosa, ma molto bene (in un mondo ideale)

Ma nella maggior parte dei casi, per svolgere il suo lavoro, un oggetto deve parlare con altro oggetto: dipende da loro.

Prima parte dell'attenuazione che separa l'implementazione dalle interfacce. Ciò significa affidarsi a interfacce (o classi puramente astratte, a seconda della lingua di scelta), in modo che un oggetto non sia legato all'implementazione specifica di un altro.

Quindi, per usare un esempio canonico, nei bisogni livello di business, è necessario svolgere una funzione che ha bisogno di accedere a - Lo strato di dati per recuperare oggetti - qualche altro servizio - un registratore per registrare le informazioni eo errori

A sua volta, ogni servizio o dipendenza ha le sue dipendenze, di cui la classe dovrebbe essere a conoscenza anche se non le utilizza. A seconda della quantità di riferimenti, l'impostazione dell'oggetto può andare rapidamente fuori mano. Ora moltiplicalo per il numero di classi che devi scrivere e finisci con un casino di cose.

L'utilizzo di un contenitore IOC aiuta a liberarsi di questo pasticcio. Quando hai bisogno di un oggetto, non lo "fai da te". Invece chiedi al contenitore IOC di recuperarlo per te. Il contenitore è responsabile della consegna di un oggetto funzionale, pronto per essere utilizzato, indipendentemente dalle sue dipendenze.

Ciò significa che la classe non ha bisogno di essere consapevole delle dipendenze delle classi su cui fa affidamento, il che riduce il groviglio. Inoltre, non ha bisogno di sapere quale classe reale implementa i servizi su cui si basa, ovvero - L'implementazione del servizio può essere definita in un altro progetto (DLL o qualsiasi altra cosa), quindi la modifica non avrà alcun impatto sulla classe - L'implementazione può essere diverso a seconda del contesto (pensare a cambiare il database, o anche andare a un servizio web per recuperare le informazioni a seconda della configurazione o anche lo stato attuale dell'applicazione).

Per provare a rispondere alle altre domande, IOC è uno schema. TDD e DDD sono metodologie di progettazione, quindi non si può equiparare l'altro. Ma IOC è uno strumento inestimabile per supportare TDD o DDD.

Conosco la zuppa acronimo e i campioni parziali che si possono trovare in giro non sono facili da preparare. Il miglior consiglio che posso darti è di provare alcuni piccoli progetti sul lato, i prototipi che ti abbandoneranno, solo per avere una mano su queste cose. Non è un modo semplice per andare se lo si guarda per lavoro, ma ne vale assolutamente la pena, anche se solo da un punto di vista personale.

La speranza aiuta un po '.

0

Inversion of Control è l'astrazione della struttura della logica. Un approccio (spesso usato come sinonimo di IoC) è Dependency Injection, che astrae i riferimenti tra gli oggetti. Quando gli oggetti vengono liberati dai dettagli di implementazione di un'applicazione, ad esempio quale classe implementa il servizio, sono liberi di concentrarsi sulle loro funzioni principali.

Ad esempio, supponiamo di avere una classe che deve mappare gli oggetti negli oggetti Bar. Si potrebbe scrivere questo:

public class FooMapper 
{ 
    public Bar Map(Foo foo) 
    { 
     // ... 
    } 
} 

e usarlo in questo modo:

public class NeedsToMapFoos 
{ 
    public void MapSomeFoos() 
    { 
     var fooMapper = new FooMapper(); 

     // ... 
    } 
} 

Mentre valida, anche questo è rigida. NeedsToMapFoos si preoccupa solo che la mappatura si verifichi, non che si verifichi in un modo specifico.

Siamo in grado di rappresentare il concetto di "implementazione di funzionamento sans" con interfaccia:

public interface IFooMapper 
{ 
    Bar Map(Foo foo); 
} 

e dichiarare una dipendenza da questa operazione:

public class NeedsToMapFoos 
{ 
    private readonly IFooMapper _fooMapper; 

    public NeedsToMapFoos(IFooMapper fooMapper) 
    { 
     _fooMapper = fooMapper; 
    } 

    public void MapSomeFoos() 
    { 
     // ...use _fooMapper... 
    } 
} 

Ora NeedsToMapFoos ha meno conoscenza, il che significa che è meno complesso. Invece di svolgere compiti amministrativi, è libero di concentrarsi sul business case.

Gli oggetti ben fatti come questo sono anche più adattabili. Proprio come i diamanti sono rigidi e l'argilla è malleabile, la struttura interna determina la risposta al cambiamento.

Infine, anche la logica scritta in questo stile è flessibile. Diciamo che FooMapper.Map è un'operazione costosa e dovrebbe essere memorizzata nella cache. È possibile utilizzare il modello decorator per avvolgere l'implementazione esistente e senza passarlo al NeedsToMapFoos:

public class CachingFooMapper : IFooMapper 
{ 
    private readonly IFooMapper _innerMapper; 
    private readonly IDictionary<Foo, Bar> _cache; 

    public CachingFooMapper(IFooMapper innerMapper) 
    { 
     _innerMapper = innerMapper; 
    } 

    public Bar Map(Foo foo) 
    { 
     // Read bar from _cache. If not there, read from inner mapper and add to _cache. 
    } 
} 

// Usage 

new NeedsToMapFoos(new CachingFooMapper(new FooMapper())); 
Problemi correlati