Forum: PC-Programmierung Spaghetti Code in C++ vermeiden


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
von Matthias (Gast)


Lesenswert?

Hallo,

ich hab in einer GUI 6 TabSheets auf denen Frames liegen. Diese sind 
alle sehr ähnlich, d.h. die Datenverarbeitung ist immer gleich nur die 
Variablentypen, die Namen der Variablen und die Anzahl sind 
unterschiedlich.
Gibt es eine elegante Möglichkeit für eine Basisklasse, um unnötige 
Tipparbeit und Copy/Paste Fehler zu vermeiden?

von MaWin (Gast)


Lesenswert?

Matthias schrieb:
> Gibt es eine elegante Möglichkeit für eine Basisklasse, um unnötige
> Tipparbeit und Copy/Paste Fehler zu vermeiden?

ja

von Matthias (Gast)


Lesenswert?

Ach komm...

von c-lover (Gast)


Lesenswert?

Matthias schrieb:
> Ach komm...

Deine Frage wurde doch beantwortet...
Für genauere Antworten solltest du die Frage vielleicht präziser 
formulieren, bzw. mehr Kontext liefern.

von Thilo R. (harfner)


Lesenswert?

Etwas mehr Information wäre schon hilfreich, meine Kristallkugel ist 
gerade beim Kallibrieren.
So aus dem Bauch heraus: Eine Basisklasse, die die Werte in einer 
geeigneten Collection hält? Bei unterschiedlichen Typen können unter 
Umständen Templates helfen, aber dazu wäre es hilfreich, etwas über eben 
diese Umstände zu wissen.
Und GUIs gibt es auch mehrere, selbst wenn das OS bekannt wäre, was es 
hier nicht ist.
Übrigens geht es hier nicht um die Vermeidung von Spaghetti Code, 
sondern um die Vermeidung von Copy and Paste (was fraglos ein Übel ist, 
aber nicht das gleiche).

von Matthias (Gast)


Lesenswert?

Das OS und die GUI sollen mal keine Rolle spielen.
Letzen Endes geht es darum z.B. etwas aus einem .ini-file zu lesen, zu 
speichern, zur Anzeige zu bringen, bei Änderungen den Speicherinhalt 
aktualisieren, auf Knopfdruck einen Stream mit allen Daten zu versenden 
und beim Schließen die aktuellen Werte wieder ins ini.file zu schreiben.
Das Ganze bräuchte ich n-mal mit unterschiedlichen Namen, Datentypen und 
Anzahl.
Ich hab mir jetzt überlegt, eine Basisklasse mit allen Eigenschaften 
anzulegen und der Init-Funktion einen Pointer auf eine Struktur  und die 
Anzahl zu übergeben. Die Struktur beschreibt die Eigenschaften und den 
Namen von jedem Datum. Anhand dessen kann ich in den Methoden auf die 
Behandlung der entsprechenden Typen verzweigen.

von c-lover (Gast)


Lesenswert?


von Valeri D. (valeri_d)


Lesenswert?

Matthias schrieb:
> Hallo,
>
> ich hab in einer GUI 6 TabSheets auf denen Frames liegen. Diese sind
> alle sehr ähnlich, d.h. die Datenverarbeitung ist immer gleich nur die
> Variablentypen, die Namen der Variablen und die Anzahl sind
> unterschiedlich.
> Gibt es eine elegante Möglichkeit für eine Basisklasse, um unnötige
> Tipparbeit und Copy/Paste Fehler zu vermeiden?

Eine der Möglichkeit dazu, GUIs generisch zu erstellen. Dabei kommt man 
früher oder später dazu, die echten Eigenschaften, die auf der GUI nur 
angezeigt oder angezeigt und verändert werden können nicht fest zu 
haben, sondern auch dynamisch zu realisieren.

Dabei wird aber nötig sein, die dazugehörigen Informationen zu 
organisieren, wie Datentype, Validierungs-Werte, evtl. mögliche Werte 
abhängig von dem jetzigen Status (Lifecycle-Werte) usw. Das bedeutet, 
dass auch diese Informationen existieren nicht absolut wie in einer 
Klassen-Definition, sondern sind alle dynamisch und werden aus einem 
BusinessObject (BO) - Katalog ausgelesen. Egal wie man ihn auch 
definiert. Denn erst danach besteht die Möglichkeit, auch GUI dynamisch 
zu konfigurieren, wo bei den Feld-Platzhalter auch Namen der 
Eigenschaften erwähnt werden, die dort dargestellt werden. Da diese 
Namen alles Strings (Keys) sind und in dem BO Katalog sind die Felder 
Key-basiert sind, wird eine GUI-Engine in der Lage sein, aus dieser 
GUI-Konfiguration dein Dialog oder Teile des Dialoges zusammen zu 
stellen. Man kann weiter gehen, dazu einfache GUI-Editoren zu 
entwickeln.

Der Nachteil dabei ist, dass es erst zur Laufzeit die gesamte Bindungen 
und Überprüfungen gemacht werden. Somit Fehleranfällig. Z.B. in der 
Konfiguration definierst du ein Feld zur Anzeige "NAME2", jedoch dieses 
Feld gibt es nicht in deinem Katalog. Somit wird bei der Anzeige  mit 
dieser GUI-Konfiguration eine Kollision entstehen, die gelöst werden 
muss.

Und zweiter Nachteil besteht darin, dass früh oder später man genauso 
ein "komplexes" GUI-Editor entwickeln wird, der bereits da ist, um z.B. 
die Win-GUI zu beschreiben. Klar, wenn die GUI-Konfiguration danach 
vollständig aus den Felder erstellt werden kann, die derzeit aktiv sind, 
dann wird es nicht möglich sein, falscher Feldnamen zu benutzen und das 
Problem von oben weniger relevant sein kann. Trotzdem bleibt das Problem 
auch dort. Denn Felder können auch entfernt bzw. ersetzt werden, was in 
den GUIs noch nicht passierte usw. Aber das ist schon ein kleines Übel.

Es sind aber auch sehr viele Vorteile. Z.B. wird es mögliche sein, ohne 
die Software zu verändern oder neu zu verteilen, das gesamte BO Katalog 
und die dazu gehörigen GUIs zu in der neuen Version produktiv zu 
schalten. Alles kann z.B. in einer zentralen Datenbank gespeichert 
werden und von jedem Ort diesen Katalog kann beim Starten ausgelesen 
werden. Oder in einer ini-Datei. Je nach Größe der Applikation. Es ist 
eine ziemlich coole Sache. Nur, wenn man an "alles" denkt. So werden 
viele Lösungen gebaut. Besonders im Enterprise Bereich. Bestes Beispiel 
SAP.

Das bedeutet, dass es zwei Klassen-Arten existieren. Klassen für die 
eigentliche Applikation, um das Framework am Leben zu halten. Weitere 
sind Klassen, die in Wirklichkeit keine Klassen sind, sondern dynamische 
Container, die zur Laufzeit dynamisch gebaut, mit Daten gefüllt, 
geändert und gehalten werden, wo der Zugriff auf die Eigenschaften nicht 
im Programmcode "kompiliert" wird, sondern per Name auf die Werte 
zugegriffen wird. Auch die Funktionen mit solchen Objekten müssen 
realisiert werden. Denn diese Funktionen sind nicht mehr in der Klasse 
gekapselt, sondern Business-Funktionen verinnerlichen. Z.B. eine 
Funktion "Einen neuen User anlegen" ist nicht die Methode "AddNewUser" 
in der Klasse User. Sondern es ist eine Methode an der Klasse 
DatenAdapter.AddNeuUser und an sie wird ein dynamischer Container 
übergeben, der zur Laufzeit zusammengestellt wurde. Was ein dynamischer 
Container zur Laufzeit sein wird - ist dir überlassen. Es kann eine XML, 
JSON usw. sein. Es kann auch eine Auslistung bestimmter Werte sein, eine 
Datensatz mit dynamischen (zur Laufzeit erstellten) Feldern sein. Also 
hier ist die Kreation gefragt.

Es ist eine kurze Fassung. Ich hoffe, ein wenig verständlich 
dargestellt. Auch, wenn es evtl. an deiner Anfrage sehr weit vorbei 
geht.

Doch. Auch die Felder eigenhändig auf der Form zu platzieren, auch in 
der 100 Stück, ist zwar manchmal mühsam, gehört aber auch zum Geschäft. 
Daher bitte - wenn es sein muss, geduldig sein :)

von Wilhelm M. (wimalopaan)


Lesenswert?

Matthias schrieb:
> Ich hab mir jetzt überlegt, eine Basisklasse mit allen Eigenschaften
> anzulegen und der Init-Funktion einen Pointer auf eine Struktur  und die
> Anzahl zu übergeben. Die Struktur beschreibt die Eigenschaften und den
> Namen von jedem Datum. Anhand dessen kann ich in den Methoden auf die
> Behandlung der entsprechenden Typen verzweigen.

Was Du da schreibst, hört sich aber so gar nicht nach OO an.

von Matthias (Gast)


Lesenswert?

Ich nehm auch OO

von NichtWichtig (Gast)


Lesenswert?

Matthias schrieb:
> Hallo,
>
> ich hab in einer GUI 6 TabSheets auf denen Frames liegen. Diese sind
> alle sehr ähnlich, d.h. die Datenverarbeitung ist immer gleich nur die
> Variablentypen, die Namen der Variablen und die Anzahl sind
> unterschiedlich.
> Gibt es eine elegante Möglichkeit für eine Basisklasse, um unnötige
> Tipparbeit und Copy/Paste Fehler zu vermeiden?

https://de.wikipedia.org/wiki/Template_(C%2B%2B)

von M.K. B. (mkbit)


Lesenswert?

c-lover schrieb:
> https://en.cppreference.com/w/c/language/union

In C++ sollte man hier auf std::variant zurückgreifen. Damit ist auch 
sichergestellt, dass man nicht auf den falchen Type der Union zugreifen 
kann, dass wäre nämlich undefined behaviour.
Das setzt aber RTTI (Run time type information) voraus.

std::variant erlaubt es auch mit dem Visitorpattern auf die Element 
zuzugreifen.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.