Domanda

Qualcuno può spiegare a me i vantaggi dell'utilizzo di un contenitore IOC oltre il semplice codifica predefinita nella realizzazione di un costruttore di default?

In altre parole, ciò che è sbagliato in questo codice?

public class MyClass
{
    private IMyInterface _myInterface;

    public MyClass()
    {
        _myInterface = new DefaultMyInterface();
    }

    public MyClass(IMyInterface myInterface)
    {
        _myInterface = myInterface;
    }
}

Per quanto posso dire, questa classe serve per l'iniezione del costruttore abbastanza così i test di unità e beffardo è fatto facilmente.Inoltre, il costruttore di default rimuove l'overhead computazionale dell'IOC container (per non parlare di tutto il processo è molto più trasparente).

Il solo benefici posso vedere all'utilizzo di un contenitore IOC è se avete bisogno di cambiare l'implementazione delle interfacce di frequente.Mi manca qualcosa?

È stato utile?

Soluzione

L'idea di Cio è di delegare una parte di componente funzionalità a un'altra parte del sistema.In Cio mondo, ci sono componenti che non sappiamo l'uno dell'altro.Il tuo esempio viola questo, come si sta creando accoppiamento stretto tra MyClass e alcuni attuazione di IMyInterface. L'idea principale è che il componente non ha alcuna conoscenza su come verrà utilizzato.Nel tuo esempio, il componente fa qualche ipotesi circa il suo utilizzo.

In realtà questo approccio può funzionare, ma la miscelazione del Cio ed esplicita l'inizializzazione dell'oggetto non è una buona pratica IMO.

Cio fornisce accoppiamento eseguendo tardiva per il prezzo del codice di chiarezza.Quando si aggiunge un ulteriore comportamento di questo processo, rende le cose ancora più complicate e può portare a bug quando alcuni componenti potenzialmente in grado di ricevere oggetti indesiderati o imprevisti comportamento.

Altri suggerimenti

Scegli un lato :)

In breve CIO è raccomandato.Il problema con il codice che non posso cambiare l'implementazione di default di dipendenza, senza dover ricompilare il codice come hanno dichiarato alla fine.CIO consente di modificare la configurazione o la composizione di oggetti in un file esterno senza necessità di ricompilazione.
CIO assume la "costruzione e montaggio di responsabilità" da il resto del codice. Lo scopo del CIO non è per fare il vostro codice testabile...è un piacevole effetto collaterale.(Proprio come TDDed codice porta ad una migliore progettazione)

Non c'è nulla di sbagliato in questo codice e si può ancora usare con la Dependency Injection framework come Spring e Guice.

Molti sviluppatori di vedere la Primavera del file di configurazione XML come un vantaggio su di cablaggio dipendenze all'interno del codice, come si può passare implementazioni senza il bisogno di una fase di compilazione.Questo beneficio è in realtà realizzato in situazioni in cui è già in possesso di diverse implementazioni compilato nel percorso della classe e si desidera scegliere l'attuazione in fase di distribuzione.Si può immaginare una situazione in cui un componente è fornito da terzi dopo la distribuzione.Allo stesso modo ci può essere un caso in cui si desidera spedire ulteriori implementazioni come una patch dopo la distribuzione.

Ma non tutti DI quadri di configurazione XML.Google Guice, per esempio, sono Moduli scritti come classi Java che deve essere compilato come qualsiasi altra classe java.

Così che cosa è il vantaggio DI se anche avete bisogno di un passaggio di compilazione?Questo ci riporta alla tua domanda originale.Posso vedere i seguenti vantaggi:

  1. Approccio Standard DI tutta l'applicazione.
  2. Configurazione nettamente separati dagli altri la logica.
  3. Capacità di iniettare proxy.La primavera, per esempio, ti permette di fare dichiarativa gestione di Transazioni con l'iniezione di proxy invece di implementazione
  4. Più facile ri-uso della logica di configurazione.Quando si utilizza DI estesamente, si vedrà un complesso albero delle dipendenze in continua evoluzione nel tempo.La gestione di esso, senza chiaramente separate livello di configurazione e il supporto per il framework può essere un incubo.DI quadri di rendere più facile il riutilizzo logica di configurazione tramite l'ereditarietà e altri mezzi.

L'unica preoccupazione che ho è (1) se il servizio predefinito dipendenza di per sé ha un altro / servizio secondario di dipendenza (e così via...il tuo DefaultMyInterface dipende ILogger) e (2) è necessario isolare il primo servizio di dipendenza dal secondo (necessario per verificare DefaultMyInterface con uno stub ILogger).In questo caso, evidentemente, dovrà perdere l'impostazione di default "nuovo DefaultMyInterface" e invece di fare uno di questi:(1) pura iniezione di dipendenza o (2) service locator o (3) contenitore.Accumulo(nuovo DefaultMyInterface());

Alcune delle preoccupazioni di altri manifesti elencati potrebbero non essere giusto per la tua domanda.Non stavi chiedendo più la "produzione" di implementazioni.Si stanno chiedendo i test di unità. Nel caso di unità tesing il tuo approccio con il mio primo avvertimento dichiarato, sembra legittimo;Anch'io vorrei prendere in considerazione di usarlo in semplici casi di test di unità.

Allo stesso modo, un paio responder espresso preoccupazione per repititiousness.Non mi piace repitition, ma se (1) l'implementazione di default è davvero di default (YAGNI:non hai piani su come modificare l'impostazione predefinita) e (2) non credo che il primo avvertimento ho detto vale e (3) preferire il codice più semplice l'approccio con cui hai condiviso, quindi non credo che questa particolare forma di repitition è un problema.

Oltre ad accoppiamento lasco, un Cio consentirà di ridurre la duplicazione del codice.Quando si utilizza un Cio e si desidera cambiare l'implementazione di default dell'interfaccia, è necessario modificare solo in un unico luogo.Quando si utilizza di default contructors per iniettare l'implementazione predefinita, è necessario modificare ovunque l'interfaccia è utilizzata.

In aggiunta agli altri commenti, si potrebbe argomentare che il LAVAGGIO (Non ripetersi) linea di principio, in questi casi.È redudnant a mettere quella di default il codice di creazione in ogni classe.È anche introducign speciale per la gestione del caso in cui non c'è bisogno di essere di qualunque tipo.

Non vedo perché la tua tecnica di inserire a mano l'implementazione di default non potrebbe essere utilizzato in combinazione con una IOC container.Solo, le dipendenze non specificate nella configurazione sarebbe l'implementazione di default.

O mi manca qualcosa?

Uno dei motivi si potrebbe desiderare di utilizzare un Contenitore IOC sarebbe quello di facilitare fine di configurazione del software.

Dire, per esempio, si forniscono le varie implementazioni di una particolare interfaccia - il cliente (o il vostro team di servizi professionali) può decidere quale utilizzare modificando CIO file di configurazione.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top