static class



  • slux schrieb:

    also ich will ... global über A::m_A drauf zugreifen können. die instanz wurde erstellt, aber wenn ich von außen drauf zugreife, dann ist der pointer NULL

    Zeig ein vollständiges, kompilierbares Beispiel.



  • cooky451 schrieb:

    dot schrieb:

    Singleton ist der Antipattern schlechthin...

    👎 Zugegeben, es gibt viele "falsche" Anwendungen dafür, heißt nicht, dass es nie sinnvoll ist.

    👍 Danke, ich hab' schon Angst bekommen.

    Allerdings sind bei mir Singletons auch einfach nur statische Membervariablen:

    class A
    {
    public:
    
        static A Singleton;
    
        A(A const&) = delete; // C++11, sonst einfach private machen.
        A& operator=(A const&) = delete;
    
    private:
    
        A():
        myVar(3)
        {
            //...
        }
    
        int myVar;
    };
    
    A A::Singleton;
    


  • cooky451 schrieb:

    👎 Zugegeben, es gibt viele "falsche" Anwendungen dafür, heißt nicht, dass es nie sinnvoll ist.

    Hast du schon mal ein sinnvolles Singleton gebaut?

    Edit: Das obligatorische Zitat von Gamma: http://www.informit.com/articles/article.aspx?p=1404056

    Erich Gamma schrieb:

    When discussing which patterns to drop, we found that we still love them all. (Not really—I'm in favor of dropping Singleton. Its use is almost always a design smell.)



  • Also ich benutze häufig Singletons.

    Die Appliaktion welche ich schreibe sind allerdings Maschinensteuerungen.

    Das gibt es genau einen Handler (Stückzuführung), einen Laser, ein Mess-System usw.

    Das sind alles eindeutig Singletons! Es gibt keinen Grund diese nicht auch so zu programmieren.



  • weicher schrieb:

    Das sind alles eindeutig Singletons!

    Warum? Nur weil du nur eine Instanz brauchst? Was hat es die Klasse zu kümmern, wie viele Instanzen der benutzende Code erstellt? Welche technische Notwendigkeit (in der Klasse selbst, nicht in deinem Use Case) gibt es, dass es nur einen Laser gibt? Welches Problem hast du mit dem Singleton gelöst?



  • Ich sehe nicht, was an einem Eventhandler, Laser oder Mess-System inheränt ein Singleton sein soll. Es ist durchaus möglich, mehrere davon zu haben, und wenn dieser use case auf dich zukommt, musst du einen Haufen Code umschreiben, ohne dass dies bei vernünftiger Entwicklung notwendig geworden wäre.

    Ferner hat ein Singleton alle Nachteile, die globale Variablen auch mit sich bringen. Nicht nur schränkst du deine Klasse sinnlos ein, auch der Code, der das Singleton verwendet, ist auf dieses Szenario festgelegt und nicht mehr zu gebrauchen, wenn sich die Umstände mal ändern.

    Der einzige mir bekannte Anwendungsfall, in dem ein Singleton vertretbar (nicht notwendig!) ist, ist Logging, und dann auch nur hinter einer Makro-Schale, damit man das Backend einigermaßen einfach austauschen kann, wenn es mal notwendig werden sollte. Das das Singleton als "Design-Pattern" verbreitet wird, ist eigentlich ein Unding.



  • Ich sehe nicht, was an einem Eventhandler

    Nicht Eventhandler!! sondern nur Handler entspricht Kreuztisch, Bandvorschub, Roboter usw. usf.

    Der einzige mir bekannte Anwendungsfall, in dem ein Singleton vertretbar (nicht notwendig!) ist, ist Logging, und dann auch nur hinter einer Makro-Schale, damit man das Backend einigermaßen einfach austauschen kann, wenn es mal notwendig werden sollte.

    Genau deswegen das Singleton, bei unseren Maschinen ist immer genau ein Mess-System vorhanden. Aber nicht auf allen Maschinen das gleiche. Wenn aus irgend einem Grund auf einer Maschine das Messystem ausgetauscht wird, muss ich nur die entsprechende DLL in das Applikationsverzeichnis kopieren und das wars. Natürlich kann man das auch ohne Singleton lösen, aber warum wenn es in
    der Realität doch eines ist?

    Genau die gleiche Situation bei den Handlern. Es gibt verschiedene Bandvorschübe für die verschiedenen SMD Tapes und für unsere Montagebänder.

    Da unsere ganze Firma auf die Quarzproduktion ausgerichtet ist sind die Variationsmöglichkeiten ziemlich eingeschränkt.

    Egal welches Mess-System es interessieren nur FS, FL, RS, C1 und C0

    Egal welcher Handler es wird immer genau ein Quarz bearbeitet mehr geht nicht weil die Dinger sich gegenseitig beeinflussen.

    Das Singleton ist einfach. Es erfüllt seinen Zweck, es entspricht der Realität.

    Herzliche Grüsse
    Walter



  • weicher schrieb:

    Das sind alles eindeutig Singletons!

    Warum? Nur weil du nur eine Instanz brauchst? Was hat es die Klasse zu kümmern, wie viele Instanzen der benutzende Code erstellt? Welche technische Notwendigkeit (in der Klasse selbst, nicht in deinem Use Case) gibt es, dass es nur einen Laser gibt? Welches Problem hast du mit dem Singleton gelöst?

    Nenne doch bitte einen Vorteil, den du durch das Singleton bekommen hast. Stell dir deinen Code ohne Singletons vor und sag uns, was dann komplizierter wäre.

    Edit: Singleton kommt mir immer vor wie eine Lösung für ein Problem, das gar nicht vorhanden war. Wenn ich nur eine Instanz haben möchte, erstelle ich nur eine Instanz. Ich verbiete doch nicht alles, was ich nicht benutze.



  • Hallo Michael,

    Welches Problem hast du mit dem Singleton gelöst?

    Die Varianten für die einzelnen Handler, Mess-Systeme usw. sind in DLL's ausgelagert. Warum DLL's, in Lib's kann man keine Resourcen wie zB. Dialoge einbetten.

    Mit unserem Plug-In System können wir die DLL's aus unseren Applikationen ansprechen. Vor dem Umbau auf Singletons (vor etwa 15 Jahren) hatten wir immer wieder das Problem, dass mehrere Komponenten von verschiedenen Programmierern jeweils zB. eine Mess-System Instanz erzeugt haben. Jede dieser Instanzen hat dann das reale Mess-System jeweils mit seinen Kommandos angesprochen... Das Durcheinander und die Zermürbende Fehlersuche kannst Du dir eventuell vorstellen.

    Seit der Umstellung auf Singletons mit 2 Zeilen Code, sind diese Probleme Geschichte.

    Herzliche Grüsse
    Walter



  • Ist das dein Ernst? Normalerweise läuft euer System mit 0 Messsystemen (denn keiner hat eine Instanz erstellt, verwechsle nicht Klasse mit Objekt). Dann will jemand etwas von eurem physisch vorhandenen Messsystem und erstellt sich kurzerhand ein eigenes Messsystem? Das ist, als ob ich erwarten würde, dass das hier funktioniert:

    vector<int> foo;
    foo.push_back(1);
    foo.push_back(2);
    
    int getSize()
    {
        vector<int> bar;
        return bar.size();    // soll 2 zurückgeben
    }
    

    Übergib das Messsystem als Parameter oder noch besser, falls es möglich ist, nur die Werte, die das Messsystem geliefert hat (was interessiert es den Empfänger, woher die Werte kommen, wenn er nur mit diesen rechnen soll?). Aber wenn du doch selbst sagst, dass es nur ein Messsystem in deinem Use Case gibt, warum werden dann mehrere erstellt?



  • Hallo Michael,

    Aber wenn du doch selbst sagst, dass es nur ein Messsystem in deinem Use Case gibt, warum werden dann mehrere erstellt?

    Ich bin ja nicht der einzige welcher an unseren Applikationen oder der Bibliothek rumprogrammiert, ich muss es nur ausbaden wenn etwas nicht funktioniert 😉

    while (true)
    {
    Programmierer: "Wenn ich meine Komponente testen will,
    dann muss ich doch eine Instanz vom Mess-System erzeugen"
    Ich: "Erzeuge doch das Mess-System in der Testumgebung
    und übergebe den Pointer an Deine Komponente"
    Programmierer: "Ok, dann mach ich's halt so (müffel müffel)"
    2 Wochen später, nach erneuter Fehlersuche
    }

    Seitdem die Schnittstelle klar und es schlicht nicht mehr möglich ist mehrere Instanzen zu erzeugen funktioniert es auch.

    Herzliche Grüsse
    Walter



  • Michael E. schrieb:

    Hast du schon mal ein sinnvolles Singleton gebaut?

    Sicher. Nehmen wir z.B. mal WSAStartup() und WSACleanup(). Das eine muss ich vor dem Erstellen des ersten Sockets ausführen, das andere am Ende des Programms. Für sowas baue ich halt ein kleines unsichtbares Singleton. Ich könnte natürlich auch eine normale Klasse nehmen und ne globale Variable davon anlegen, aber es ist ja nun mal klar ersichtlich und erforderlich, dass nur genau eine Instanz dieser Klasse existiert. Aber wenn du eine schöne Alternative kennst, immer her damit.



  • statische Konstruktoren und Destruktoren :p



  • Kellerautomat schrieb:

    statische Konstruktoren und Destruktoren :p

    Ja ja, nur bitte nicht so wie du sie vor hast. 🤡



  • cooky451 schrieb:

    Michael E. schrieb:

    Hast du schon mal ein sinnvolles Singleton gebaut?

    Sicher. Nehmen wir z.B. mal WSAStartup() und WSACleanup(). Das eine muss ich vor dem Erstellen des ersten Sockets ausführen, das andere am Ende des Programms. Für sowas baue ich halt ein kleines unsichtbares Singleton. Ich könnte natürlich auch eine normale Klasse nehmen und ne globale Variable davon anlegen, aber es ist ja nun mal klar ersichtlich und erforderlich, dass nur genau eine Instanz dieser Klasse existiert. Aber wenn du eine schöne Alternative kennst, immer her damit.

    Jedes Socket kann das für sich machen, WSAStartup() und WSACleanup() zählen mit.



  • TyRoXx schrieb:

    cooky451 schrieb:

    Michael E. schrieb:

    Hast du schon mal ein sinnvolles Singleton gebaut?

    Sicher. Nehmen wir z.B. mal WSAStartup() und WSACleanup(). Das eine muss ich vor dem Erstellen des ersten Sockets ausführen, das andere am Ende des Programms. Für sowas baue ich halt ein kleines unsichtbares Singleton. Ich könnte natürlich auch eine normale Klasse nehmen und ne globale Variable davon anlegen, aber es ist ja nun mal klar ersichtlich und erforderlich, dass nur genau eine Instanz dieser Klasse existiert. Aber wenn du eine schöne Alternative kennst, immer her damit.

    Jedes Socket kann das für sich machen, WSAStartup() und WSACleanup() zählen mit.

    Nope.

    Nur weil aktuell kein Socket offen ist, will ich ja nicht zwangsläufig WSACleanup aufrufen. Etwas Singleton-artiges ist hier schon korrekt.



  • weicher schrieb:

    Seitdem die Schnittstelle klar und es schlicht nicht mehr möglich ist mehrere Instanzen zu erzeugen funktioniert es auch.

    Aber du bist doch derjenige, der den fremden Code aufruft oder nicht? Wenn du beim Aufruf eine Messsysteminstanz übergibst, muss der aufgerufene Code auch die Messsysteminstanz annehmen. Verwirft er die dann oder was? Wenn ich eine Messsysteminstanz übergeben bekomme, komme ich doch nicht auf die Idee und erstelle mir eine eigene Instanz.



  • cooky451 schrieb:

    Nehmen wir z.B. mal WSAStartup() und WSACleanup(). Das eine muss ich vor dem Erstellen des ersten Sockets ausführen, das andere am Ende des Programms. Für sowas baue ich halt ein kleines unsichtbares Singleton. Ich könnte natürlich auch eine normale Klasse nehmen und ne globale Variable davon anlegen, aber es ist ja nun mal klar ersichtlich und erforderlich, dass nur genau eine Instanz dieser Klasse existiert. Aber wenn du eine schöne Alternative kennst, immer her damit.

    Ich hab noch nie mit Sockets gearbeitet, weshalb ich nachfragen muss: Was spricht dagegen, WSAStartup beim Starten des Programms aufzurufen? Sprich WSAStartup als Erstes und WSACleanup als Letztes in der main.



  • Hallo Michael,

    Aber du bist doch derjenige, der den fremden Code aufruft oder nicht?

    Lies meinen letzen Post noch einmal sorgfältig durch.

    Normalerweise macht man in Komponenten in etwa folgendes:

    MeasSystem* measure = Object<MeasSystem> (_T("MeasSystem"));
      assert (measure != NULL);
      if (measure->GoOnline ())
      {
        ...
      }
    

    Da beim testen einer Komponente noch kein MessSystem existiert schlägt der
    assert (measure != NULL) zu.

    Was macht also der bequeme Programmierer (gibt's auch andere? 😉 )

    MeasSystem* measure = CreateObject<MeasSystem> ();
      assert (measure != NULL);
      if (measure->GoOnline ())
      {
        ...
      }
    

    Dann läuft sein Test...

    Herzliche Grüsse
    Walter



  • Michael E. schrieb:

    cooky451 schrieb:

    Nehmen wir z.B. mal WSAStartup() und WSACleanup(). Das eine muss ich vor dem Erstellen des ersten Sockets ausführen, das andere am Ende des Programms. Für sowas baue ich halt ein kleines unsichtbares Singleton. Ich könnte natürlich auch eine normale Klasse nehmen und ne globale Variable davon anlegen, aber es ist ja nun mal klar ersichtlich und erforderlich, dass nur genau eine Instanz dieser Klasse existiert. Aber wenn du eine schöne Alternative kennst, immer her damit.

    Ich hab noch nie mit Sockets gearbeitet, weshalb ich nachfragen muss: Was spricht dagegen, WSAStartup beim Starten des Programms aufzurufen? Sprich WSAStartup als Erstes und WSACleanup als Letztes in der main.

    Prinzipiell nichts. Bis auf dass es bei portablen Libraries halt unpraktisch ist.
    Wenn es aber eine reine Win32 Anwendung ist, spricht nichts dagegen. Es sei denn natürlich man erstellt einen Socket vor main()...


Anmelden zum Antworten