Designfrage: Motor _hat_ Motorkomponenten



  • Hallo Leute,

    stehe ein wenig auf dem Schlauf, wie ich ein vermeintlich simples Konstrukt am besten anlege.

    Beispiel: Es gibt eine Klasse Motor (davon abeleitet verschiedene Arten von speziellen Motoren) und eine Klasse Motorkomponente (z. B. Stator, Rotor, Welle, ...).

    Ein Motor habe nun eine Liste von Motorkomponenten. Jede Motorkomponente soll wissen, zu welchem Motor sie gehört. Daher mein Ansatz: Die Motorkomponenten werden im Konstruktor von Motor angelegt und erhalten jeweils den this-Zeiger, um später auf den Motor schließen zu können (und darüber dann auch auf andere Motorkomponenten, z. B. muss der Rotor auf wissen, welcher Stator denn zu ihm gehört).

    Irgendwie besonders schick find ich das nicht. Gibt´s da in der weiten Welt der Entwurfsmuster was schöneres?

    class Motor
    {
    private:
    list<Motorkomponente*> komponenten;
    }
    
    class Motorkomponente
    {
    private:
    Motor* const m;
    public:
    Motorkomponente(Motor* const am):m(am);
    }
    
    class Stator:public Motorkomponente
    {
    public:
    Stator(Motor* const am):Motorkomponente(am);
    }
    

  • Mod

    KeineAhnung78 schrieb:

    Irgendwie besonders schick find ich das nicht. Gibt´s da in der weiten Welt der Entwurfsmuster was schöneres?

    Im gewissen Sinne ja: Ganz anderes Design. Da hinkt irgendwas gewaltig. Warum muss eine Komponente wissen, zu welchem Ganzen sie gehört? Ist der Stator denn abhängig vom Motortyp verschieden? Dann gehört dies (falls es sich um unterschieldliche Parameter handelt) in die Statorinitialisierung des Motortyps oder (falls sich das Verhalten komplett ändert) in eine eigene abgeleitete Klasse.

    Wenn der Rotor wissen muss, welcher Stator zu ihm gehört, dann teil ihm dies (und nur dies) mit. Oder bau noch ein Verbindungsstück ein, welches beide kennt. In einem abstrakten Sinne ist dies sicherlich ein Designpattern aus dem Bereich der Interobjektkommunikation, aber für solch eine Übungsaufgabe würde ich das eher selbst entwickeln.



  • SeppJ schrieb:

    Warum muss eine Komponente wissen, zu welchem Ganzen sie gehört?

    Im Gesamtprogramm kann es mehrere Motoren geben und entsprechend viele Einzelkomponenten. Für den Berechnungalgorithmus muss der Rotor u. a. auch auf Statoreigenschaften zugreifen müssen. Daher will ich eine Struktur schaffen, wo eine Motorkomponente es schafft, sich alle seine "Kollegen" zu holen und deshalb bin ich (ungeschickterweise) über die Klasse "Motor" gegangen.

    SeppJ schrieb:

    Ist der Stator denn abhängig vom Motortyp verschieden? Dann gehört dies (falls es sich um unterschieldliche Parameter handelt) in die Statorinitialisierung des Motortyps oder (falls sich das Verhalten komplett ändert) in eine eigene abgeleitete Klasse.

    Ja, der Stator ist vom Motortyp verschieden.

    SeppJ schrieb:

    Wenn der Rotor wissen muss, welcher Stator zu ihm gehört, dann teil ihm dies (und nur dies) mit. Oder bau noch ein Verbindungsstück ein, welches beide kennt. In einem abstrakten Sinne ist dies sicherlich ein Designpattern aus dem Bereich der Interobjektkommunikation, aber für solch eine Übungsaufgabe würde ich das eher selbst entwickeln.

    Nur eine Verbindung zwischen Stator und Rotor ist zu wenig. Es müssen alle Motorkompoenten sich finden können.

    Vielleicht hab ich ein Verständnisproblem, aber denk mal an ein Auto, dass viele Komponenten hat. Die Komponente Kofferraumsteckdose muss nun wissen, wie der Zustand der Batterie ist, dazu muss die Steckdose die Aufgabe "deligieren", was mit der Batterie los ist.


  • Mod

    KeineAhnung78 schrieb:

    Vielleicht hab ich ein Verständnisproblem, aber denk mal an ein Auto, dass viele Komponenten hat. Die Komponente Kofferraumsteckdose muss nun wissen, wie der Zustand der Batterie ist, dazu muss die Steckdose die Aufgabe "deligieren", was mit der Batterie los ist.

    Das ist richtig. Die Steckdose muss die Batterie kennen (oder ein Kabel zwischen ihnen verlegt sein). Aber nirgendwo kommt der Autotyp ins Spiel oder die Kurbelwelle des Motors. Es ist bloß eine Sache zwischen Steckdose und Batterie. Ich könnte die Kofferaumsteckdose und die Autobatterie beide ausbauen und bei mir auf dem Schreibtisch zusammenstecken. Es würde funktionieren, obwohl ich gar kein Auto habe. Wenn dein System die Wirklichkeit widerspiegeln soll, dann muss dies funktionieren. Die Steckdose braucht eine Batterie (oder besser allgemein: Eine Stromquelle) um ihre Funktion zu erfüllen, aber sie braucht nicht zu wissen in welchem Fahrzeug sie eingebaut ist.

    KeineAhnung78 schrieb:

    Im Gesamtprogramm kann es mehrere Motoren geben und entsprechend viele Einzelkomponenten. Für den Berechnungalgorithmus muss der Rotor u. a. auch auf Statoreigenschaften zugreifen müssen. Daher will ich eine Struktur schaffen, wo eine Motorkomponente es schafft, sich alle seine "Kollegen" zu holen und deshalb bin ich (ungeschickterweise) über die Klasse "Motor" gegangen.

    Geh nicht über den Motor um die Kollegen zu holen. Teil den Komponenten beim Zusammenbau (des Motors) mit, wer ihre Kollegen sind. Oder benutze die Abstraktion der Verbindungskomponenten, wenn du es ein bisschen schicker haben möchtest.



  • KeineAhnung78 schrieb:

    Nur eine Verbindung zwischen Stator und Rotor ist zu wenig. Es müssen alle Motorkompoenten sich finden können.

    Dann richtest du für alle Komponenten die sich kennen sollen eine Verbindung ein. Entweder ein eigenes Konzept, oder gleich boost::signals[2].
    Dann würde ich die einzelnen Komponenten NIEMALS in einer Liste mit gleichen Basiszeigern abspeichern. Die Anzahl der Elemente für jeden Motortyp ist bekannt, dann mach gleich ordentliche Member.

    Vielleicht hab ich ein Verständnisproblem, aber denk mal an ein Auto, dass viele Komponenten hat. Die Komponente Kofferraumsteckdose muss nun wissen, wie der Zustand der Batterie ist, dazu muss die Steckdose die Aufgabe "deligieren", was mit der Batterie los ist.

    Die Steckdose muss definitiv nicht wissen, was für eine Batterie an ihm hängt. Die Steckdose wurde vom Konstrukteur mit der Batterie verbunden. Im Programm bist du der Konstrukteur, die Verbindung legst du -> wieder mit boost::signals[2] oder einem eigenen Mechanismus.



  • Vielen Dank!!!

    Ich werde über eine Verbindungsklasse nachdenken und mir boost::signals ansehen.

    Leider wird es je nach Motortyp unterschiedliche Algorithmen und auch unterschiedliche notwendige Verbindungen geben. Daher muss die Struktur sehr allgemein sein. Ich kann nicht sagen, dass immer der Rotor auf den Stator zugreifen muss. Evtl. braucht der Rotor bei einem anderen Motor nun Parameter des Motorgehäuses...



  • Werden hier auch Motorenkenntnisse benötigt?
    Das sieht bisher nach einem E-Motor aus.

    MfG f.-th.


  • Mod

    KeineAhnung78 schrieb:

    Leider wird es je nach Motortyp unterschiedliche Algorithmen und auch unterschiedliche notwendige Verbindungen geben. Daher muss die Struktur sehr allgemein sein. Ich kann nicht sagen, dass immer der Rotor auf den Stator zugreifen muss. Evtl. braucht der Rotor bei einem anderen Motor nun Parameter des Motorgehäuses...

    Du könntest ein Strategy-Pattern zur Konstruktion des Motors benutzen. Das entspräche denn im wirklichen Leben dem Ingenieur der den Motor plant.



  • f.-th. schrieb:

    Werden hier auch Motorenkenntnisse benötigt?
    Das sieht bisher nach einem E-Motor aus.

    MfG f.-th.

    Ja, es geht um E-Motoren. Dennoch verstehe ich die Frage nicht ganz!?



  • KeineAhnung78 schrieb:

    Es gibt eine Klasse Motor (davon abeleitet verschiedene Arten von speziellen Motoren) und eine Klasse Motorkomponente (z. B. Stator, Rotor, Welle, ...).

    Ein Motor habe nun eine Liste von Motorkomponenten. Jede Motorkomponente soll wissen, zu welchem Motor sie gehört.

    wie SeppJ bin ich der Meinung, dass das ein Designfehler wäre, da Du zyklische Referenzen in Deinen Entwurf bekommst, die sich i.A. störend auswirken.

    Welche Zweck soll Deine fertige Applikation am Ende haben? Es ist ein Riesenunterschied, ob Du an einer (Motor-)Steuerung oder an einer (Motor-)Simulation oder einem Artikelverwaltungsprogramm für Motorteile arbeitest. Die dazugehörigen Entwürfe sind dann ziemlich unterschiedlich.

    Wie läuft das Programm ab? Was ist der Input und was soll am Ende ausgegeben werden?

    Warum nicht einen Motor mit Stator, Rotor und Welle als Member? Und der Motor schaltet dann die notwendigen Verbindungen zwischen den einzelnen Objekte; wobei diese ja noch mit Interfaces versehen werden können, falls es verschiedenen Typen von Motorkomponenten gibt.

    Eine Kernfrage ist noch: wozu dient Motorkomponente? Ist dies nur ein Griff zum Anfassen (und Wegwerfen) der Objekte, oder hat Motorkomponentenoch irgendeine 'Motoreigene' Methode?

    Gruß
    Werner



  • Wernen, vielen Dank für deine konkreten Fragen.

    Werner Salomon schrieb:

    Welche Zweck soll Deine fertige Applikation am Ende haben? Es ist ein Riesenunterschied, ob Du an einer (Motor-)Steuerung oder an einer (Motor-)Simulation oder einem Artikelverwaltungsprogramm für Motorteile arbeitest. Die dazugehörigen Entwürfe sind dann ziemlich unterschiedlich.

    Motorauslegung

    Werner Salomon schrieb:

    Wie läuft das Programm ab? Was ist der Input und was soll am Ende ausgegeben werden?

    Input sind verschiedene Textdateien (ini-Stil), die aber je nach Motor einen abweichenden Aufbau haben. Ausgegeben werden (zunächst auf Kommandozeile) die elektrischen Daten verschiedener Betriebspunkte. Die Eigenschaften des Motors werden also durch charakteristische Größen beschrieben.

    Werner Salomon schrieb:

    Warum nicht einen Motor mit Stator, Rotor und Welle als Member? Und der Motor schaltet dann die notwendigen Verbindungen zwischen den einzelnen Objekte; wobei diese ja noch mit Interfaces versehen werden können, falls es verschiedenen Typen von Motorkomponenten gibt.

    Hab ich sogar so gemacht, nur hier aus Schreibfaulheit die Liste eingefügt 🙄. Motor hat im Moment die Komponenten: Stator, Rotor, Gehäuse, Welle und Luftspalt. Wobei vielleicht besser Rotor und Welle durch ein _hat_ein_ verbunden werden könnten und ebenso Stator _hat_ein_ Gehäuse.

    Werner Salomon schrieb:

    Eine Kernfrage ist noch: wozu dient Motorkomponente? Ist dies nur ein Griff zum Anfassen (und Wegwerfen) der Objekte, oder hat Motorkomponentenoch irgendeine 'Motoreigene' Methode?

    Im Konstruktor möchte ich alle erforderlichen Daten (Abmessungen etc.) aus den ini-Datei in Membervariablen abspeichern und daraus weitere Kenndaten in Memberfunktionen berechnen, die sich unmittelbar aus den Inputdaten ergeben. Beispiel: Die Abmessungen einer Nut stehen in der Inputdatei und die Fläche dazu wird ausgerechnet.



  • Ich sehe in dem Zeiger jeder Komponente auf den Motor selbst absolut kein Problem.

    Die reale Welt muss nicht immer 1:1 abgebildet werden, es geht viel mehr darum die Aufgabenstellung zu modellieren. Daher sollten wir uns nicht über eine Werkstatt und das Ausbauen von Motoren unterhalten sondern über die Aufgabenstellung.

    Denn vielleicht sind die Parent-Pointer genau das was notwendig ist. uU ist hier eine Baumansicht sinnvoller als eine flache Liste? Das alles entscheidet die Aufgabenstellung...



  • Ich würde hier mal den Builder Pattern vorschlagen. Und wenn du mich fragst hat wohl weder der Rotor einen Stator noch der Stator einen Rotor. Ich würde mal sagen ein Motor besteht aus einem Stator und einem Rotor...



  • Shade Of Mine schrieb:

    Denn vielleicht sind die Parent-Pointer genau das was notwendig ist. uU ist hier eine Baumansicht sinnvoller als eine flache Liste? Das alles entscheidet die Aufgabenstellung...

    Ich könnte mir folgendes vorstellen:

    Stator, Rotor und Luftspalt kennen ihren Motor.

    Die Welle als Bestandteil des Rotors kennt zunächst nur den Rotor (und über diesen dann auch den Motor).

    usw...entpsprechend für die vielen anderen Komponenten.



  • Ok - 'Motorauslegeung' und der Input für den Motor kommt aus einer Textdatei, die aber anscheinend schon den fertigen Motor und nicht die Anforderungen an den Motor beschreibt.

    Ist es richtig, dass das Programm dann ausschließlich die Eigenschaften (elektr. Daten an Betriebspunkten etc.) berechnet, und die eigentliche Auslegung dann extern (ggf. durch den Bediener) geschieht?

    Wenn es so ist, dann hast Du sicher einen (oder mehrere) Algorithmen, die Daten aus den verschieden Komponenten sammeln und daraus die gewünschten Ergebnisse bestimmen.

    Mal angenommen, da sind mehrere Motortyen und zu jedem Typ gibt es genau einen Algorithmus. Dann erfordert dieser Algorithmus bestimmte Information von jeder einzelnen Motorkomponente.
    Wäre dann folgender Ablauf sinnvoll? Motor wird aus ini-Datei geladen - in Abhängigkeit des Inhalts der ini-Datei können unterschiedliche Klassen instanziiert werden (egal ob Motor oder dessen Komponenten). Der Motor legt ggf. noch Verbindungen zw. den Komponenten. Jede Komponente hat ein Interface über das der Algo zugreift.

    .. so ich brauche erstmal Dein 'so isses' - bevor ich weiter spinne 😉

    Gruß
    Werner



  • KeineAhnung78 schrieb:

    Ich könnte mir folgendes vorstellen:

    Stator, Rotor und Luftspalt kennen ihren Motor.

    Die Welle als Bestandteil des Rotors kennt zunächst nur den Rotor (und über diesen dann auch den Motor).

    usw...entpsprechend für die vielen anderen Komponenten.

    .. nein tu's nicht. ich habe selber vor Jahren auch mal so angefangen. Das ist voll in die Hose gegangen. Ich habe es anschließend das 'Papa-Pattern' genannt - aufzunehmen in die Gruppe der Antipattern.

    Das, was Du da vorschlägst, klappt nur, wenn der Motor seine Komponenten nicht kennt!



  • Werner Salomon schrieb:

    Mal angenommen, da sind mehrere Motortyen und zu jedem Typ gibt es genau einen Algorithmus. Dann erfordert dieser Algorithmus bestimmte Information von jeder einzelnen Motorkomponente.
    Wäre dann folgender Ablauf sinnvoll? Motor wird aus ini-Datei geladen - in Abhängigkeit des Inhalts der ini-Datei können unterschiedliche Klassen instanziiert werden (egal ob Motor oder dessen Komponenten). Der Motor legt ggf. noch Verbindungen zw. den Komponenten. Jede Komponente hat ein Interface über das der Algo zugreift.

    So isses :D.

    Je nach Motortyp gibt es eine Instanz einer von Motor abgeleiteten Klasse. Diese Klasse konstruiert alle benötigten Komponenten.

    Daneben gibt der Anwender (ebenfalls durch ini-Datei) vor, welche Berechnungen durchgeführt werden sollen.

    Dazu gibt es dann eine Klasse Berechnung, die diese Informationen verwaltet.

    Berechnung hält einen Zeiger auf den Motor. Soll bsp.weise ein Leerlauf berechnet werden, ruft Berechnung dann die entsprechende Leerlauffunktion der abgeleiteten Motorklasse auf (virtuelle Funktion).

    Und die Leerlauffunktion greift auf alle Daten der Motorkomponenten zu.



  • KeineAhnung78 schrieb:

    Dazu gibt es dann eine Klasse Berechnung, die diese Informationen verwaltet.

    Nö. Berchnung ist eine Funktion.



  • KeineAhnung78 schrieb:

    Je nach Motortyp gibt es eine Instanz einer von Motor abgeleiteten Klasse. Diese Klasse konstruiert alle benötigten Komponenten.

    Daneben gibt der Anwender (ebenfalls durch ini-Datei) vor, welche Berechnungen durchgeführt werden sollen.

    jetzt müßte man noch wissen, ob jede Berechnung auf jeden Motortyp angewendet werden kann? - wenn ja, wird es einfacher, weil man dann nur einen einzigen Satz von Interfaces benötigt, mit dem eine Berechnung auf Motor & Co zugreift.



  • Nur mal so eine Frage: Für was sind in dem Szenario eigentlich die Komponenten gut!?


Anmelden zum Antworten