was versteht man unter gutem Programmdesign?



  • Hallo,

    des Öfteren liest man hier Aussagen wie "schlechtes Programmdesign" oder "allgemein schrecklicher Code", wenn Fragende ihren Beispielcode posten. Mich würde interessieren, wie "gutes" Design aussehen würde, was sagen die Experten hier, die das ja öfters bemängeln(Wutz, Sepp, Dirk)?

    Oder ist "gutes" Design einfach Erfahrung, bzw. eine große Anzahl ungeschriebener Gesetze wie "verwende keine globalen Variablen" "kein Goto" usw?

    Wie kann ich mir gutes Design aneignen?

    Grüße



  • Schlechtes bzw. gutes Programmdesign ist nicht abhängig von der Programmiersprache sondern von der Erfahrung, der Auffassungsgabe und dem Abstraktionsvermögen des Programmierers.

    Aber C ist (leider) oftmals als Werkzeug missbraucht worden, wenn Dilettanten beweisen wollten, irgendwas begriffen zu haben oder gar anderen Leuten was erklären zu wollen.
    Deppenhafte Aussagen wie
    `"läuft doch"

    "compiliert doch"`
    desavouieren solche Leute.

    Ich werde hier jetzt nicht kostenlos und komprimiert eine Lektion für gutes Programmdesign anbieten, nur ein paar Stichworte
    - zuerst kommt das Daten-Design, dann das Programm-Design
    - OOP Ansatz (geht natürlich auch in C)
    - Top-Down (für neuen Code, bei Refactoring eher Bottom-Up)
    - möglichst viel den Compiler erledigen lassen (der warnt ggf. und verrechnet sich nie!), d.h. möglichst wenig Laufzeit-Abhängigkeiten
    - wie überhaupt: möglichst wenig Abhängigkeiten zulassen, d.h. Funktionen sollen immer möglichst wenig/gar keine Vor/Randbedingungen haben (z.B. hat strncpy ggü. strcpy mehr Abhängigkeiten, deshalb weg mit dem Mist)
    - Standard-Funktionen benutzen
    - wenn die nicht reichen, dann andere Standards (POSIX) oder wenigstens gut abgehangene Bibliotheken anstatt eigenem Rumgefrickel benutzen (das setzt natürlich immer (eine u.U. ausgiebige) Recherche voraus)
    - keinen Fachbüchern/autoren und den dortigen "Tipps" blind vertrauen, immer kritisch bleiben:
    Tim Hentenaar's Blog
    - das gilt auch für andere "Ratgeber", z.B. halte MISRA " don't use malloc " für Schrott, wie ich skeptisch ggü. allen pauschalisierenden "Ratgebern" bin



  • Zuschauer schrieb:

    Wie kann ich mir gutes Design aneignen?

    wenn du c-coder bist dann lass dich nicht zur nutzung von c++ verführen. das ist die erste regel.



  • n2016 schrieb:

    Zuschauer schrieb:

    Wie kann ich mir gutes Design aneignen?

    wenn du c-coder bist dann lass dich nicht zur nutzung von c++ verführen. das ist die erste regel.

    Wieso denn das?



  • Zuschauer schrieb:

    Oder ist "gutes" Design einfach Erfahrung, bzw. eine große Anzahl ungeschriebener Gesetze wie "verwende keine globalen Variablen" "kein Goto" usw?

    wie kommst du darauf, dass du keine globalen variablen und kein goto verwenden sollst?

    ansonsten besteht gutes design aus sinnvollen und klar verständlichen namen für variablen, Klassen usw, eingerücktem Code und sinnvollen Kommentaren, die es einem ermöglichen, innerhalb von Sekunden zu verstehen, was welcher programmteil macht.



  • abseits von µC sind doch globale Variablen schlechter Stil und goto erst recht, ist das nicht das Erste was man bei C lernt?



  • doch das lernt man, weil die fehleranfälligkeit beim unbedachten umgang mit goto und globalen variablen sehr hoch ist, aber nicht vom goto und von den globalen variablen kommt, sondern am programmierer liegt.

    aber wenn du z.b. threads hast und sperrvariablen setzen willst, warum solltest du dann keine globalen variablen verwenden? ist doch das einfachste. oder du programmierst dir monopoly und die anderen spieler müssen wissen, wie viel geld jeder hat. warum aufwand betreiben, wenn sowieso jeder darauf zugreifen kann?

    bei goto hast du eben den komfort, unkompliziert an eine programmstelle zu springen, ohne zig abfragen durchführen zu müssen. wenn dir also auffällt, dass du sonst viel schreibarbeit bekommst (klassisches beispiel: ganz viele if-else-anweisungen ineinander und du musst da raus), dann benutz goto.



  • Schwachsinn.
    Hört nicht auf den Mann.



  • abseits von µC sind doch globale Variablen schlechter Stil und goto erst recht

    Es gibt in jeder Programmiersprache Techniken, die "problembehaftet" sind.
    Goto's und gloabale Variablen gehören sicher dazu ....

    Aber nur wenn man was zu 100% eliminieren kann, es also für jede Situation eine bessere Lösung existiert, kann man eine Technik auch wirklich meiden ^^

    bei goto's geht das ganz gut bei diversen Programmiersprachen zum beispiel ... aka gotos im Code = schlechter Code.

    bei goto hast du eben den komfort, unkompliziert an eine programmstelle zu springen

    Oder man schaut sich sein design eine Stufe hoeher noch mal an ^^
    Oft ! ist ein Goto gar ned so sehr ein problem, es macht den Code nicht so viel schwerer nachvollziehbar und vereinfacht aufn 1. blick Dinge ...
    Aber wenn man einmal mit Goto's angefangen hat ...
    Und es geht meist auch besser ohne Goto's, nur ist da das drüberliegende Design schon Problematisch / suboptimal ... und das zu korrigieren macht mehr Arbeit ...
    Um zig verschachtelte bedingungsbläcke zu vermeiden, gibts andere Techniken z.b.

    Bei globalen variablen möchte ich das auch mal sehen ^^
    IMHO globale Variablen lassen sich ab und an nicht vermeiden, ohne andere problembehaftete Dinge zu tun. Aber in diversen programmiersprachen lassen sich globale variablen super verstecken, aka salonfähig machen ^^

    Mich würde interessieren, wie "gutes" Design aussehen würde,

    Kann man eigentlich mit wenigen Stichpunkten schnell beschreiben, aber im Detail ergeben sich dann ne ganze Menge SubPropleme ....
    - Verständlichkeit
    - Wiederverwendbarkeit
    - Sich an technische Vorgaben der Programmiersprache / verwendeten Libs halten

    Alle Punkte die einen immer um die Ohren geworfen werden, lassen sich da zuordnen ^^

    Und in der Praxis gibts kaum 100% einwandfreien code ....
    Programmierer schreiben im normalen Alltag keine Lehrbücher sondern praktische Lösungen. Das heisst, Zeitdruck !
    Und zu einem grossteil sind Anwendungen gewachsen. Das heisst am anfang gabs ne "Dirty" Lösung, ne Demo, nen script ...
    Viele Anwendungen fangen mit "Tools" Scripts ... etc an, die Techniker mit kaum Programmiererfahrung mal fix "hingezaubert" haben. Durch Verbreitung ensteht dann erst einmal der Bedarf an so einem Tool ...
    Und man soll plötzlich was solonfähiges draus machen, mit features, die keiner vorher genau beschreiben kann, sondern immer nur hinterher sagen, das so wie es implementiert wurde, nicht gemeint war ^^
    Also berabeitet man oft immer nur die schlimmsten dinge ....

    Ciao ...



  • naja ich kann mich nicht daran erinnern gesagt zu haben, dass schleifen, verzeigungen und funktionsaufrufe schwachsinn sind und nur noch goto verwendet werden sollte, und genauso wenig habe ich gesagt, dass man sämtliche im programm vorkommenden variablen global anlegen soll.
    klar vermeiden kann mans immer, ist manchmal halt aufwändiger und man muss aufpassen, was man da macht, aber wenns komplett überflüssig wäre, hätte man es aus der sprache entfernt.

    wobei das mal ne super aufgabe für nen wettbewerb o.ä. wäre, ein programm nur mit goto und einer minimalen anzahl globaler variablen / arrays zu realisieren. 😃



  • naja ich kann mich nicht daran erinnern gesagt zu haben, dass schleifen, verzeigungen und funktionsaufrufe schwachsinn sind und nur noch goto verwendet werden sollte

    Nein, aber es liest sich wie "naja ein Goto, solange der Code ned davon strotzt ist doch legitim" -> aka 1 oder 2 goto's = noch gutes Design 🙂
    Das wollt ich nur bissi korrigieren 🙂
    Und es gibt noch viel mehr üble Dinge die in Programmiersprachen drinne sind, grad in C/C++ die man nur wegen code(abwärts)-kompatiblitaet ned abschaltet.

    Wie groß wär die acceptance eines neuen C-Compilers, wenn der die linux kernel ned mehr übersetzen könnte ...

    Ciao ...



  • Kommt drauf an, wofür man die ein, zwei goto verwendet. Eine Schleife ist vom maschinencode her ja nichts anderes, als goto, warum dann also goto verwenden?

    Wenn man dieses ganze "gefährliche Zeugs" sowieso doof findet, kann man ja auch Java benutzen, ist zwar ohne ende langsam, aber dafür ist alles abgesichert.



  • Benutz kein goto und gut ist. Gibt außer schlechter RAII-Nachahmung keinen Grund dafür.



  • HansKlaus schrieb:

    aber wenn du z.b. threads hast und sperrvariablen setzen willst, warum solltest du dann keine globalen variablen verwenden? ist doch das einfachste.
    ...
    klar vermeiden kann mans immer, ist manchmal halt aufwändiger und man muss aufpassen, was man da macht, aber wenns komplett überflüssig wäre, hätte man es aus der sprache entfernt.

    Hör auf mit deinem naiv dümmlichen Laiengequatsche. Du hast keine Ahnung wovon du redest. Deine Annahmen warum etwas so ist wie es ist, sind Schwachsinn.
    Halt einfach die Klappe und trolle dich dahin zurück, woher du kommst.

    HansKlaus schrieb:

    Wenn man dieses ganze "gefährliche Zeugs" sowieso doof findet, kann man ja auch Java benutzen, ist zwar ohne ende langsam, aber dafür ist alles abgesichert.

    lol
    "In Java ist alles abgesichert."
    Von C hast du keine Ahnung und von Java auch nicht.
    Du hast keine Ahnung wovon du redest.
    Halt einfach die Klappe und trolle dich dahin zurück, woher du kommst.



  • HansKlaus schrieb:

    Wenn man dieses ganze "gefährliche Zeugs" sowieso doof findet, kann man ja auch Java benutzen, ist zwar ohne ende langsam, aber dafür ist alles abgesichert.

    Langsam ist relativ.
    Es gibt sogar Hardware-Emulatoren in Java und Java-Bytecode-Prozessoren.



  • Wutz schrieb:

    "In Java ist alles abgesichert."
    Von C hast du keine Ahnung und von Java auch nicht.
    Du hast keine Ahnung wovon du redest.
    Halt einfach die Klappe und trolle dich dahin zurück, woher du kommst.

    naja in java kannst du nicht mal eben so daten irgendwo hinschreiben, du hast keine zeiger und keinen zugriff auf die hardware, jedenfalls nicht so, wie du ihn bei c hast bzw. haben könntest. selbst für globale variablen musst du dir erstmal ein objekt erstellen. für mich ist das "alles schön abgesichert".
    hat natürlich für den allgemeinen gebrauch sicherlich seine vorteile, da die fehleranfälligkeit niedriger istt, ändert aber nichts daran.

    Mirek schrieb:

    Langsam ist relativ.
    Es gibt sogar Hardware-Emulatoren in Java und Java-Bytecode-Prozessoren.

    sicherlich, ist aber trotzdem nur "fast so schnell" wie c++. es reicht in den meisten fällen ja auch, aber manchmal kommt es darauf an, ob eine anweisung 6 takte braucht, oder nur 3.



  • Dass Java eine lahme Krücke ist, ist natürlich nicht mehr richtig, manchmal kann es hinsichtlich der Ausführungsgeschwindigkeit (nicht vergessen, Programmiersprachen haben keine Geschwindigkeit....) schon mit der von C++ mithalten, besonders wegen des Jit und Hotspot Gedöns.
    Mir ist Java trotzdem nicht geheuer...


  • Mod

    @HansKlaus: Wutz drückt es vielleicht nicht sehr höflich aus, aber hat schon Recht, dass das was du hier über Sprachkonzepte in C und Java zum Besten gibst ziemliches Halbwissen ist. Du verzettelst dich mit jedem Beitrag immer mehr.



  • HansKlaus schrieb:

    sicherlich, ist aber trotzdem nur "fast so schnell" wie c++. es reicht in den meisten fällen ja auch, aber manchmal kommt es darauf an, ob eine anweisung 6 takte braucht, oder nur 3.

    Darauf hast du mit C auch keinen Einfluss. Zum Glück sind die Zeiten, in denen der Programmierer Taktzyklen zählen durfte, lange vorbei.

    Und letztlich gilt immer noch: ein performanter Algorithmus in einer "lahmen Sprache", schlägt immer sein unperformantes, dilettantisch dahingefrickeltes Gegenstück in C.



  • Öhem,

    worum geht's eigentlich? Man kann auch unter strikter Einhaltung der MISRA- Regeln ziemlich obfuskativen Schrott schreiben, genauso kann eine Verwendung von goto Licht ins Dickicht bringen.
    In Ermangelung von Exceptions bleibt in C ja nicht viel anderes. Ein goto auf ein Label cleanup:, das (hoffentlich) alle Ressourcen zurückgibt, ist auf jeden Fall übersichtlicher, als alle Steuerstrukturen einzeln aufzulösen.
    Technisch passiert ja auch nichts anderes als ein gezielter Verwurf des Returnstacks. Beim break passiert das gleiche, halt nur mit dem obersten Element. switch-case z.B. würde sonst nur begrenzt Sinn machen.

    Unter "gut" verstehe ich hauptsächlich "les- und nachvollziehbar", mache das nicht daran aus, ob da ein goto drinsteht.

    Los, steinigt mich! :p


Anmelden zum Antworten