C++ DIP (Dependency Inversion Principle) ?
-
Hallo!
Ich weiß soweit was ein Interface ist, wozu man ein Interface braucht. Aber das Dependency Inversion Principle , im bezug auf Interfaces, habe ich irgendwie nicht ganz verstanden.
Zu frage: "Was genau sagt das DPI aus im bezug auf Interfaces?"
Schonmal vielen dank im voraus !
-
Du meinst Dependency Injection bzw. Inversion of Control?!
Und dabei werden üblicherweise Interfaces (d.h. in C++ abstrakte Klassen) als Parameter verwendet, um zum einen die Erzeugung außerhalb der Klasse bzw. Funktion zu halten als auch die Möglichkeit zu bieten, verschiedene Implementierungen zu benutzen (bes. sinnvoll im Zusammenhang mit Unit-Tests die Verwendung von Mock-Objekten).
-
Dependency Injection wird aber mit DI abgekürzt...
-
@NoIDE sagte in C++ DIP (Dependency Inversion Principle) ?:
Dependency Injection wird aber mit DI abgekürzt...
Und wie hilft deine Antwort uns weiter?
Ich hab mal eine ganz kurze suche gemacht.
DI ist, soweit ich das verstanden habe, eine Möglichkeit DIP umzusetzen.
(Wenn man Wikipedia in der Hinsicht vertrauen kann.)Denn "Dependency Inversion Principle", wie der Name schon sagt, beschreibt nur ein Prinzip und keine konkrete Umsetzung des Prinzips.
https://en.wikipedia.org/wiki/Dependency_inversion_principle#Related_patterns
Various patterns such as Plugin, Service Locator,[3] or Dependency injection[4][5] are employed to facilitate the run-time provisioning of the chosen low-level component implementation to the high-level component.
https://en.wikipedia.org/wiki/Dependency_Injection
Dependency injection is often used to keep code in-line with the dependency inversion principle.
-
Dieser Beitrag wurde gelöscht!
-
Oh, dann habe ich mich auch ein bißchen vertan - ich hatte nicht an das 5. Prinzip von SOLID gedacht: Dependency Inversion Prinzip.
-
@Sebi1412
Vielleicht hilft ein Beispiel.Die "naive" Variante ohne DIP:
class FooTransport final { public: explicit FooTransport(std::string_view serverAddress); void send(ComposedMessage const& message); // ... }; class Messenger final { public: Messenger() : m_transport(readConfigFile().getEntry("ServerAddress")) { } // ... private: void doSend(ComposedMessage const& message) { m_transport.send(message); } FooTransport m_transport; }; int main() { Messenger m; m.run(); }
Hier ist
Messenger
direkt von der konkreten Transport-KlasseFooTransport
abhängig.Mit DIP:
class AbstractTransport { public: virtual ~AbstractTransport() = default; virtual void send(ComposedMessage const& message) = 0; // ... }; class FooTransport final : public AbstractTransport { public: explicit FooTransport(std::string_view serverAddress); void send(ComposedMessage const& message) override; // ... }; class Messenger final { public: Messenger(std::unique_ptr<AbstractTransport> transport) : m_transport(std::move(transport)) { } // ... private: void doSend(ComposedMessage const& message) { m_transport->send(message); } std::unique_ptr<AbstractTransport> const m_transport; }; int main() { auto const serverAddress = readConfigFile().getEntry("ServerAddress"); Messenger m{std::make_unique<FooTransport>(serverAddress)}; m.run(); }
Hier ist
Messenger
nicht mehr vonFooTransport
abhängig. Dafür sind beide von der abstrakten Interface-KlasseAbstractTransport
abhängig.FooTransport
weil es das vonAbstractTransport
vorgeschriebene Verhalten umsetzen muss, undMessenger
weil es einAbstractTransport
Objekt benötigt und sich auf das vonAbstractTransport
vorgeschriebene Verhalten verlässt.
Und das wird als "Dependency Inversion" bezeichnet.Den Umstand dass das "Transport" Objekt von aussen an das
Messenger
Objekt übergeben wird nennt man "Dependency Injection". Und wenn man es so wie hier an den Konstruktor übergibt, dann nennt man es auch "Constructor Injection".
-
@Th69 sagte in C++ DIP (Dependency Inversion Principle) ?:
Oh, dann habe ich mich auch ein bißchen vertan - ich hatte nicht an das 5. Prinzip von SOLID gedacht: Dependency Inversion Prinzip.
Ach, auf einmal ist mein Einwand berechtigt gewesen? Nach @firefly war dieser doch total nutzlos?
-
Habe es leider erst jetzt gelesen, aber nochmal vielen herzlichen dank an alle Kommentare die haben mir aufjedenfall weitergeholfen mit dem Thema SOLID bzw. DIP wärmer zu werden und es zu verstehen was DIP ist und wieso DIP sinnvoll ist vor allem in der OOP.
-
@Sebi1412
p.s.: Dependency Injection muss natürlich nicht mit einer abstrakten Basisklasse kombiniert werden. Man könnte in dem Beispiel von oben auch direkt eineFooTransport
übergeben. Das kann auch manchmal Sinn machen - wobei mir jetzt aus dem Stegreif kein Beispiel einfällt.Am flexibelsten ist es allerding mit der abstrakten Basisklasse. Auch wenn man es im eigentlichen Programm nicht braucht, ist es in Tests oft sehr praktisch. z.B. kann man so die
Messenger
Klasse testen, ohne dass man einen echten Server braucht mit dem man dieMessenger
Objekte kommunizieren lassen kann. Statt dessen macht man für den Test eine spezielleTestTransport
Klasse, die ebenfalls vonAbstractTransport
abgeleitet ist, und bloss so tut als ob sie mit einem Server kommunizieren würde.