Iniezione di dipendenza con costruzione predefinita

4

La maggior parte del mio codice di produzione ha tipi fissi di dipendenze, illustrati di seguito: il House ad esempio, in fase di esecuzione, dipende sempre dallo stesso Kitchen .

Pertanto, mi sto chiedendo cosa ottengo avendo il House force chiunque lo costruisca a iniettare le sue dipendenze invece di fornire l'opzione per iniettare le dipendenze, cioè fornire sia un costruttore predefinito che un costruttore DI?

Ciò che si perde non consentendo la costruzione predefinita è facilmente visibile se si confrontano mainDI e mainDefault . Anche se ogni classe ha solo due dipendenze, se la profondità della gerarchia delle dipendenze è 3, come ad esempio nel percorso House -> Bedroom -> Bed , devi istanziare oggetti 2 ^ 3 nella classe di primo livello che sembra non fattibile per progetti di grandi dimensioni con una dipendenza profondità di gerarchia di 10 o più.

Avendo il costruttore DI, sono ancora in grado di testare una classe.

Quindi, per tutti gli esperti di DI in circolazione, qual è il lato negativo di questo approccio?

struct House {
  House(Bedroom ib, Kitchen ik) : b(ib), k(ik) {}
  House() : b(Bedroom()), k(Kitchen()) {}
  private:
    Bedroom b;
    Kitchen k;
}

struct Bedroom {
  Bedroom(Bed ib, Lamp il) : b(ib), l(il) {}
  Bedroom() : b(Bed()), l(Lamp()) {}
  private:
    Bed b;
    Lamp l;
}

struct Bed {
  Bed(Frame if, Mattress im) : f(if), m(im) {}
  Bed() : f(Frame()), m(Mattress()) {}
  private:
    Frame f;
    Mattress m;

}


mainDefault() {
  House h()
}


mainDI() {
    Frame f;
    Mattress m;
    Bed b;
    Lamp l;
    Kitchen k;

    Bed b(f, m);
    Bedroom br(b, l);    
    House h(br, k);        
}
    
posta user695652 18.03.2017 - 18:06
fonte

3 risposte

5

Even if each class has only has two dependencies, if the dependency hierarchy depth is 3, as for example in the House -> Bedroom -> Bed path, you have to instantiate 2^3 objects in your top level class which seems unfeasible for large projects with a dependency hierarchy depth of 10 or more.

Non commettere errori, sei ancora che istanzia gli oggetti da qualche parte .

Therefore, I am wondering what I gain by having the House force whoever constructs it to inject its dependencies as opposed to provide the option to inject the dependencies, i.e. provide both a default constructor and a DI-constructor?

Ottieni visibilità. Se la tua classe principale veramente è la cosa che decide ciò che viene istanziato in profondità nella tua gerarchia, questo è un odore. Un odore enorme a seconda della profondità della gerarchia, dal momento che le classi stanno perdendo i dettagli di implementazione fino in fondo.

Nascondendo ciò dietro un costruttore predefinito (o peggio, e un contenitore IoC), stai nascondendo tutto questo accoppiamento. Dovresti invece lavorare per rimuovere quell'accoppiamento dove ha senso. Otterrai i costruttori semplificati e tutti gli altri vantaggi del codice disaccoppiato.

    
risposta data 18.03.2017 - 19:05
fonte
1

Quando usi Dependency Injection non devi passare un numero esponenziale di argomenti attraverso il costruttore. Invece hai una classe Assembler (simile a una Factory) che può essere configurata per creare oggetti per te da qualsiasi classe configurata. Questo dovrebbe lasciare il tuo codice di classe pulito, senza un numero esponenziale di parametri, ma ti darà anche la possibilità di cambiare facilmente l'implementazione.

Il problema con il tuo approccio è che dovrai passare un numero esponenziale di argomenti durante il test dell'integrazione.

Martin Fowler ha una spiegazione dettagliata su come usare DI: link

    
risposta data 18.03.2017 - 18:46
fonte
0

Va bene per soluzioni di piccole dimensioni con un progetto / libreria.
In questo caso la tua classe Home è responsabile della creazione di oggetti da cui dipende.

Per le soluzioni più grandi, dove le classi Home , Bedroom e Bed sono in librerie diverse, questo approccio violerà il principio "Inversion of Control". Perché i tipi di livello superiore dipenderanno da tipi di livello inferiore.
Pertanto, quando apporti le modifiche interne alla classe Bed , dovrai ricompilare l'intera soluzione.

Se invece le classi di livello superiore dipendono dalle astrazioni, puoi lavorare con classi di livello inferiore senza dover ricompilare l'intero sistema.

In questo caso è necessario creare un progetto di un punto di ingresso con il metodo Main . Questo sarà solo un progetto che conoscerà tutte le dipendenze e costruirà un intero oggetto grafico per la tua applicazione.

    
risposta data 21.03.2017 - 06:21
fonte

Leggi altre domande sui tag