L'iniezione di dipendenza è a mano un'alternativa migliore alla composizione e al polimorfismo?

10

Per prima cosa, sono un programmatore entry level; In effetti, sto finendo un A.S. laurea con un progetto di pietra di copertura finale durante l'estate. Nel mio nuovo lavoro, quando non c'è un progetto da fare (sono in attesa di riempire la squadra con altri nuovi assunti), mi è stato dato dei libri da leggere e imparare mentre aspetto - alcuni libri di testo, altri non tanto (come il codice completo). Dopo aver esaminato questi libri, mi sono rivolto a Internet per imparare il più possibile e ho iniziato a conoscere SOLID e DI (abbiamo parlato del principio di sostituzione di Liskov, ma non di molte idee SOLIDE). Quindi, come ho appreso, mi sono seduto per imparare meglio, e ho iniziato a scrivere del codice per utilizzare DI a mano (non ci sono quadri DI sui computer di sviluppo).

Il fatto è che, mentre lo faccio, noto che sembra familiare ... e sembra che sia molto simile al lavoro che ho fatto in passato usando la composizione di classi astratte usando il polimorfismo. Mi manca un'immagine più grande qui? C'è qualcosa in DI (almeno a mano) che va oltre? Capisco la possibilità di avere configurazioni non in codice di alcuni framework DI con alcuni grandi vantaggi per quanto riguarda il cambio delle cose senza dover ricompilare, ma quando lo faccio a mano, non sono sicuro che sia diverso da quanto sopra ... Qualche idea su questo sarebbe molto utile!

    
posta Drake Clarris 01.06.2012 - 22:54
fonte

4 risposte

18

L'idea fondamentale in DI è semplicemente quella di spingere le dipendenze in oggetti, piuttosto che lasciarli estrarre le dipendenze dall'esterno. Questo è stato anche chiamato "inversione del controllo" in precedenza. Ciò consente di controllare molto meglio le dipendenze e, ultimo ma non meno importante, di scrivere codice facile da testare.

I framework DI si basano solo su questa idea e (in parte) automatizzano la parte spesso noiosa delle dipendenze degli oggetti di cablaggio insieme. In caso contrario, potrebbe richiedere una quantità significativa di codice in un progetto più grande quando è fatto a mano.

Per definire le dipendenze, oltre ai file di configurazione esterni, è anche possibile utilizzare le annotazioni del codice al giorno d'oggi, ad es. in lingue come Java e C #. Questi possono portare il meglio di entrambi i mondi: le dipendenze del cablaggio in uno stile dichiarativo, ma proprio all'interno del codice stesso, al quale logicamente appartiene. Per me, la possibilità di cambiare le dipendenze senza doverle ricompilare non è così importante, come raramente viene fatto nella vita reale (a parte alcuni casi speciali), ma introduce una separazione spesso artificiale delle dipendenze dalle classi e dagli oggetti definiti all'interno del codice .

Per tornare alla domanda del titolo, DI non è un'alternativa alla composizione né al polimorfismo; dopotutto, è reso possibile da questi due.

    
risposta data 01.06.2012 - 23:50
fonte
13

Il miglior articolo che abbia mai letto sull'argomento era James Shore's . Ho fatto " DI a mano " per anni, come parte dell'astrazione e polimorfismo. Quindi, dopo essere entrato nel mondo professionale e ho continuato a sentire che il termine veniva gettato, avevo una grande disconnessione tra ciò che pensavo che la parola dovrebbe dire e che cosa significhi realmente:

"Dependency Injection" is a 25-dollar term for a 5-cent concept.

Questo è il post di Shore, che ha chiarito tutto per me. Ad esempio:

Data

class Engine {public abstract void start()}
class V8 extends Engine {...}
class V6 extends Engine {...}

Invece di scrivere:

class Car
{
    private Engine engine;
    public Car()
    {
        this.engine = new V6();
    }

    public void start()
    {
        this.engine.start();
    }
}

Scrivi qualcosa del genere:

class Car
{
    private Engine engine;
    public Car(Engine a)
    {
        this.engine = a;
    }

    public void start()
    {
        this.engine.start();
    }
}

...

Car F = new Car(new V8());

E ciò consente alla specifica istanza Car di dover gestire specifici dettagli di Engine . Una macchina ha solo bisogno di un motore, non gli importa quale, purché implementa la funzionalità di base del motore. Cioè, la tua classe Car non è legata a specifiche dipendenze di implementazione; è "iniettato" altrove, potenzialmente in fase di runtime.

Questo specifico esempio di Car usa il sottotipo di DI chiamato "Costruttore Iniezione", il che significa semplicemente che la dipendenza è stata consegnata come argomento costruttore. Puoi anche utilizzare un metodo setEngine(Engine a) per "Iniezione di setti" e così via, ma questi sottotipi mi sembrano pedanti.

Ancora un po ', tuttavia, molti framework DI forniscono al boilerplate il collegamento di una serie di questi elementi più astrattamente referenziati l'uno sull'altro.

Questo è tutto.

    
risposta data 02.03.2016 - 21:57
fonte
0

Non sono un esperto in quanto ho iniziato a usare DI solo negli ultimi due anni, ma alcuni dei temi / funzionalità utili dei contenitori DI che ho notato sono (che non considero prodotti di composizione / polimorfismo (ma su questo posso essere corretto):

  • hub centrale per la creazione di oggetti
  • fornire singleton su una base per thread
  • tecniche orientate all'aspetto come l'intercettazione
risposta data 01.06.2012 - 23:15
fonte
0

Oltre a DI, esiste una configurazione di composizione di classe nell'applicazione root (invece di configurare usando xml). Non è necessario alcun framework DI o IoC, anche se possono riordinare la configurazione della composizione di classe, in particolare per i progetti di grandi dimensioni. Questo perché il framework DI viene normalmente fornito con container che implementano funzionalità aggiuntive, come il cablaggio automatico, che aiuta a configurare la composizione della classe. Puoi leggere la mia voce blog per estrarre la mia comprensione su questo argomento.

    
risposta data 07.06.2016 - 21:29
fonte