2015-08-05 8 views
7

In generale, le mie dipendenze sono astratte alle interfacce, ma userò solo un'implementazione concreta durante l'utilizzo non di test. Ad esempio, se io scrivo un FooService:Iniezione di dipendenza: cosa si perde quando si istanziano le classi concrete nel costruttore senza parametri

public class FooService : IFooService 
{ 
    private readonly IBarDependency _barDependency; 

    public FooService(IBarDependency barDependency) 
    { 
     this._barDependency = barDependency; 
    } 

    public FooService() : this (new BarDependency()) 
    { 
     // nothing to do here 
    } 

    . . . // code goes here 
} 

Ora puristi tendono a boccheggiare per l'orrore, perché ho istanziato una classe concreta nel costruttore senza parametri. In passato, l'ho scrollato di dosso, perché so che l'unica volta in cui non userò la lezione concreta è quando collaudo unità e dipendenze beffarde.

Mentre lo fa paio classe FooService alla classe BarDependency, non è uno stretto accoppiamento; queste classi e interfacce esistono anche nello stesso assembly, quindi non mi sembra che io stia perdendo molto qui o dipingendo me stesso in un angolo. Posso ancora facilmente testare la classe FooService senza ottenere codice ingestibile, semplicemente usando il costruttore che mi permette di passare in interfacce fittate.

Quindi la domanda è: che cosa è effettivamente a rischio qui? Cosa sto perdendo con questo tipo di schema che vale la pena aggiungere un contenitore IoC?

+0

Io uso lo stesso approccio in piccoli progetti. DI e altre regole del "fare bene" di solito rendono i piccoli progetti eccessivamente complessi. Certo, porta molti vantaggi ma non vale sempre la pena. –

risposta

6

Gestione della durata, ad esempio. Forse usi il codice BarDependency per tutto il tuo codice e vuoi che una sola istanza sia viva. Non è possibile farlo se ogni utente crea le proprie istanze.

È inoltre necessario trovare tutti gli usi di new BarDependency() se si desidera sostituirlo con new NewBarDependency().

Un contenitore risolve entrambi i problemi, poiché in questo modo si configura l'istanziazione e il ciclo di vita degli oggetti in un unico metodo, vale a dire dove si imposta il contenitore.

+0

Quindi stai suggerendo che il contenitore di IoC è più adatto all'iniezione di pattern Singleton? Ciò ha senso. –

+1

Sì, è possibile utilizzare una durata "una sola volta per AppDomain", quindi non è necessario singoletti o classi statiche. – CodeCaster

1

Quello che si perde senza dipendenza è l'iniezione della capacità di centralizzare tutti gli aspetti della gestione delle dipendenze. Visualizzare il grafico delle dipendenze e gestire i cicli di vita dei tuoi oggetti è più facile quando hai tutte le informazioni in un posto, invece che sparse per tutto il codice.

Un esempio concreto sarebbe se si volesse sostituire l'implementazione predefinita di IBarDependency utilizzata in alcune, ma non in tutte le classi. Ragionare su quali sostituire è molto più semplice se le dipendenze sono tutte collegate nello stesso file o gruppo di file.

2

Dipende, ma se FooService deve essere accessibile da qualche altro sviluppatore, la dipendenza da BarDependency sarà fondamentalmente nascosta. A mio avviso, non solo il mocking e il testing sono la ragione per usare l'injection dependency, ma anche una chiara indicazione su ciò che viene utilizzato da alcune classi e su ciò di cui hanno bisogno per funzionare correttamente. E forse sono molto purista, ma quando un tale schema è ok, allora è facile andare oltre e finire con un codice totalmente accoppiato e duraturo.

Problemi correlati