Dependency injection



  • @jockelx sagte in Dependency injection:

    @it0101
    Ja, das ist doch klar, aber das ist halt gerne auch mal Mist.

    class Window
    {..}
    
    class Button(Window* parent)...
    
    

    Mein Button darf nicht länger leben, als mein Window.
    Wenn mein Window zerstört wird, dann soll bitte kein Child leben und denken, es könnte noch irgendwas sinnvolles mit dem Window anfangen.
    Das ist falsch programmiert und das will ich dann nicht durch einen smart_ptr vertuschen, indem das Programm nicht knallt, sondern irgendwas unsinniges mit dem nicht mehr existierendem Fenster macht.

    In deinem konstruierten Fall hat du recht.
    Aber in dem Fall, der hier besprochen wird, wo man eine const-Referenz im Konstruktor übergibt, handelt es sich meist um Objekte, die
    a) dem referenzierenden Objekt übergeordnet sind
    oder
    b) gar keine Beziehung zum referenzierenden Objekt haben ( Properties-Klasse z.B. )
    aber eher nicht um eine untergeordnete Beziehung ( Child ).
    Ein Child ( "Button" ) würde man der Klasse vermutlich nicht als Referenz übergeben, sondern dort in der Klasse ("Window") erzeugen und somit die Lebenszeit des Childs ( "Button" ) auf die Lebenzeit der Klasse ("Window") begrenzen. Auch das geht wiederum mit smartpointern, wenn man das will.



  • @it0101

    Aha. '*parent' im Konstruktor ist ein total konstruiertes Beispiel und const-Referenz im Konstruktor sind meist dieses und jenes...;-)

    Ist glaube ich für uns beide nicht mehr sonderlich gewinnbringend, die Diskussion.
    Wichtig ist ja nur, dass man weiß, wann man was zu nehmen hat und ich denke, das wissen wir beide.



  • @jockelx sagte in Dependency injection:

    @it0101

    Aha. '*parent' im Konstruktor ist ein total konstruiertes Beispiel und const-Referenz im Konstruktor sind meist dieses und jenes...;-)

    Ist glaube ich für uns beide nicht mehr sonderlich gewinnbringend, die Diskussion.
    Wichtig ist ja nur, dass man weiß, wann man was zu nehmen hat und ich denke, das wissen wir beide.

    Ich habe ja auch nie gesagt dass die Lösung mit dem klassischen Pointer falsch ist. Das würde ich mir auch nie anmaßen, da mir die theoretische Informatikerausbildung fehlt. Ich komme eher aus der technischen Ecke und daher ist mir eine Lösung so lieb wie die andere 😎



  • @sewing sagte in Dependency injection:

    ist das halten einer Referenz in dieser Form denn als schlechter Stil im Allgemeinen zu vermeiden?

    Kommt auf den Kontext an. Bei Proxy-Klassen ist das durchaus üblich (siehe z.B. Expression Templates oder std::vector<bool>::reference). Diese will man oft auch gerne leichtgewichtig halten, so dass ein std::shared_ptr Overkill wäre.

    std::string_view ist auch noch ein Beispiel wo man sowas macht ohne dass ich es als "schlechten Stil" bezeichnen würde.
    Solche Referenzen sollte man natürlich immer mit Bedacht einsetzen, da man sich damit schnell böse Schellen einfahren kann wenn dem Anwender nicht bewusst ist, dass er selbst dafür verantwortlich ist, dass das referenzierte Objekt länger leben muss als die Instanz, welche die Referenz hält. Leider kann man das auch nur über die Dokumentation kommunizieren - will man es idiotensicher machen, muss man eben mit std::shared_ptr oder einer Kopie arbeiten - oder die Klasse nur in einem Programmkontext verwenden wo die Lebensdauer implizit zugesichert ist (z.B. ein Member, der eine Referenz auf die umschließende Klasseninstanz hält).

    Solche Referenzen oder die Alternative nicht-besitzender Zeiger sind natürlich eine sehr schlanke Lösung, bei er die die Referenz haltenden Instanzen nicht selten komplett wegoptimiert werden. Sie sollten aber keine Standardlösung sein.


Anmelden zum Antworten