Datenbankzugriffsschicht ohne mit Singletons um sich zu schmeißen?



  • Zeus schrieb:

    CStoll schrieb:

    PS: Ich will hier nicht die Vorteile der DI verteidigen, dazu kenne ich das Konzept zu wenig.

    Doch kennst du, ich versteh blos nicht, dass es unter eigenen Begiff gehypt wird 😉

    Gehypt wird glaub ich mehr DI mit Frameworks und entsprechenden Konfigurationsmöglichkeiten und nicht die simple Konstruktor-Injection die dot hier so hypt.



  • Gibt es hier eigentlich irgendjemand, außer dot, der Logger und DB manuell per Konstruktor-Injection weiter gibt, oder verwendet ihr alle DI Frameworks dazu?



  • In den C#/ASPX Projekten (habe ich Anfang des Jahres von einem Ex-Kollegen geerbt) habe ich Framework-basierte DI (d.h. durch Austausch/Bearbeiten einer XML-Datei kann ich die verwendeten Klassen austuaschen und Parameter setzen).
    In den SAL-Projekten, die die überwiegende Mehrheit bei uns ausmachen, läuft es wohl auf eine Art Header-basierte DI hinaus (auch wenn es dort keine Trennung zwischen Header und Implementationsdatei gibt).
    C++ habe ich seit einer Weile nicht mehr produktiv und im größeren Stil verwendet.

    (Randfrage: Der Umgang der STL mit Allokatoren und Traits-Klassen dürfte doch auch in den Bereich DI fallen, oder?)



  • Ich verstehe gar nicht, wieso hier um createInstance gestritten wird, kann man nicht auch so die if-Abfrage sparen und Threadsicherheit erzeugen:

    class TestSingleton
    {
    private:
    	static TestSingleton st;
    
    	int z;
    
    	TestSingleton() {z = 100;}
    	TestSingleton(const TestSingleton&);
    
    public:
    	static TestSingleton& getInstance()
    	{
    		return st;
    	}
    
    	int getZ() const {return z;}
    };
    
    TestSingleton TestSingleton::st ;
    

    Das kompiliert bei mir problemlos. Nachteil ist, dass es immer instanziiert wird und nicht bei Verwendung. Aber je nach Anwendungszweck finde ich das nicht so dramatisch.



  • Eisflamme schrieb:

    Ich verstehe gar nicht, wieso hier um createInstance gestritten wird, kann man nicht auch so die if-Abfrage sparen und Threadsicherheit erzeugen:

    Thread-Sicherheit: Ja, das Problem bei diesem Ansatz ist die Initialisieurngs-Reihenfolge von globalen Objekten.



  • Hm, verstehe... Und so was?

    class TestSingleton
    {
    private:
    	static TestSingleton st;
    
    	int z;
    
    	TestSingleton() {z = 100; std::cout << "Singleton initialized.";}
    	TestSingleton(const TestSingleton&);
    
    	friend TestSingleton& getSingletonInstance();
    
    public:
    	int getZ() const {return z;}	
    };
    
    TestSingleton& getSingletonInstance()
    {
    	static TestSingleton ts;
    	return ts;
    }
    

    Hm und die Übergabe von Traits und Allokatoren passt für DI imo nicht ganz, weil man nur Klassen, aber keine Objekte übergibt. Großer Vorteil der DI ist aber, dass man die Initialisierung dem Aufrufer überlässt. Man löst dadurch eher die dynamische Polymorphie ab, finde ich.



  • Eisflamme schrieb:

    Hm, verstehe... Und so was?

    Das hat auch wieder ein verstecktes if (in der Umsetzung der static-Variablen) 😉
    Aber wir müssen jetzt nicht alle Variationen eines Singleton durchgehen, dafür gibt es schon genug Fachlitertur, die sich mit den Vor- und Nachteilen der einzelnen Varianten beschäftigen. Ich bin bis jetzt zumindest davon ausgegangen, daß es hier um Möglichkeiten zur kompletten Vermeidung von Singletons geht.

    Hm und die Übergabe von Traits und Allokatoren passt für DI imo nicht ganz, weil man nur Klassen, aber keine Objekte übergibt. Großer Vorteil der DI ist aber, dass man die Initialisierung dem Aufrufer überlässt. Man löst dadurch eher die dynamische Polymorphie ab, finde ich.

    Wenn du es auf die Spitze treiben willst, kannst du auch parametrisierte Allokatoren schreiben und als Konstruktor-Parameter an die STL-Container übergeben 😉
    Aber meine Randfrage sollte hauptsächlich ausloten, wo die Experten (dot/Zeus/...) anfangen, von DI zu sprechen.



  • CStoll schrieb:

    Ich bin bis jetzt zumindest davon ausgegangen, daß es hier um Möglichkeiten zur kompletten Vermeidung von Singletons geht.

    Ja ich auch...

    CStoll schrieb:

    Aber meine Randfrage sollte hauptsächlich ausloten, wo die Experten (dot/Zeus/...) anfangen, von DI zu sprechen.

    ich bin ganz sicher kein Experte was das Thema angeht. Abgesehen davon hast du recht, die Idee hinter den STL Allokatoren ist sicher sowas ähnliches wie DI. Nur passiert das dort auf Typebene und nicht auf Objektebene, ka inwiefern man da noch von DI sprechen würde.



  • dot schrieb:

    ich bin ganz sicher kein Experte was das Thema angeht. Abgesehen davon hast du recht, die Idee hinter den STL Allokatoren ist sicher sowas ähnliches wie DI. Nur passiert das dort auf Typebene und nicht auf Objektebene,

    Nee, genau genommen passiert es auf Objektebene. Nicht nur Alloaktoren, auch zum Beispiel der Vergleicher in std::sort.
    Das Objekt ist allerdings in der Praxis meistens leer, da muß ich Dir Recht geben, und nur sein Typ wird verwendet. Muß aber nicht sein. Objekte, die zum Beispiel zur Laufzeit erst wissen, nach welchem Attribut sortiert werden soll, habe ich schon gesehen. Da ist aber dann auch vom Typ her klar, daß es ein Vergleicher ist, denn er hat den passenden operator<. Oder Allokatoren, die Objekteigenen Speicher haben, das geht ein wenig in Richtung memory pools.
    Wir machen von den Objekten die Typen aber nie ganz weg. Wir benutzen keine Basisklasse Object für alles und kein

    struct IComparer{
       virtual bool less(Object const& a,Object const& b);
       friend bool operator<(...//nur nötig, weil std::-Zeugs so pingelig ist
    

    , obwohl das ginge.



  • Versteh ich nicht. Man übergibt doch nur den Typen. Und wenn der genutzt werden soll, wird der lokal instanziiert.



  • Eisflamme schrieb:

    Man übergibt doch nur den Typen.

    Nicht wirklich.
    http://www.cplusplus.com/reference/stl/map/map/



  • Stimmt, hab vergessen dass man den Allocator/Comparator ja tatsächlich als Instanz übergibt, hab mir für einen Moment eingebildet die wären mehr nur ne Art Policy. Aber so kann man imo natürlich von einer Art Dependency-Injection reden, ist ja einfach nur statischer statt dynamischer Polymorphismus...



  • Oh, ich Fisch, dann passt DI.


Anmelden zum Antworten