Ich habe mehrere empfohlene Verwendung von IoC-Containern im Code gesehen. Die Motivation ist einfach. Nehmen Sie den folgenden in Abhängigkeit injizierten Code:
class UnitUnderTest
{
std::auto_ptr<Dependency> d_;
public:
UnitUnderTest(
std::auto_ptr<Dependency> d = std::auto_ptr<Dependency>(new ConcreteDependency)
) : d_(d)
{
}
};
TEST(UnitUnderTest, Example)
{
std::auto_ptr<Dependency> dep(new MockDependency);
UnitUnderTest uut(dep);
//Test here
}
In:
class UnitUnderTest
{
std::auto_ptr<Dependency> d_;
public:
UnitUnderTest()
{
d_.reset(static_cast<Dependency *>(IocContainer::Get("Dependency")));
}
};
TEST(UnitUnderTest, Example)
{
UnitUnderTest uut;
//Test here
}
//Config for IOC container normally
<Dependency>ConcreteDependency</Dependency>
//Config for IOC container for testing
<Dependency>MockDependency</Dependency>
(Das obige ist natürlich ein hypothetisches C ++ - Beispiel)
Ich stimme zu, dass dies die Schnittstelle der Klasse vereinfacht, indem der Parameter für den Abhängigkeitskonstruktor entfernt wird. Ich denke jedoch, dass die Heilung aus mehreren Gründen schlechter ist als die Krankheit. Erstens, und dies ist für mich sehr wichtig, macht dies Ihr Programm von einer externen Konfigurationsdatei abhängig. Wenn Sie eine einzelne Binärbereitstellung benötigen, können Sie diese Art von Containern einfach nicht verwenden. Das zweite Problem ist, dass die API jetzt schwach und schlechter ist und streng getippt ist. Der Beweis (in diesem hypothetischen Beispiel) ist das Zeichenfolgenargument für den IoC-Container und die Besetzung des Ergebnisses.
Gibt es also noch andere Vorteile bei der Verwendung dieser Art von Behältern oder stimme ich denjenigen, die die Behälter empfehlen, einfach nicht zu?
quelle
Antworten:
Bei einer großen Anwendung mit vielen Schichten und vielen beweglichen Teilen sind die Nachteile im Vergleich zu den Vorteilen eher gering.
Der Container "vereinfacht die Schnittstelle" der Klasse, dies ist jedoch sehr wichtig. Der Container ist eine Lösung für das Problem, das durch die Abhängigkeitsinjektion entsteht. Dabei müssen Abhängigkeiten überall durch Objektdiagramme und über Funktionsbereiche hinweg übertragen werden. Sie haben hier ein kleines Beispiel mit einer Abhängigkeit: Was wäre, wenn dieses Objekt drei Abhängigkeiten hätte und die Objekte, die davon abhängen, mehrere Objekte, die von ihnen abhängen , und so weiter? Ohne Container sind die Objekte an der Spitze dieser Abhängigkeitsketten letztendlich dafür verantwortlich, alle Abhängigkeiten in der gesamten Anwendung zu verfolgen.
Es gibt auch verschiedene Arten von Behältern. Nicht alle von ihnen sind strikt typisiert, und nicht alle erfordern Konfigurationsdateien.
quelle
Der Guice IoC - Framework von Java beruht nicht auf einer Konfigurationsdatei , sondern auf Konfigurationscode . Dies bedeutet, dass sich der Code der Konfiguration nicht von dem Code unterscheidet, aus dem sich Ihre eigentliche Anwendung zusammensetzt, und dass er überarbeitet werden kann usw.
Ich glaube, dass Guice das Java-IoC-Framework ist, das endlich die richtige Konfiguration hat.
quelle
Diese großartige SO-Antwort von Ben Scheirman enthält einige Codebeispiele in C #. Einige Vorteile von IoC-Containern (DI):
quelle