2012-12-19 9 views
5

Forse mi sono perso nella documentazione, ma mi chiedo come dovrei gestire gli "oggetti helper"?Devo iniettare gli oggetti necessari per l'esecuzione di un algoritmo? Devo iniettare tutto?

codice di esempio:

public Path dijkstra(Node startNode, Node endNode) { 
    Set<Node> nodesToInspect = new HashSet<Node>(); // should this Object be injected? 
    Path path = new Path(); // and this one? 

    while (!nodesToInspect.isEmpty()) { 
     // some logic like: 
     path.add(currentNode); 

    } 

    return path; 
} 

dovrei iniettare tutto o dovrei dire a un certo punto che l'algoritmo "conosce" meglio che cosa ha bisogno? Dovrei provare ad eliminare ogni "nuovo"? o sono alcune creazioni di oggetti bene, per le classi ad esempio API come HashSet, ArrayList, ecc

+0

http://stackoverflow.com/questions/1005473/must-dependency-injection-come-at-the-expense- di incapsulamento – sdasdadas

risposta

2

Prima di sostituire una semplice new con l'iniezione di dipendenza, è necessario porsi "perché sto facendo questo?" ... "quale vantaggio reale ha?". Se la risposta è "Non so" o "niente", allora non dovresti.

In questo caso, non vedo alcun vantaggio reale nell'utilizzo di DI nei primi casi nel codice di esempio. Non c'è bisogno di nulla al di fuori di quel metodo per sapere come viene rappresentato l'insieme interno ... o anche per sapere che esiste.

L'altra domanda da porsi è se esiste un modo più semplice e più ovvio per raggiungere l'obiettivo. Ad esempio, lo scopo (più probabile) dell'utilizzo di DI per la variabile path consiste nel consentire all'applicazione di utilizzare una classe diversa Path. Ma il modo più semplice per farlo è passare un'istanza Path al metodo dijkstra come parametro esplicito. Potresti anche usare l'overloading per renderlo più appetibile; per esempio.

public Path dijkstra(Node startNode, Node endNode) { 
    return dijkstra(startNode, endNode, new Path()); 
} 

public Path dijkstra(Node startNode, Node endNode, Path path) { 
    ... 
} 

L'ultima cosa da considerare è che Di (in Java) comporta una riflessione a un certo livello, ed è inevitabilmente più costoso rispetto agli approcci classici di utilizzare new o di fabbrica oggetti/metodi. Se non hai bisogno della flessibilità extra di DI, non dovresti pagare per questo.


Ho appena notato che le due variabili a cui si fa riferimento sono variabili locali. Non sono a conoscenza di alcun framework DI che consente di iniettare variabili locali ...

+0

Google Guice mi consentirebbe di passare qualche oggetto Provider alla mia classe, con cui potrei generare il Se facilmente. Ancora non sono sicuro se questo è un buon modo. –

+0

@ Assurdo-mente: il passaggio di un provider non è un classico DI (un 'Provider' è effettivamente un oggetto factory). E inoltre, è necessario chiedersi cosa (di valore) stai effettivamente raggiungendo. –

1

Ricordare il principio di progettazione: "incapsulare ciò che cambia spesso" o "incapsulare ciò che varia". Come ingegnere, sai meglio cosa è probabile che cambi. Non vorresti codificare l'anno 2012 in codice che vivrà fino al prossimo decennio, ma non vorresti nemmeno impostare "Math.PI" come impostazione di configurazione - che sarebbe un overhead e una configurazione extra non avresti mai bisogno di toccare.

Tale principio non cambia con l'iniezione dipendenza.

Stai scrivendo un algoritmo e sai quale implementazione di Set ti serve, come nell'esempio Dijkstra? Crea il tuo oggetto tu stesso. Ma cosa succederebbe se il tuo collaboratore offrisse presto una nuova fantastica implementazione di Set ottimizzata per il tuo caso d'uso, o cosa succederebbe se tu stia sperimentando diverse implementazioni di raccolta per il benchmarking? Forse vorrete iniettare un fornitore fino a quando la polvere non si depositerà. Questo è meno probabile per le raccolte, ma forse è più probabile per oggetti usa e getta simili che potreste pensare come "oggetti helper".

Supponiamo che stiate scegliendo tra diversi tipi di CreditCardAuthService che possono variare in fase di esecuzione. Ottimo caso per iniezione. Ma cosa succede se hai firmato un contratto quinquennale e sai che il tuo codice verrà sostituito molto tempo prima? Forse l'hard-coding per un servizio ha più senso. Ma poi devi scrivere alcuni test unitari o test di integrazione e davvero non vuoi usare un vero back-end con carta di credito. Torna all'iniezione di dipendenza.

Ricorda: il codice è malleabile. Un giorno potresti decidere di estrarre il tuo hard-coded HashSet e sostituirlo con qualcos'altro, il che va bene. O forse scoprirai che hai bisogno del tuo servizio per variare abbastanza spesso da dover essere controllato da Guice, e quindi aggiungere un parametro costruttore e un'associazione e chiamarlo un giorno. Non ti preoccupare troppo. Tieni presente che solo perché hai un martello, non tutti i problemi sono un Provider<WoodFasteningService>.

0

Quando si lavora con DI, preferisco evitare "nuovo" quando possibile. Ogni istanza creata al di fuori del contenitore (ad esempio l'iniettore di guizzi) non può essere sottoposta a refactoring per l'uso (cosa succederebbe se l'istanza "Path" dovesse ottenere una "radice" di stringhe iniettata dalla configurazione ... e non è possibile utilizzare gli intercettori anche su tali oggetti. Quindi, a meno che non sia un Entity-Pojo puro, utilizzo sempre/Inject continuamente Fa parte dell'inversione del pattern di controllo (hollywood) e della testabilità ... cosa succede se si deve prendere in giro Path o Set in Junit? se li hai iniettati (in questo caso i Provider), puoi facilmente cambiare l'implementazione concreta in seguito.

+0

buon punto, ma questo approccio causa "inquinamento costruttore". Già in questo semplice caso il mio costruttore avrebbe bisogno di due Provider e non ho nemmeno postato l'algoritmo completo o le dipendenze di altre classi. Inoltre, come dovrebbe un utente determinare quale Set è il migliore/migliore per un algoritmo? –

+0

Se si utilizza il constructor injection, anche l'istanza verrà creata da guice, quindi l'Utente non decide quale implementazione utilizzare. Ma in Casi come questo, preferisco comunque l'iniezione sul campo. –

+0

L'iniezione sul campo mi obbliga a utilizzare l'iniezione di dipendenza durante il test, che non desidero e/o non posso utilizzare. Sì, l'istanza viene creata dal provider, ma l'utente deve ancora scegliere (o ha la possibilità di cambiare) il fornitore corretto/migliore. –

Problemi correlati