Klassen statt Funktionen



  • Hallo,

    ich bin dabei ein größeres Programm zu schreiben.

    Das Programm liest Daten einer Turbine aus 2 verschiedenen Textdateien ein.
    Diese Daten speichert es in einem Objekt der Klasse Turbine ab. Diese Klasse Turbine enthält auch eine Klasse Schaufel über eine Komposition.
    Dann führt es unterschiedliche Berechnungen mit den Daten durch und gibt die Ergebnisse aus.

    Die genannten Klassen scheinen sinnvoll zu sein, aber das Einlesen der Daten mache ich zur Zeit über Funktionen ohne Klassen. Es sind einige Funktionen wie z.B. AnalysiereZeile(), UseTextDoc2(), SchreibeSchaufelDaten(), TrimWhiteSpace() und diese sind eher lang, da die Daten komplex sind und nicht ganz einfach einzulesen sind.
    Dabei frage ich mich, ob es nicht vielleicht besser wäre, auch das Einlesen über Klassen statt nur Funktionen zu realisieren. Aber irgendwie fehlt mir der Ansatz dazu. Im Allgemeinen wird OOP bevorzugt, aber kann es in diesem Fall dennoch nicht sinnvoll sein?

    Könnt ihr mir sagen, inwiefern das Einlesen mit Klassen besser sein könnte und wie man das realisieren könnte?



  • Dinge, die man anfassen kann, sind Klassenobjekte. Also Deine Turbinen und Schaufeln (außer es ist nur eine Schaufelanzahl, dann isses nur ein int).
    Tätigkeiten sind Funktionen.
    Du bis perfekt auf dem rechten Wege.
    Meide Klassen. Mach sie nur, wo sie sich aufdrängen.
    OOP ist nur ein Zuckerle, und soll nicht hübsche klare Wege verdrängen. Am Ende mache es so, wie Du den Eindruck hast, daß es sich hübsch anfühlt. Keine religiösen Lehrsätze befolgen, die dann doch nur dafür sorgen, daß Du umständlich programmierst. Bescheidenheit in der Wahl der Sprachmittel ist die allerwichstigste Tugend des sehr guten Programmierers.
    Also laß krachen, mach, was Du willst, glaube keinem.
    Auch mir nicht. Besonders, wenn ich wieder absolute statements absetze. Die sind immer falsch. Das ist ja das verteufelte am Programmieren.



  • Und was spricht gegen Methoden?

    Methoden können auch Tätigkeiten erledigen?

    Definition:
    Methode = Funktion einer Klasse, im Sinne von "NICHT Zweck einer Klasse"
    Funktion = freistehende Funktion



  • Pippi schrieb:

    Und was spricht gegen Methoden?

    Methoden können auch Tätigkeiten erledigen?

    Definition:
    Methode = Funktion einer Klasse, im Sinne von "NICHT Zweck einer Klasse"
    Funktion = freistehende Funktion

    In #c++@freenode wirste für solche Aussagen gesteinigt.



  • Pippi schrieb:

    Und was spricht gegen Methoden?
    Methoden können auch Tätigkeiten erledigen?

    Klar. Wenn es die Klasse gibt, und da eine Methode gut reinpaßt.

    Halt nicht nur deshalb Methoden bauen, weil es "objektorientierter" erscheint, wie

    class Mathematik{
       ...
       double wurzel(double x);
    };
    


  • Du könntest auch statt Klassen namespaces verwenden, dadurch hättest du eine gewisse Strukturierung in deinem Code.



  • Okay, danke für den Rat.
    Ich werde es wohl so lassen wie es ist, evtl. später namespaces verwenden.

    Eine andere Frage: durch die Komposition ( ein Objekt Turbine hat 3 Objekte Schaufeln) habe ich das Problem, für alle Set Methoden des Turbinen-Objekts Set Methoden der Schaufeln aufrufen und diese erst die Werte belegen können. Gibt es eine Möglichkeit, das geschickter zu machen?

    Ich habe es mit einem Pointer versucht, der immer auf die gerade verwendete Schaufeln zeigt. Aber selbst der Pointer hat ja keinen Zugriff auf private Daten einer Unterklasse ...



  • chubb20 schrieb:

    Eine andere Frage: durch die Komposition ( ein Objekt Turbine hat 3 Objekte Schaufeln) habe ich das Problem, für alle Set Methoden des Turbinen-Objekts Set Methoden der Schaufeln aufrufen und diese erst die Werte belegen können. Gibt es eine Möglichkeit, das geschickter zu machen?

    Was genau? Normalerweise ist es geschickt, nicht zu viele Set- und Get-Funktionen zu verwenden. Gerade wenn diese nicht bedeutungsvoll implementiert werden können, ist das ein Hinweis darauf, sie besser wegzulassen. Denn nicht jeder Member braucht einen 1:1-Getter und -Setter.



  • Das Problem ist, dass ich durch das Einlesen (und der Suche nach Schlüsselwörtern dabei) in Unterfunktionen bin und die eingelesenen Werte daher nicht so gut zusammen in einer Set() Methode setzen kann.

    Mir bleibt wohl die Wahl zu versuchen, die Werte per Referenz in den Unterfunktionen zu ändern und dann am Ende in der main() eine Set() Methode für viele Werte zu verwenden

    oder aber

    wie bisher eher viele Set() Methoden zu verwenden.

    (Man kann nicht auf ein SchaufelObjekt direkt zugreifen; man muss es über die Turbine machen oder?)



  • chubb20 schrieb:

    (Man kann nicht auf ein SchaufelObjekt direkt zugreifen; man muss es über die Turbine machen oder?)

    Die Frage ist eher, warum du überhaupt auf die Schaufelobjekte zugreifen musst? Stellt die Turbine nicht eine Abstraktion der Schaufeln dar? Denn wenn die Turbine 2.0 plötzlich nicht nur 3, sondern 4 Schaufeln hat, kannst du so ohne Weiteres die Implementierung austauschen, während die Schnittstelle gleich bleibt.

    Keine Ahnung wie sinnvoll das bei deinem Beispiel ist, aber es ist generell ein guter Grundsatz, die Schnittstelle der Klasse eher klein zu halten.



  • Scorcher24 schrieb:

    Pippi schrieb:

    Und was spricht gegen Methoden?

    Methoden können auch Tätigkeiten erledigen?

    Definition:
    Methode = Funktion einer Klasse, im Sinne von "NICHT Zweck einer Klasse"
    Funktion = freistehende Funktion

    In #c++@freenode wirste für solche Aussagen gesteinigt.

    Weshalb?

    Was stimmt an der Aussage nicht?



  • Ich verstehe nicht, warum "NICHT Zweck einer Klasse" so betont wird. Methoden zeigen, was ein Objekt "tun kann" oder "was damit gemacht werden" kann, d.h. die Methode wird Attribute verändern oder Attribute auswerten und auf bestimmte Weise zurückliefern.

    Meinetwegen kann es auch noch Hilfsfunktionen geben, die nur Rückgabewerte liefern, welche weiter verwendet werden, das sind dann beispielsweise private Methoden, die man aber eher reinsteckt, weil man hier den Vorteil hat, dass sie nach außen nicht sichtbar sind (man kann allerdings überlegen, ob sie nicht dennoch nach außen sichtbar und frei sein sollten, wenn sie keine Attribute nutzen).

    Und Math ist meiner Auffassung nach deswegen so ein typisches Beispiel für eine unnötige Klasse, weil keine der Methoden irgendwelche Attribute ändert. Mehr noch: Alle Methoden sind statisch. Das ist keine Klasse.



  • Nexus schrieb:

    Die Frage ist eher, warum du überhaupt auf die Schaufelobjekte zugreifen musst?

    Je mehr ich über die Komposition nachdenke, umso bedenklicher kommt mir die Verbindung vor. Physikalisch gesehen "hat eine Turbine Schaufeln", aber:

    In dem Programm wird nur eine Turbine benutzt. Vor dem Programstart ist die Anzahl der Schaufeln nicht bekannt, sie wird aber über eine Datei eingelesen und dann nicht mehr verändert. Auch die Eigenschaften der Schaufeln werden nicht mehr verändert. Daher hat das Schnittstellenkonzept für mich kaum Bedeutung.
    Im Grunde haben die Schaufeln alle ein paar Gemeinsamkeiten, die ich in der Klasse Turbine abgespeichert habe, sonst hat die Turbine keine bestimmte Aufgabe. Ansonsten brauche ich hauptsächlich die Schaufeln und deren Werte. Daher ist es für mich umständlich, auf die Schaufeln über die Turbine zuzugreifen.

    Nun überlege ich, ob es sein könnte, dass eine Vererbung sinnvoller ist, oder ob ich die beiden Klassen Turbine und Schaufel einfach nebeneinander existieren lasse ohne eine bestimmte Verbindung.



  • chubb20 schrieb:

    Nun überlege ich, ob es sein könnte, dass eine Vererbung sinnvoller ist, oder ob ich die beiden Klassen Turbine und Schaufel einfach nebeneinander existieren lasse ohne eine bestimmte Verbindung.

    Tun die verscheidenen Schaufeln denn unterschiedlich schaufeln? Mußt Du verschiedene Schaufelklassen mit vierschiedenen virtuellen schaufel()-Methoden haben? Falls nicht, kann es sein, daß es bei der Turbinenklasse bleibt und es gar keine Schaufelklasse gibt.



  • Mmh ich bin mir nicht ganz sicher:
    Es gibt verschiedene Schaufeln mit unterschiedlichen Werten bzw. Attributen. Allerdings brauch ich keine verschiedenen Methoden für die verschiedenen Schaufeln.

    Also denke ich du hast recht und ich kann entweder die Turbinen oder die Schaufelklasse weglassen und die Werte in die andere Klasse übernehmen.
    Am sinnvollsten ist es glaube ich, nur eine Schaufel-Klasse zu haben und die Werte, die für alle Schaufeln gleich sind, als statische Attribute zu wählen.



  • chubb20 schrieb:

    Mmh ich bin mir nicht ganz sicher:
    Es gibt verschiedene Schaufeln mit unterschiedlichen Werten bzw. Attributen. Allerdings brauch ich keine verschiedenen Methoden für die verschiedenen Schaufeln.

    Haben die Schaufeln die gleichen Attribute mit unterschiedlichen Werten, oder haben sie tatsächlich unterschiedliche Attribute? Wenn wirklich unterschiedliche Attribute aber die gleichen Methoden für unterschiedliche Schaufeln angenommen werden können, dann spricht dies u.U. für Polymorphie.

    chubb20 schrieb:

    Also denke ich du hast recht und ich kann entweder die Turbinen oder die Schaufelklasse weglassen und die Werte in die andere Klasse übernehmen.
    Am sinnvollsten ist es glaube ich, nur eine Schaufel-Klasse zu haben und die Werte, die für alle Schaufeln gleich sind, als statische Attribute zu wählen.

    Hat die Turbinenklasse noch eine andere Aufgabe als die, Schaufeln zu gruppieren? Ist z.B. der Anstellwinkel einer Schaufel in einer Turbine eine Eigenschaft der Schaufel oder der Turbine? Kann der Anstellwinkel variabel sein? Ist es denn dann eine Eigenschaft der Turbine? Hat die Turbine Eigenaschaften, welche nicht den Schaufeln zugeordnet werden können? Ist z.B. das Lager relevant für Dein Modell? Ist es relevent, die Schaufeln auch eigenständig betrachten zu können?



  • Die Schaufeln haben alle die gleichen Attribute.

    Ja, die Turbine hat Eigenschaften (Attribute), die nicht den Schaufeln zugeordnet werden können (in der Tat z.B. das Lager). Ein Attribut wirkt z.B. auf die eine Hälfte der Schaufeln mit positivem Vorzeichen, auf die andere Hälfte mit negativem Vorzeichen. Das Ergebnis ergibt sich am Ende aus Eigenschaften von Turbine und Schaufeln.

    Bisher habe ich eine feste Anzahl von Schaufeln "per Value" in der Turbinenklasse. Aber ich möchte eine variable Anzahl haben.
    Vielleicht sollte ich einen Pointer zu einem Schaufelobjekt in der Turbinenklasse verwenden.

    Dann kann eine beliebige Anzahl Schaufeln erzeugt werden und auch außerhalb der Turbinenklasse. Zudem kann ich die Schaufel-Objekte dann mit Werten belegen ohne über die Turbine zugreifen zu müssen oder?



  • Eisflamme schrieb:

    Ich verstehe nicht, warum "NICHT Zweck einer Klasse" so betont wird. Methoden zeigen, was ein Objekt "tun kann" oder "was damit gemacht werden" kann, d.h. die Methode wird Attribute verändern oder Attribute auswerten und auf bestimmte Weise zurückliefern.

    Genau das zeigen Methoden eigentlich nicht.
    Klar, du kannst die Attribute eines Objekts ändern, aber was man mit Objekten machen kann, wird dadurch nicht wirklich gesagt.
    Denn du kannst z.B. ja auch mit Objekten Dinge anstellen und dabei lediglich auf set und get Methoden zurückgreifen, obwohl du aber über richtige Funktionen viel mehr mit den Objekten machst.

    Du könntest Objekte z.b. selbst als Elemente einer Liste speichern, die Liste selbst existiert dann aber außerhalb des Objekts und wird daher auch nicht mit den Klassenmethoden des Objekts verwaltet, sondern eben z.B. mit freistehenden Funktionen wie bei C mit structs üblich.
    In diesem Fall wird das Objekt nämlich zum Datentyp reduziert, natürlich mit den vielen Methoden die Attribute des Objekts zu manipulieren, aber es bleibt von außen betrachtet halt nur ein Datentyp in der Liste, viel mehr ist es dann nicht.



  • chubb20 schrieb:

    Hallo,

    ich bin dabei ein größeres Programm zu schreiben.

    Das Programm liest Daten einer Turbine aus 2 verschiedenen Textdateien ein.
    Diese Daten speichert es in einem Objekt der Klasse Turbine ab. Diese Klasse Turbine enthält auch eine Klasse Schaufel über eine Komposition.
    Dann führt es unterschiedliche Berechnungen mit den Daten durch und gibt die Ergebnisse aus.

    Die genannten Klassen scheinen sinnvoll zu sein, aber das Einlesen der Daten mache ich zur Zeit über Funktionen ohne Klassen. Es sind einige Funktionen wie z.B. AnalysiereZeile(), UseTextDoc2(), SchreibeSchaufelDaten(), TrimWhiteSpace() und diese sind eher lang, da die Daten komplex sind und nicht ganz einfach einzulesen sind.
    Dabei frage ich mich, ob es nicht vielleicht besser wäre, auch das Einlesen über Klassen statt nur Funktionen zu realisieren. Aber irgendwie fehlt mir der Ansatz dazu. Im Allgemeinen wird OOP bevorzugt, aber kann es in diesem Fall dennoch nicht sinnvoll sein?

    Könnt ihr mir sagen, inwiefern das Einlesen mit Klassen besser sein könnte und wie man das realisieren könnte?

    Kannst du mal beschreiben, was du machen willst, ohne irgendwelche Klassen und Attribute zu erwähnen? Also einfach nur was deine Daten sind, was eingestelt und berechnet werden soll und was dann ausgegeben wird. Sonst wird das hier nur ein wildes rumgerate.



  • Bei der bisherigen Beschreibung von OP könnte es durchaus sinnvoll sein, einige Funktionen als static Methoden der Klasse Turbine anzubieten.

    Und die Funktion "SchreibeSchaufelDaten" sollte wahrscheinlich als public Methode der Klasse Schaufel angeboten werden.

    mfg, NRWsoft


Log in to reply