Quando usare DI e quando creare te stesso in Java

8

Ho una discreta quantità di OOP con varie lingue, ma sono piuttosto nuovo in Java.

Sto leggendo un sacco di tutorial in cui un gran numero di oggetti sono creati all'interno del codice di una classe, e sto provando a scorrerli, ma costruisco le versioni delle classi nelle esercitazioni che fanno Iniezione delle dipendenze invece di istanziare tutte le classi stesse.

Ma Java non è come le altre lingue che ho usato in quanto praticamente tutto è un oggetto. Se dovessi letteralmente iniettare tutto, il risultato sarebbe molto disordinato e difficile da seguire.

Ovviamente non si inietterebbero oggetti String, e suppongo che ci siano altri oggetti che non si inietterebbero, ma non sono sicuro di dove dovrebbe andare la linea. A che punto la DI smette di essere la cosa giusta da fare, e quando inizia ad essere un peso? Come decidi pragmaticamente cosa iniettare e cosa solo istanziare?

FYI, le esercitazioni che sto svolgendo sono link e collegamento per creare un semplice client e server. Tuttavia, non sto copiando la riga per linea, sto cercando di creare classi equivalenti che seguano le migliori pratiche

    
posta GordonM 11.03.2013 - 08:39
fonte

5 risposte

4

In .Net (che è simile a questo proposito che tutto è un oggetto), io uso DI principalmente con i miei oggetti di dominio (entità, repository e servizi) e oggetti applicativi (controllori, modelli di vista), quindi i repository / servizi ottengono iniettato nei modelli controller / view e simili. Ciò significa che la mia logica aziendale e applicativa è completamente testabile, il motivo principale per cui utilizzo DI.

Fondamentalmente gli oggetti a cui si iniettano e si iniettano cose, sono per lo più oggetti specifici per la soluzione che si sta costruendo. Se alcuni oggetti sono "nativi" nella lingua o nel framework (come .Net), probabilmente non è necessario iniettarli. Molti oggetti hanno bisogno di una stringa per rappresentare i dati, e una stringa è fondamentalmente una "caratteristica linguistica" che non è specifica per il tuo dominio. La stessa cosa vale per enumerables, liste, array e un sacco di altre cose che non hanno bisogno di cambiare quando si desidera eseguire la classe in isolamento dal resto del sistema.

La cosa più importante da guardare è l'accoppiamento tra le tue classi dominio / applicazione. Se un oggetto non introduce un accoppiamento stretto, di solito è sicuro crearlo. Uno dei modi per verificare l'accoppiamento è provare a eseguire i metodi in una classe in isolamento (che è fondamentalmente test dell'unità). Ciò che deve essere DI-ed è tutte le dipendenze che è necessario prendere in giro, per essere sicuri che la classe che stai testando sia effettivamente in esecuzione dal sistema.

    
risposta data 11.03.2013 - 11:18
fonte
4

In primo luogo, è OK usare la nuova parola chiave, davvero! DI è una tecnica fantastica, ma c'è la tentazione di abusarne. I tempi in cui potresti voler utilizzare DI sono:

  • Test doppio - Spesso con i test unitari si desidera eseguire il mock out / testare una doppia risorsa di terze parti, poiché non si desidera portare in alto quella risorsa di terze parti (ad esempio, un DB Oracle completo). Ad esempio, invece di creare una nuova connessione al database del grande DB Oracle, potresti voler sostituire quella connessione con una ad un HSQL (nel database di memoria).

  • Quando si desidera controllare l'ambito (~ durata di vita) di quell'oggetto e il ciclo di vita dell'oggetto naturale Java non funziona per voi. Molti framework basati su Java ti consentono di farlo.

  • Quando vuoi i singleton.

  • Ogni volta che pensi di aver bisogno di un Factory, Service Locator o simili. Ciò include se hai bisogno di fabbriche diverse (rare, ma succede).

In altre occasioni, crea semplicemente un nuovo oggetto, in effetti in caso di dubbio, crea un nuovo oggetto - puoi sempre rimuoverlo quando ne vedi il bisogno in seguito: -).

    
risposta data 11.03.2013 - 09:38
fonte
0

Da Wikipedia :

The primary purpose of the dependency injection pattern is to allow selection among multiple implementations of a given dependency interface at runtime, or via configuration files, instead of at compile time. The pattern is particularly useful for providing stub test implementations of complex components when testing, but is often used for locating plugin components, or locating and initializing

Non dovresti aver bisogno di iniettare stringhe, puoi semplicemente passarle come parametri al metodo pertinente. Non dovresti aver bisogno di iniettare dati, appart da config.

I buoni test unitari ti aiutano a localizzare gli errori e quindi dovresti testare il tuo codice indipendentemente dalle altre unità di codice. DI può aiutarti a raggiungere questo obiettivo.

    
risposta data 11.03.2013 - 10:54
fonte
0

In generale, trovo che una classe dovrebbe essere sempre new 'd di un'altra classe.

Questo perché una volta che si procede lungo la strada dell'iniezione di dipendenza, ogni oggetto che usa new deve iniettare tutte le dipendenze degli oggetti che crea, il che significa che l'oggetto genitore deve conoscere anche tutte quelle dipendenze. Se A ha una dipendenza su B e C crea A istanze con new allora C deve automaticamente avere una dipendenza su B , anche se C non usa mai B direttamente . Per prima cosa viola la separazione delle preoccupazioni, a meno che l'unico lavoro di C sia quello di creare A s. Altrimenti crea un problema se vuoi aggiungere una dipendenza a A perché tutte le cose che lo creano ora devono aggiungere la stessa dipendenza. Davvero non dovrebbero preoccuparsi di questo. È meglio avere C dichiarare una dipendenza su AFactory e AFactory avere una dipendenza su B . Quindi puoi aggiungere dipendenze a A tutto ciò che desideri e solo AFactory deve essere modificato.

    
risposta data 12.03.2013 - 12:23
fonte
-1

"A che punto DI si ferma a essere la cosa giusta da fare, e quando inizia a essere un peso? ..."

Prima di tutto mi piace DI e lo uso molto quindi non fraintendermi

DI è ottimo per il lato server, ma i giochi cambiano tutti insieme quando si tratta di programmazione Gui. Ad es. Ho incorporato Guice a un'applicazione GUI esistente sviluppata in Swing

  • Devi rifattorizzare un sacco per sbarazzarti di cose come fabbriche statiche, dipendenze annidate, ecc.
  • Devi essere consapevole di come il contenitore DI crea / gestisce gli oggetti per es. se crea oggetti con entusiasmo all'avvio quindi puoi avere problemi di prestazioni (può essere qualsiasi app, ma in particolare nelle app GUI 15-40 secondi di ritardo). È possibile eseguire il tweek dell'impostazione se il contenitore DI lo consente.
  • Per incorporare DI in un progetto esistente hai bisogno di revolution than evolution

Come gestire le dipendenze annidate?

diciamo che è necessario accedere ad alcune dipendenze nella classe nidificata profondamente , puoi usare DI in uno dei seguenti modi:

  • Modifica costruttore per avere un'iniezione del costruttore (quindi sapere finiamo con il costruttore che prende molti parametri ...)?
  • Usa l'iniezione sul campo (che non è una buona soluzione perché stiamo esponendo i nostri campi)
  • Usa l'iniezione setter (quindi sappi che abbiamo bisogno di creare setter non necessari nel nostro codice)

Che ne dici se vuoi creare un oggetto usando new () (perché l'oggetto deve essere creato in Runtime in base ad alcuni criteri) e vuoi registrarlo nel contenitore (Guice non gestisce gli oggetti creati con new (), che è buono )? Quindi ora è necessario riportare l'attenzione sul contenitore anziché sviluppare nuove funzionalità nell'app.

Parole finali in alcuni casi usando DesignPatterns + pensiero creativo e buona progettazione dell'architettura, puoi evitare i situtations dove Gaine è piccolo e i problemi sono causati dall'introduzione DI

    
risposta data 12.03.2013 - 12:05
fonte

Leggi altre domande sui tag