Ich habe kürzlich über die @ImplementedBy
in 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 @ImplementedBy
Anmerkung:
@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
@ImplementedBy
sorgfä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 @ImplementedBy
lohnt 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@ImplementedBy
Anmerkung, wird diebind()
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?
quelle
Antworten:
Ich denke, die Gefahr besteht hier darin, nur die
@ImplementedBy
Anmerkung zu verwenden. Bei sachgemäßer Verwendung in Verbindung mitbind()
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:
Und dann
NoOpDataService
ist: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,
DataService
mü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.
quelle