Qual è la motivazione dietro l'annotazione @ImplementedBy in Guice?


10

Di recente ho letto @ImplementedBydell'annotazione disponibile in Google Guice . Consente al programmatore di specificare un'associazione tra un'interfaccia e la sua implementazione per un uso futuro nell'iniezione delle dipendenze. È un esempio di associazione just-in-time .

Sono abbastanza abituato a definire collegamenti espliciti nei miei moduli, usando la sintassi seguente:

bind(SomeInterface.class).to(SomeInterfaceImplementation.class);

Secondo la documentazione, ciò equivale al seguente uso @ImplementedBydell'annotazione:

@ImplementedBy(SomeInterfaceImplementation.class)
public interface SomeInterface {
    //method declarations
}

L'unico guadagno che posso vedere qui è che il codice è leggermente più corto. Allo stesso tempo, questo approccio ha giustamente sottolineato gli stessi documenti:

Usare @ImplementedBycon attenzione; aggiunge una dipendenza in fase di compilazione dall'interfaccia alla sua implementazione.

Tale dipendenza potrebbe non essere un problema in molti casi, ma personalmente lo vedo come un odore di codice.

Quali casi d'uso @ImplementedByvalgono la pena utilizzare l' annotazione?

Un modo possibile sembra essere quello di impiegarlo nel codice di una libreria o di un framework. Come descritto nei documenti, l'annotazione può fornire un'associazione predefinita facilmente sostituibile da una esplicita.

Se un tipo si trova in entrambe le bind()istruzioni (come primo argomento) e ha l' @ImplementedByannotazione, bind()viene utilizzata l' istruzione. L'annotazione suggerisce un'implementazione predefinita che può essere sovrascritta con un'associazione.

In questo modo, come sviluppatore di una libreria, posso fornire ai miei utenti un'associazione pronta per l'uso che può essere personalizzata da qualche parte nel codice client.

È questa l'unica ragione per cui esiste l'annotazione? O c'è qualcosa che mi manca? Posso ottenere qualcosa usandolo nel codice che è solo un'applicazione che si occupa di alcune logiche aziendali e non di una libreria / framework da estendere?


2
Domanda correlata, forse duplicata (anche se il tuo titolo è più chiaro): Guice's @ImplementedBy evil?
Jeff Bowman,

Non un duplicato rigoroso, ma ci sono state discussioni interessanti al riguardo qui: stackoverflow.com/questions/6197178/…
Richard Vodden,

Risposte:


8

Penso che il pericolo qui sia usare solo l' @ImplementedByannotazione. Utilizzato in modo appropriato, insieme alle bind()istruzioni nel modulo e così via, va bene.

Avere un'implementazione predefinita è ottima per i test; non devi necessariamente definire esplicitamente un'iniezione simulata ogni volta che stai testando una classe che ha molte dipendenze o se hai una classe da cui dipendono molte cose (quindi devi definire una derisione ogni volta ).

Ad esempio, potresti avere una classe:

@ImplementedBy(NoOpDataService.class)
interface DataService {
    Map<String, MyPOJO> getData();
}

E poi NoOpDataServiceè:

class NoOpDataService implements DataService {
    @Override
    public Map<String, MyPOJO> getData() {
        return Collections.emptyMap();
    }
}

Ovviamente non lo userete mai nel vostro codice attuale; nel tuo modulo Guice vincolerai un'implementazione che effettivamente fa qualcosa. Ma tutti i test su classi che ottengono un'iniezione DataServicenon devono più avere un legame finto.

tl; dr Sono d'accordo con te sul fatto che far dipendere le tue interfacce dalla tua implementazione possa essere un odore di codice; ma può anche rimuovere il codice del boilerplate per semplificare i test. Non è una funzione difficile da implementare; e anche se esiste un piccolo potenziale di abuso, in definitiva le conseguenze non possono essere troppo gravi (un servizio si avvia di sorpresa) e non sarebbe troppo difficile da risolvere anche se ciò dovesse accadere.


3
Aggiunta del codice di prova alla produzione?
Basilevs,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.