fat-lobyte hat geschrieben:Xin hat geschrieben:Ich stehe dem Konzept "Exceptions" extrem kritisch gegenüber
Das ist bekannt

Dennoch wäre es fair, wenn du deine Meinung als solche deklarierst und somit auch andere zulässt.
Habe ich das nicht, wenn ich schreibe: „ICH stehe dem Konzept Exceptions extrem skeptisch gegenüber“ oder gibt es eine hier Zensur, wenn Du oder Kerli sich zu Exceptions äußern?
Ich finde, das ist fair genug.
fat-lobyte hat geschrieben:In der 3. inneren Schleife in einem Algorithmus der gigantische Daten verarbeitet - wie soll ich sagen - selber Schuld wer da zu exceptions greift.
Nicht nur throw kostet Zeit - auch try kostet, auch wenn es so unschuldig aussieht und eigentlich ja auch nichts tut, um den Algorithmus weiter zu bringen.
Und in einer Umgebung, die Exceptions als Normal akzeptiert, ist es nicht unwahrscheinlich, dass die 3. innere Schleife eine Funktion wirft, die try verwendet.
fat-lobyte hat geschrieben:xin hat geschrieben:Und ich garantiere dafür, dass mein Code sauberer und performanter läuft als jeder Exception-Code, der nicht zu "Lehrzwecken" dem Idealbild nach entwickelt wurde.
Nehmen wir mal an das stimmt: wer weiß wie der Code mit Exceptions ausshen würde? Vielleicht liegt das nämlich nur daran dass du gut programmieren kannst, nicht daran dass Exceptions von Grunde auf falsch sind.
Wem hilft es, wenn ich gut mit oder ohne Exceptions programmieren kann und andere mit oder ohne Exceptions schlecht programmieren?
Wer mit Exceptions Mist baut, verkompliziert die Angelegenheit meist massiv, weil ein Programm mit einer gefangene Exception weiterläuft, aber invalide Objekte hinterlässt. Wenn es dann kracht, ist oftmals nicht mehr sinnvoll nachzuvollziehen, wie das invalide Objekte entstanden ist.
fat-lobyte hat geschrieben:So wie ich das sehe hast du in deinem Leben schon zuviel schlechten Code gesehen. Das ist bedauerlich, und ich kann durchaus deine Frustration mit Exceptions verstehen.
Aber deine Argumentation sieht für mich so aus: "Man kann viel falsch machen, deswegen sollte mans gleich lassen.“.
Nein - im Gegenteil - ich finde Exceptions sogar gut - Wenn man sie in Ausnahmen benutzt. Die einzige für mich wirklich grundsätzlich legitimierte Ausnahme ist ein try...catch in main. Alles andere ist eigentlich ein Regelfall.
fat-lobyte hat geschrieben:Ich finde anstatt Exceptions zu verteufeln solltest du darauf hinweisen wie man sie richtig verwendet. Es gibt nämlich eben ein paar Dinge die man beachten muss:
1) Keine Exceptions in Destruktoren.
2) catch(...) ist verboten.
3) catch(const std::runtime_exception&) ist verboten.
4) Exceptions sind Sparsam einzusetzen, und zwar nur in Ausnahmefällen, wie der Name schon sagt.
Alleine diese Regeln werden regelmäßig verletzt - besonders catch(...) ist während der Entwicklung sehr verlockend, und wenn’s funktioniert, dann funktioniert es ja. Und dann bleibt das catch(...) stehen oder wird vergessen.
Das passiert auch professionellen Entwicklern, denn da wo ich das hassen gelernt habe, wurde durchaus vergleichsweise sehr professionell gearbeitet. Und das meine positiv. Trotzdem ist Zeitdruck in der Realität nach dem Studium sehr präsent und in einem Entwicklungsteam reicht eine Person, die eben eine andere Meinung teilt und der das dann anders macht. Und die ist Regelfall mehrfach vorhanden.
Aus genau dem Grund bin ich von dem Konzept nicht überzeugt.
Gravierende Fehler können durch einen einzelnen verschleppt werden, damit fehlt die Zuständigkeit. Es entsteht eine "Verkettung unglücklicher Umstände". Diese unglücklichen Umstände folgen allerdings einer Regel, die durch den Gebrauch von Exceptions vorgegeben wird.
Und das ist der Punkt, an dem das Konzept "Exceptions" hakt. Der Verlauf der Verwendung führt immer wieder zu einem ganz spezifischen, das Produkt im höchsten Maße gefährdenden Design-Fehler.
fat-lobyte hat geschrieben:5) Wenn man mit der Exception nichts anzufangen weiß, dann fängt man sie auch nicht auf.
Was man nicht bestimmen kann, weil eine Ableitung einer Exceptions, die man fängt, sich eben auch hier verfängt und behandelt wird - wie auch immer.
Werden Exceptions nicht gefangen, steigt das Programm aus. Dann hätte man es auch gleich explodieren lassen. Die Meldung "Eine Exception ist aufgetreten, alle Daten sind verloren" mit "Okay" zu quittieren macht mich nicht glücklicher, denn es ist eben nicht "Okay".
Und schonmal gar nicht will ich dem Arsch von Programmierer meine Absolution mit "Okay" erteilen, der soeben meine Arbeit vernichtet hat, weil er scheiße Programmiert hat. Ich will dem Typen den Hals umdrehen, okay?
fat-lobyte hat geschrieben:6) Nur ein Exception-Typ für einen Fehler. Diagnostikinformationen einbauen!
Algorithmen machen keine Fehler. Fehlende Dateien muss man berücksichtigen. Ich sehe keinen Grund, Exceptions zu werfen. Ausnahmen sind unbehandelte Code-Pfade, die ich der aufrufenden Funktion auf's Auge drücke.
Wenn der Fehler "Division durch Null" vorbeifliegt, dann weiß der Catch-Block nicht, wer diesen Fehler geworfen hat. Er fliegt halt hier vorbei. Diese Information ist verloren. Wie soll der Catch-Block reagieren? Insbesondere, wenn diese Exception von einem Programmteil geworfen wird, der nach dem Catch-Block implementiert wurde, der Catch-Block also diese Möglichkeit gar nicht berücksichtigen kann.
Der Catch-Block wird sich drum kümmern - aber niemand kann sagen, ob danach ein valides oder invalides Objekt zurückbleibt.
fat-lobyte hat geschrieben:7) ... (Bitte weitere Punkte anführen)
Benutze keine Exceptions, dann kannst Du die zuvor genannten Regeln vergessen. Je weniger Regeln Du beachten musst, desto weniger Regeln kannst Du verletzen.
fat-lobyte hat geschrieben:
- Ich möchte nämlich, wenn ich ein Objekt anlege, dass dieses Objekt nach vollendetem Konstruktoraufruf gültig ist. Ich brauche keine "Hängenden" Objekte die ich erst noch mit object.isValid() und object.getErrorCode(), object.getErrorMessage() bearbeiten.
Ich auch nicht. Deswegen ist mir die C++-Semantik von new auch zuwider und wird in Genesys so nicht eingesetzt. Dort bekommst Du vielleicht ein Objekt, bevor Du es nutzen darfst,
musst Du den Codepfad in zwei Möglichkeiten teilen: Du hast ein valides Objekt - oder Du hast kein Objekt.
fat-lobyte hat geschrieben: - Ich möchtet nicht bei jeder operation bei der Fehler auftreten den Fehler abfangen, verarbeiten und weiterreichen. Oft sind die Fehlerquellen die gleichen, und dann will ich nicht jedes mal das gleiche abfragen:
Die Fehlerquelle mag die gleiche sein, aber vielleicht an anderer Stelle im Code.
Datei nicht gefunden... okay, kann behoben werden.
Der Fehler kann an x-Stellen auftreten. Zwischen diesen Stellen können bereits Handlungen Objekte verändert haben und in einem invaliden Übergangsstatus hinterlassen haben. Muss man sich jetzt um diese Zombies kümmern oder nicht?
Wie oft können im Code Dateien nicht gefunden werden und wird dieser Fehler behandlet? Wie oft kann die Exception geworfen werden. Das ergibt eine Multiplikation. Im Worst-Cast musst Du pro Catch alle throws dieser Exception gesondert bearbeiten. Die Idee Code zu sparen ist löblich, faktisch trennt man den Fehler vom Algorithmus, muss aber bei der Fehlerbehandlung aber an vollkommen anderer Stelle erst wieder herausfinden, wie man auf die fehlerhafte Stelle reagieren muss. Dass kann auch alles in der Exception beschrieben stehen, wie Du es Deiner 6. Regel beschrieben hast. Aber wenn ich da alle Informationen zusammentrage, wie ich den Fehler behebe - wieso behebe ich nicht einfach den Fehler, sondern lasse das jeweils die Funktionen machen, die mich gerufen haben - und das können ja beliebig viele sein? Spart das Code?
fat-lobyte hat geschrieben:Eine Exception heißt für mich: Achtung! Da ist was gewaltig faul. Zustand wiederherstellen oder Programm beenden. Knallt eine Exception durch, weiß ich dass dort ein Fehler ist. Eine halbe Stunde später einen ungültigen Zeiger zu referenzieren, der "hoffentlich" NULL ist ist weniger hilfreich.
Exceptions werden zu häufig als Regelfall benutzt oder während der Entwicklung übergangen, denn wenn der Algorithmus fertig ist, dann wird die Exception ja nicht
mehr auftreten.
fat-lobyte hat geschrieben:Außerdem finde ich ja virtuelle Methoden genauso Schlimm. Man weiß ja nie welche aufgerufen wird. Und Mehrfachvererbung sowieso, ich meine da blickt ja keiner mehr durch. Oder Templates, das muss ja ein riesiger Overhead sein damit das generisch Funktioniert und die Fehlermeldungen sind unlesbar. Und überhaupt, Operatorüberladung ist ja das schlimmste, da kann man ja den Datentyp nicht erkennen. Und die IOStreams, die std::string's, die std::vector<>s, die Algorithmen, alles Hexenwerk. Verbrennen sollte man es.
Ich habe kein Problem damit kritische Konzepte auch wieder aus Sprachen zu verbannen und als Irrweg zu kennzeichnen. Exceptions wäre für mich ein solches Konzept.
Ich habe mir Exceptions angesehen und direkt die Probleme gesehen und sie später im Beruf in genau der vorhergesagten Dramatik wiedergefunden - produziert von ausgebildeten Informatikern. Exceptions sind allgemein anerkannter und legitimierter Spaghetticode im Fehlerfall. Um Redundanzen zu vermeiden (gleicher Fehler, eine Behandlung) gibt es bessere Konzepte (Funktionen), die die Information, wo der Fehler aufgetreten ist, ebenfalls verwalten können (Parameter).
Es ist genausowenig perfekt, aber es ist unkomplizierter, denn es funktioniert ohne quer durch den Stack zu springen. Fehler sind im Code benannt und aufgeführt, statt "Fehler" zu brüllen und dann zu gucken, ob sich irgendeine der Funktionen auf dem Stack vielleicht dafür interessiert.
Das ist meine Meinung und von mir gemachte Erfahrung.