Von UML zu C++ (Analysemuster "Wechselnde Rollen")



  • Ich versuche das UML Analysemuster "Wechselnde Rollen" in C++ zu übertragen, nur um zu verstehen wie allgemein UML zu Code umgesetzt werden.

    Folgendes ist das Analysemuster "Wechselnde Rollen":

                                                     <------------------ [Gast]
    [Besucher] 1 ------------- * [Besucherrollen] 
                                                     <------------------ [Künstler]
    

    Ich fasse kurz das Muster zusammen. Zwischen den Klassen Besucher und Besucherrollen ist eine bidirektionale Assoziation von 1 zu beliebig vorhanden.

    Besucherrollen selbst ist eine abstrakte Basisklasse der Klassen Gast und Künstler. Eine "wechselnde Rolle" erhält man, wenn ein Künstler als Besucher eine Veranstaltung besucht. Ist er Mitwirkender, kann er kein Gast sein. Ein Theaterstück an dem er nicht Schauspielt, kann er dennoch als Gast ansehen. Er kann also die Rolle des Gastes oder des Künstlers einnehmen, aber in diesen Zusammenhang nicht zur gleichen Zeit. Er ist also entweder Gast oder Künstler.

    Nun habe ich versucht dieses Modell in C++ Code umzusetzen.

    #include <iostream>
    #include <string>
    #include <vector>
    
    // ********************************** KLASSEN **********************************
    class Besucherrolle;
    class Besucher
    {
      public:
        std::string name;
        bool eintrittserlaubnis;
        // Vektor von der Basisklasse erstellt, damit darin Objekte der Kindklassen
        // liegen können. (Als Pointer angelegt)
        std::vector<Besucherrolle*> grundBesuch; // Hier die Kardinalität: beliebig
    
        Besucher();
        Besucher(Besucherrolle&);
    };
    
    // Basisklasse (Abstrakt)
    class Besucherrolle
    {
      public:
        std::string besucherRolle;
        virtual void definiertBesucher()=0;
    
      protected:
        Besucher* besucher; // Hier Kardinalität 1
    };
    
    
    // Hier die Vererbung
    class Gast : public Besucherrolle
    {
      public:
        bool hatTicketGekauft;
        void definiertBesucher() override;
    };
    
    class Kuenstler : public Besucherrolle
    {
      public:
        int rolleID;
        void definiertBesucher() override;
    };
    
    // ********************************* METHODEN **********************************
    Besucher::Besucher(){}
    Besucher::Besucher(Besucherrolle& typBesucher)
    {
      grundBesuch.push_back(&typBesucher);
      grundBesuch.at(0)->besucherRolle="Gast";
      // Downcasten geht hier nicht:
      //dynamic_cast<Gast*>(grundBesuch.at(0)->hatTicketGekauft);
    
      grundBesuch.push_back(new Kuenstler);
      grundBesuch.at(1)->besucherRolle="Kuenstler";
    }
    
    void Gast::definiertBesucher()
    {
      hatTicketGekauft=true;
    }
    
    void Kuenstler::definiertBesucher() {/*steht was*/}
    
    // *********************************** MAIN **********************************
    int main()
    {
      Gast einGast;
      Besucher besucherRob(einGast);
      besucherRob.eintrittserlaubnis=true;
      besucherRob.name="Rob";
    
      einGast.hatTicketGekauft=true;
    
      return 0;
    }
    

    Wie ich die Idee dieses Analysemusters verstehe, soll die "Besucher"-Klasse zugriff auf die Klassen "Gast" und "Künstler" haben. Das habe ich mit den Vektor in Zeile 14 versucht zu implementieren. Hier nochmal:

    std::vector<Besucherrolle*> grundBesuch;
    

    Zugleich sollen Gast und Künstler zugriff auf Besucher haben können. (Zeile 28).

    Erste Frage: Habe ich die Umsetzung des Modells richtig gemacht? Wenn nicht, wie würde die Umsetzung hierzu aussehen? Statt die Verwendung eines Vektors mit Zeiger auf die Basisklasse Besucherrollen durch den auf die verschieden Objekte Kindklassen gezeigt wird, sollte vielleicht ein Vektor für jede Kindklasse angelegt um Zugriffprobleme zu vermeiden?

    Zweite Frage: Wenn ja. In dieser Form kann ich aber nicht von Klasse "Besucher" auf die Kindklassen von "Besucherrolle": "Gast" und "Künstler" zugreifen. Auch nicht mit einem Versuch "Downzucasten" wie in die kommentierte Zeile 54.

    dynamic_cast<Gast*>(grundBesuch.at(0)->hatTicketGekauft);
    

    gibt mir einen Complierfehler:

    error: 'class Besucherrolle' has no member named 'hatTicketGekauft'
    

    Außerdem finde ich die Lösung durch Cast nicht optimal. Vielleicht gibt es eine bessere Lösung ohne Cast. Diese würde mich interessieren.

    Diese Übung ist eine für mich. Ich bin dabei zu versuchen verschiedene Analysemuster in C++ umzuschreiben. Bin aber neu in diesem Thema. Deshalb bitte ich im Verständnis, falls das Gemachte sinnlos ist.

    Ich freue mich auf Eure Antworten.



  • @GMgenia sagte in Von UML zu C++ (Analysemuster "Wechselnde Rollen"):

    error: 'class Besucherrolle' has no member named 'hatTicketGekauft'

    Überleg dir noch mal, was du in deinem Code castest. Die Fehlermeldung gibt dir einen Hinweis.



  • Hallo, danke für die Antwort!

    Aber ich denke, dass meine Fragen nicht ganz verstanden wurden. Es geht mir erstmal darum zu wissen ob das Muster adäquat umgesetzt wurde. Das ist die Hauptfrage.

    Zweitens will ich gerne wissen ob eine Lösung ohne Casten möglich wäre.

    Und falls nicht, dann würde ich schon gerne eine etwas präzisere Antwort zum Casten erhalten wollen, als ein "überleg mal".



  • @GMgenia warum sollte ich nachdenken, wenn es dir zu anstrengend ist?



  • Dieses Form dient der doch der gegenseitigen Hilfe. Deswegen finde ich, Ihre Antwort passt hier nicht rein und ist unseriös. Hätte ich durch meine Überlegung die Antworten auf meine Fragen gefunden, würde ich doch diese Fragen hier nicht stellen. Wenn Sie keine konkreten Antworten auf meine Fragen haben, bitte ich Sie sich dann lieber gar nicht zu äußern. Es ist nur ein Zeitverlust sowohl für mich als auch für Sie.



  • Es ist total unüblich sich hier im Forum zu siezen. Was verstehst Du denn an der Fehlermeldung nicht?



  • @GMgenia sagte in Von UML zu C++ (Analysemuster "Wechselnde Rollen"):

    Dieses Form dient der doch der gegenseitigen Hilfe.

    Du hilfst mir? Das sehe ich nicht. Du verweigerst selbst jegliche Anstrengung und verlangst, dass andere umsonst deine Probleme lösen.



  • Es geht mir nicht um die Fehlermeldung. Es geht mir um die Umsetzung von UML zu C++ Code. Ob diese Umsetzung richtig. Das ist die Frage.

    Zur Fehlermeldung. Die Fehlermeldung verstehe ich gut. Ich kann durch der Basisklasse nicht auf die Kindklassen zugreifen. Das ist einleuchtend.

    Aber wie wird diese Modell dann in C++ umgesetzt, das ist meine Frage.



  • @GMgenia sagte in Von UML zu C++ (Analysemuster "Wechselnde Rollen"):

    dynamic_cast<Gast*>(grundBesuch.at(0)->hatTicketGekauft)
    

    dynamic_cast hat folgende Syntax: dynamic_cast<ZielTyp>(ZuCastendesObjekt).
    Bei dir wäre also ZielTyp die Klasse Gast (OK) und ZuCastendesObjekt wäre grundBesuch.at(0)->hatTicketGekauft. Und letzteres ist halt falsch. Weil grundBesuch.at(0) dir einen Besucherrolle* gibt und Besucherrolle hat nunmal kein Member hatTicketGekauft.
    Was auch schon die Fehlermeldung sagt: error: 'class Besucherrolle' has no member named 'hatTicketGekauft'

    Du musst Casten bevor du versuchst auf das Member von Gast zuzugreifen.
    Also z.B.

    dynamic_cast<Gast*>(grundBesuch.at(0))->hatTicketGekauft = true;
    

    Davon abgesehen: Wenn ich UML Analysemuster richtig verstanden habe, dann setzt man die um indem man erstmal ein Design bastelt (mit Designmustern und so). Und erst diese setzt man dann in Code um.

    Weiters riecht dieses Muster "Wechselnde Rollen" sehr nach Datenbank. Das in C++ direkt so umzusetzen wird selten Sinn machen.

    Allgemeiner Tip: Versuche immer mit realistischen Beispielen zu arbeiten. Besucher/Künstler/Gäste als C++ Klassen sind kein realistisches Beispiel. Besucher/Künstler/Gäste in einer Datenbank sind schon eher realistisch. *
    Davon abgesehen brauchst du für eine sinnvolle Modellierung immer eine Aufgabe bzw. ein Set von Aufgaben denen das Modell/das daraus erstellte Programm gerecht werden soll.
    Anders gesagt: du brauchst ein Ziel. Ohne Ziel irgendwas drauf los zu modellieren macht keinen Sinn.

    EDIT:

    Vielleicht sollte ich dazusagen dass das Ziel nicht sein kann "Besucher/Künstler/Gäste zu modellieren". Das ist viel zu wenig konkret. Es geht darum mit welchen Daten konkret gearbeitet werden soll und darum welche Operationen auf diesen Daten ausgeführt werden sollen.

    *: Natürlich kann man alles was man in einer Datenbank ablegen kann auch in C++ Objekten ablegen. Nur ist es sehr unüblich für typische Datenbank-Aufgaben Code zu schreiben der das direkt in C++ abbildet. Für typische Datenbank-Aufgaben nimmt man halt Datenbanken. In C++ schreibt man dann vielleicht die Teile die die Daten in die Datenbank einfügen, Abfragen darauf formulieren, Änderungen machen etc. Wobei auch das eher unüblich ist - für Datenbank-Zeugs werden eher andere Sprachen verwendet. Beispielsweise Java oder C#.



  • @GMgenia sagte in Von UML zu C++ (Analysemuster "Wechselnde Rollen"):

    Aber wie wird diese Modell dann in C++ umgesetzt, das ist meine Frage.

    Gar nicht (direkt).
    Das ist ein Analysemuster, kein Designmuster.
    Und wie gesagt: es riecht sehr nach Datenbank.



  • Danke für die Antwort zum Casten!

    Zu dem Problem an sich. Ich habe mir ein Buch gekauft: "Objektorientierter Softwareentwurf mit UML) - Grundlagen". Das Beispiel ist im Buch genauso geschildert wie ich es hier übertragen habe, und mit den selben Klassenbeispielen.

    Ich bin sehr neu in UML Übertagung zu Code.

    Deshalb können meine Fragen sehr Basic erscheinen.

    Dennoch, wenn ich dem Buch folge, sind Analysemuster insgesamt sehr, sehr kurze Codes. So zumindest die geschilderten Beispiele in C#. Wie ich es verstehe sind Analysemuster wie Skelette auf denen dann weiter gearbeitet wird und die immer wieder verwendet werden können. Ob, zum Beispiel, später die erhaltenen Daten in einer Datenbank gespeichert werden, käme, wie ich den Buch verstehe, hier erstmal nicht in Frage.

    Ich habe auch mehrere Beispiele von Übertragung von Analysemustern zu C++ Code auf verschiedenen Webseiten gefunden, und es sind immer sehr kurze Codebeispiele, von nicht mehr als 50 Zeilen und viele weit weniger.

    Ich denke also, dass dies hier in diesem Analysemuster nicht anders sein sollte.

    Diese Link finde ich gut hierzu:
    https://www.informatik-aktuell.de/entwicklung/methoden/von-der-uml-nach-c-vererbung-und-interfaces.html
    https://www.pearson.ch/download/media/9783827316516_SP.pdf



  • @GMgenia sagte in Von UML zu C++ (Analysemuster "Wechselnde Rollen"):

    Ich denke also, dass dies hier in diesem Analysemuster nicht anders sein sollte.

    Dann zitiere ich eben Deine eigene Quelle:

    Analyse und Design: In der Analysephase wird zunächst geklärt, was zu tun ist. Erst in der Designphase wird festgelegt, wie dies zu tun ist.



  • @GMgenia sagte in Von UML zu C++ (Analysemuster "Wechselnde Rollen"):

    Ich habe auch mehrere Beispiele von Übertragung von Analysemustern zu C++ Code auf verschiedenen Webseiten gefunden, und es sind immer sehr kurze Codebeispiele, von nicht mehr als 50 Zeilen und viele weit weniger.

    Zeig mal ein Beispiel.
    In deinen Links sehe ich kein einziges Analysemuster.

    Davon abgesehen:
    Du kannst das Muster "Wechselnde Rollen" in ein Klassendiagramm übertragen, und dieses Klassendiagramm kannst du dann natürlich in C++ abbilden.

    Was deine Lösung angeht: jetzt mal nur auf die Datenstruktur bezogen hast du hier eine N:1 Beziehung Besucher 1----* Besucherrolle modelliert. Soweit entspricht das noch dem Muster. Weiters hast du von Besucherrolle abgeleitete Klassen - auch das entspricht noch dem Muster.

    Allerdings hast du das Muster mMn. in der Analysemuster -> Klassendiagramm Phase falsch angewendet. bool eintrittserlaubnis; als Eigenschaft von Besucher macht keinen Sinn. Denn diese Eigenschaft ist abhängig von der Veranstaltung und der Rolle.
    Bei Veranstaltungen wo der Besucher als Künstler agiert hat er vermutlich implizit eine
    Eintrittserlaubnis. Und bei Veranstaltungen wo er als Gast agiert ist die Eintrittserlaubnis abhängig davon ob er sich z.B. ein Ticket gekauft hat. D.h. der Wert kann je nach Veranstatung unterschiedlich sein. Er kann daher kein Attribut des Besuchers sein.

    Was mMn. auch Quatsch ist ist std::string besucherRolle; als Attribut von Besucherrolle. Den Typ nochmal als String abzulegen macht keinen Sinn.

    Was dagegen in Besucherrolle fehlt ist die Information für welche Veranstaltung diese Rolle gilt.

    In diesem Beispiel wäre also noch eine 3. Klasse nötig: Veranstaltung (Besucherrolle *----1 Veranstaltung).



  • @GMgenia sagte in Von UML zu C++ (Analysemuster "Wechselnde Rollen"):

    Dennoch, wenn ich dem Buch folge, sind Analysemuster insgesamt sehr, sehr kurze Codes.

    Analysemuster sind keine "Codes".



  • Ich meine die Umsetzung eines Analysemuster zu Code.



  • @GMgenia sagte in Von UML zu C++ (Analysemuster "Wechselnde Rollen"):

    Ich meine die Umsetzung eines Analysemuster zu Code.

    OK.

    Dabei sind jetzt zwei Dinge wichtig:

    1. Diese Umsetzung erfolgt nicht direkt sondern in mehreren Schritten: Erstmal baust du mit Hilfe der in der Analyhsphase ermittelten Muster ein Design. Und dann baust du aus dem Design halt Code. Wobei auch das wieder ein mehrstufiger Prozess ist, denn als erstes sollte man sich mal überlegen welche Werkzeuge (Sprachen, fertige Komponenten wie Libraries/Datenbanken etc.) man verwenden sollte.
    2. Der Prozess so einer Umsetzung ist nicht eindeutig.

    Beispiele für solche Umsetzungen sind sehr hilfreich dabei zu verstehen wie ein bestimmtes Muster gemeint ist. Aber nicht geeignet dafür sie zu lernen und dann 1:1 in Programme reinzutippen.



  • @Swordfish Es geht nicht um die Analysephase. Es geht um die OOA-Musterlösungen.

    In meinem Buch steht dazu:
    "Ein OOA-Muster (also objektorientierter Analysemuster) ist ein Ausschnitt aus vorhandenen OOA-Modellen, dessen Implementierung sich in der Praxis bereits bewährt hat und entsprechend als standardisierte Lösung angesehen werden kann.
    Sie haben die Möglichkeit, sowohl allgemeine Muster als auch Muster zu verwenden, die für spezielle Szenarien vorgesehen sind und deren Einsitzt nur dort sinnvoll erscheint.

    Ein Muster besteht aus einer Gruppe von Klassen, die festgelegte Verantwortlichkeiten und Interaktionen besitzen.

    Mit dem Einsatz von Mustern tritt der Erstellungsprozess bereits in die Phase des OOD (objekt-orientiertes-Design) über."

    Das ist genau was ich versuche zu tun.

    Ich will gerne wissen ob die Übertragung, der vorherigen Definition folgend, die ich von dem Muster "wechselnde Rollen" zu Code gemacht habe, passend wäre oder ob diese Übertragung anders wäre, also, ob das Muster anderes zu interpretieren ist.



  • @GMgenia sagte in Von UML zu C++ (Analysemuster "Wechselnde Rollen"):

    Ich will gerne wissen ob die Übertragung, der vorherigen Definition folgend, die ich von dem Muster "wechselnde Rollen" zu Code gemacht habe, passend wäre oder ob diese Übertragung anders wäre, also, ob das Muster anderes zu interpretieren ist.

    Da fehlt ein ganzer Schritt. Das Design!



  • @hustbaer Das klärt einige meiner Fragen.



  • @GMgenia sagte in Von UML zu C++ (Analysemuster "Wechselnde Rollen"):

    ch will gerne wissen ob die Übertragung, der vorherigen Definition folgend, die ich von dem Muster "wechselnde Rollen" zu Code gemacht habe, passend wäre oder ob diese Übertragung anders wäre, also, ob das Muster anderes zu interpretieren ist.

    Dazu hab ich dir ja bereits einen etwas längeren Beitrag geschrieben.

    Und es gibt noch weitere Dinge die in deiner Umsetzung keinen Sinn machen.

    z.B. was soll die Funktion definiertBesucher darstellen? Und der Code in Besucher::Besucher(Besucherrolle& typBesucher) ist auch völlig sinnfrei. Was mich wieder dazu bringt dass Beispiele realistisch sein müssen.

    Entweder du lässt erstmal alle Vorgänge weg und beschränkst dich darauf die Daten zu modellieren. Dann wirst du in deinem C++ Code keine Funktionen haben.

    Oder du brauchst realistische Vorgänge die du modellieren willst.
    Und dass jeder Besucher initial mit einer von aussen definierten Besucherrolle startet, zusätzlich aber immer die Rolle Künstler einnimmt, ist nicht realistisch.


Anmelden zum Antworten