Was ist die Motivation für die Annotation @ImplementedBy in Guice?

10

Ich habe kürzlich über die @ImplementedByin Google Guice verfügbaren Anmerkungen gelesen . Es ermöglicht dem Programmierer, eine Bindung zwischen einer Schnittstelle und ihrer Implementierung für die zukünftige Verwendung bei der Abhängigkeitsinjektion anzugeben. Dies ist ein Beispiel für eine Just-in-Time-Bindung .

Ich bin es gewohnt, explizite Bindungen in meinen Modulen mit der folgenden Syntax zu definieren:

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

Dies entspricht laut Dokumentation der folgenden Verwendung der @ImplementedByAnmerkung:

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

Der einzige Vorteil, den ich hier sehen kann, ist, dass der Code geringfügig kürzer ist. Gleichzeitig hat dieser Ansatz einen Nachteil, auf den in denselben Dokumenten zu Recht hingewiesen wird:

Verwenden Sie @ImplementedBysorgfältig; Es fügt seiner Implementierung eine Abhängigkeit zur Kompilierungszeit von der Schnittstelle hinzu.

Eine solche Abhängigkeit mag in vielen Fällen kein Problem sein, aber ich persönlich sehe sie als Codegeruch.

In welchen Anwendungsfällen @ImplementedBylohnt sich die Verwendung der Anmerkung?

Ein möglicher Weg scheint darin zu bestehen, es im Code einer Bibliothek oder eines Frameworks zu verwenden. Wie in den Dokumenten beschrieben, kann die Anmerkung eine Standardbindung bereitstellen, die leicht durch eine explizite überschrieben werden kann.

Befindet sich ein Typ sowohl in einer bind()Anweisung (als erstes Argument) als auch mit der @ImplementedByAnmerkung, wird die bind()Anweisung verwendet. Die Anmerkung schlägt eine Standardimplementierung vor , die mit einer Bindung überschrieben werden kann.

Auf diese Weise kann ich als Entwickler einer Bibliothek meinen Benutzern eine sofort einsatzbereite Bindung zur Verfügung stellen, die irgendwo im Client-Code angepasst werden kann.

Ist dies der einzige Grund für das Vorhandensein der Anmerkung? Oder fehlt mir etwas? Kann ich etwas gewinnen, indem ich es in Code verwende, der nur eine Anwendung ist, die sich um eine Geschäftslogik kümmert, und keine Bibliothek / ein Framework, das erweitert werden soll?

toniedzwiedz
quelle
2
Verwandte, möglicherweise doppelte Frage (obwohl Ihr Titel klarer ist): Ist Guices @ImplementedBy böse?
Jeff Bowman unterstützt Monica
Kein striktes Duplikat, aber es gab hier einige interessante Diskussionen darüber: stackoverflow.com/questions/6197178/…
Richard Vodden

Antworten:

8

Ich denke, die Gefahr besteht hier darin, nur die @ImplementedByAnmerkung zu verwenden. Bei sachgemäßer Verwendung in Verbindung mit bind()Anweisungen in Ihrem Modul usw. ist dies in Ordnung.

Eine Standardimplementierung eignet sich hervorragend zum Testen. Sie möchten nicht unbedingt jedes Mal explizit eine Scheininjektion definieren müssen, wenn Sie eine Klasse testen, die viele Abhängigkeiten aufweist, oder wenn Sie eine Klasse haben, von der viele Dinge abhängig sind (daher müssen Sie jedes Mal einen Schein definieren ).

Zum Beispiel könnten Sie eine Klasse haben:

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

Und dann NoOpDataServiceist:

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

Sie werden dies natürlich nie in Ihrem eigentlichen Code verwenden. In Ihrem Guice-Modul würden Sie eine Implementierung binden, die tatsächlich etwas bewirkt. Aber alle Tests an Klassen, die injiziert werden, DataServicemüssen keine Scheinbindung mehr haben.

Ich stimme Ihnen zu, dass es ein Codegeruch sein kann, wenn Ihre Schnittstellen von Ihrer Implementierung abhängen. Es kann aber auch den Boilerplate-Code entfernen, um das Testen zu vereinfachen. Es ist nicht schwierig, eine Funktion zu implementieren. und obwohl es ein geringes Missbrauchspotenzial gibt, können die Konsequenzen letztendlich nicht allzu schlimm sein (ein Dienst wird überraschend gestartet), und es wäre nicht allzu schwer zu beheben, selbst wenn dies tatsächlich geschieht.

durron597
quelle
3
Testcode zur Produktion hinzufügen?
Basilevs