Seite 1 von 2
Re: Eure Erfahrungen mit Fehlerbehandlung
Verfasst: 01.06.2010, 11:42
von Alexander Kornrumpf
Krishty: Alles klar und richtig. Natürlich sollte man das System in einem möglichst gesunden Zustand zurück lassen und an Daten retten was zu retten ist. Das würde ich nie bestreiten. Worum es mir geht, ist dass man vermutlich auch nicht viel mehr tun kann als das. Wenn einem nichts anderes zur Behandlung des Fehlers mehr einfällt, als eine Dokumentation seines Auftretens ist das meinem Verständnis nach keine echte Behandlung, es löst ja das Problem nicht.
Wenn die Anwendung trotzdem weiter laufen kann, war das Problem ja per Definition nicht ganz so schlimm, wozu dann die Aufregung.
Muss die Anwendung dagegen beendet werden ist ein kontrollierter "Nothalt" aus Sicht des Benutzers kaum von einem Absturz zu unterscheiden. In beiden Fällen klickt er X und startet neu, wie du schon so richtig festgestellt hast. Was soll er auch anderes tun?
Thomas:
Aber hier geht es doch um den "Oh mein Gott, dazu hätte es nie kommen dürfen." Fall. Ich habe doch in meinem Beitrag an zwei Stellen geschrieben dass ich mich nicht auf die Situation beziehe, in dem jemamd weiter außen das Problem lösen kann. Überspitzt formuliert: Weiter außen als der Mensch vor dem Rechner geht es nicht. Wenn selbst der nichts mehr tun kann, ist die Sache eben in die Hose gegangen. Was dann bleibt ist vielleicht Schadensbegrenzung aber Fehlerbehandlung wäre für mich ein Euphemismus.
Re: Eure Erfahrungen mit Fehlerbehandlung
Verfasst: 01.06.2010, 11:47
von Krishty
Alexander Kornrumpf hat geschrieben:Wenn die Anwendung trotzdem weiter laufen kann, war das Problem ja per Definition nicht ganz so schlimm, wozu dann die Aufregung.
Dafür sind dann die
catch-Blöcke da. Die entscheiden, ob ein Fehler recoverable ist oder ob man die Ausnahme weiterreicht. Für den Benutzer ist der Unterschied nicht sichtbar, aber dem Entwickler spart es viel weil der Code einfacher wird und sich alles im Fall einer Exception automatisch richtig verhält, nämlich genau so, als würde der Code normal beendet werden.
Re: Eure Erfahrungen mit Fehlerbehandlung
Verfasst: 01.06.2010, 12:05
von Schrompf
Ok, da reden wir vom gleichen Fall: wenn das Programm nicht weiterlaufen kann, dann sind die Resourcen auch Schnuppe. Da kann einem RAII auch gepflegt den Buckel runterrutschen. Für den Fall würde ich dann einen globalen Ärger-Handler beim System anmelden und das Log vollpumpen. Funktioniert bei uns bisher ziemlich gut, auch wenn wir doch ziemliche Probleme haben, selbst die langjährigen Teammitglieder daran zu gewöhnen, dass sie das verdammte Log mit ihren Fehlerberichten mitschicken. So ein aufpoppendes Fenster mit EMail-Option wäre da ne tolle Sache.
Re: Eure Erfahrungen mit Fehlerbehandlung
Verfasst: 01.06.2010, 12:10
von Alexander Kornrumpf
Krishty hat geschrieben:Alexander Kornrumpf hat geschrieben:Wenn die Anwendung trotzdem weiter laufen kann, war das Problem ja per Definition nicht ganz so schlimm, wozu dann die Aufregung.
Dafür sind dann die
catch-Blöcke da. Die entscheiden, ob ein Fehler recoverable ist oder ob man die Ausnahme weiterreicht. Für den Benutzer ist der Unterschied nicht sichtbar, aber dem Entwickler spart es viel weil der Code einfacher wird und sich alles im Fall einer Exception automatisch richtig verhält, nämlich genau so, als würde der Code normal beendet werden.
Aber dafür hast du diesen Thread doch nicht gestartet, oder?
Re: Eure Erfahrungen mit Fehlerbehandlung
Verfasst: 01.06.2010, 13:12
von kimmi
Das ist so eine Sache mit dem richtigen Verhalten. ich habe mal an einer Modellierungssoftware für Simulationen mitgearbeitet und dort hatten wir ein ähnliches Problem zu lösen: wie geht man mit Fehlern um, die die Datenbasis ( die Out-of-Core gehalten wurde und mehrere Gigs umfassen konnte bzw. kann ) eventuell in einen nicht definierten Zustand bringen kann. Wir haben uns dann für die Abflug-Variante entschieden, damit man nicht irgendwann durch Datenirritationen verfälschte Berechnungsergebnisse erhält, die dann zu falschen Konstruktionen führen.
Allerdings haben wir das mit Error-Eskalations-Levels beschrieben ( Fatal, normaler Error, Warnung, Info und Debuginfo ). Fatale Fehler weisen auf wirkliche Bugs hin, Errors und Warnungen weisen auf Anwendungsfehler hin. Hat man beispielsweise vor, eine Schraube zu modellieren und die Kontaktfläche zwischen Schraube und Gewinde vergessen, ist das kein Programmfehler. Ist der Kontakt-Algorithmus buggy, hilft auch keine Nutzeraktion mehr. Das musst man nun konsequent im Code vorsehen, damit das korrekt umgesetzt wird. Und natürlich schlug dann die Faulheit zu und Entwickler fingen an, Errors wie "Var i ist gleich 0" als Benutzerfehler zu definieren, was zu gewissen Irritationen von Seiten der Anwender führte :). Gegen sowas hilft dann aber recht zuverlässig Code-Lesungen.
Gruß Kimmi
Re: Eure Erfahrungen mit Fehlerbehandlung
Verfasst: 01.06.2010, 13:29
von Krishty
Alexander Kornrumpf hat geschrieben:Aber dafür hast du diesen Thread doch nicht gestartet, oder?
Krishty hat geschrieben:[…] nun vor der zweitgenannten Frage stehe, wie ich den Fehler dem User klarmache.
Mit der ersten Frage wollte ich nur ein bisschen Orientierung, wie die Fehlerbehandlungsmechanismen so verteilt sind … wenn ich verschiedene Webforen überfliege, werden da zu zwei Dritteln Return-Codes behandelt. Es hätte ja tatsächlich sein können, dass hier jemand sagt: Scheiß auf Return Codes oder Exceptions, wir liefern alles komplett ohne aus und es läuft. Dem galt mein Interesse.
Die Frage, in der ich wirklich Hilfe brauche, ist die, wie ich dem User den Fehler klarmache.
@kimmi: Das klingt wirklich gut. Wie wurden die einzelnen Fehlerarten mitgeteilt? „Abflug“ heißt, tatsächlich ohne Meldung geschlossen?
Re: Eure Erfahrungen mit Fehlerbehandlung
Verfasst: 01.06.2010, 13:54
von kimmi
Abflug heißt: Applikation stürzt ab. Mit Glück kriegt man noch einen Crashdump oder einen Callstack. So in der Form versuche ich das seitdem durchzuziehen. Klapt eigentlich ganz gut. Logs sind durch so etwas dann wirklichz nützlich, um den Punkt, an dem der Fehler aufgetreten ist ( Eingabefehler vom Benutzer oder wirklicher Programmfehler ) bis zu dem Punkt, wo das Programm gegebenenfalls abgeflogen ist, nachvollziehen zu können. Das ist halt viel aussagekräftiger als eine Messagebox mit "Ich bin dann mal weg!", auch für technisch nicht so versierte Benutzer.
Gruß Kimmi
Re: Eure Erfahrungen mit Fehlerbehandlung
Verfasst: 01.06.2010, 16:10
von Chromanoid
Ich denke es kommt auch ziemlich darauf an, wie eng man mit Kunden Kontakt hat, wie wichtig die fehlerfreiheit ist und um was für Produkte es sich handelt. Je nach dem muss man dann abwägen wieviel zeit man in die Fehlerbehandlung investieren möchte. Bei Software mit wenigen wichtigen Kunden, deren Kaufentscheidung besonders mit dem Support zu tun hat, sollte man natürlich den höchst möglichen Komfort für die Kunden und die reagierenden Entwickler/Supporter bieten.
Bei kleinen "unterbezahlten" Projekten, die im Rahmen von Werkverträgen ohne besondere Ansprüche auf gute Fehlerbehandlung stattfinden, kann man auch auf eine besonders benutzerfreundliche Fehlerbehandlung verzichten. Der Benutzer muss dann eben eine Logdatei aus einem Verzeichnis raussuchen und dem Entwickler selbst per Email zu schicken, um Hilfe zu bekommen. Fehlerfreie Software gibt es schließlich nicht wirklich und wenn nicht extra dafür bezahlt wird sollte man sich dafür auch nicht besonders viel Mühe geben (es sei denn man erhofft sich größere Folgeaufträge und ist bereit dafür auch kostenlos an der Fehlerbehandlung zu arbeiten). Ggf. kann man ja auch eine kleine Bibliothek dafür wiederbenutzen... (die entwickelt sich natürlich auch nicht einfach so ohne Kosten...).
Was jetzt genau höchsten Komfort bei Fehlerbehandlung bedeutet ist ja eigentlich schon gesagt worden... Man könnte das ganze vielleicht so nochmal aufdröseln:
Technische Fehler, die vom Benutzer eh nicht behoben/verstanden werden können sollten sich auch so darstellen und sich nur bei einem Knopfdruck auf "Technische Details" o.Ä. in voller Schönheit offenbaren. Eine Email-/Druckfunktion mit Screenshotmöglichkeit für solche Fehler mit entsprechenden Daten wie z.B. Stacktrace o.Ä. ist sicherlich sinnvoll.
Fehler die vom Benutzer behoben werden können, sollten immer mit entsprechenden Anweisungen gemeldet werden. Als Beispiel wäre da eine nicht beschreibbare Datei zu nennen, die von einem anderen Programm verwendet wird.
Auf jeden Fall sollten Fehler auch immer in eine Log-Datei geschrieben werden, die zur Not vom Supporter angefordert werden kann. Wichtig ist bei komfortabler Fehlerbehandlung natürlich auch die Möglichkeit nach einem Absturz die "letzte Sitzung" wieder herzustellen.
Bei Java ist die Fehlerbehandlung meiner Meinung nach ziemlich gut gelungen und schön in das Gesamtkonzept integriert. Man hat als Programmierer überall einen Logger zur Verfügung (mit mehreren Log-Levels), der bei Exceptions einen Stacktrace ausgeben kann und alles in beliebige Loghandler (z.b. email handler, text datei handler, konsolenhandler, dialogbox handler und html datei handler) schreibt. Die Handler muss man zwar teilweise selbst programmieren, aber das geht schnell von der Hand und man kann sie überall wiederverwenden...
http://java.sun.com/j2se/1.4.2/docs/api ... ndler.html Da es sich dabei nicht unbedingt um ein neues Konzept handelt sollte es das ganze natürlich auch in anderen Sprachen geben... Für die Leute die Stacktraces nicht benutzen, so sieht ein Java-Stacktrace aus :):
Code: Alles auswählen
java.lang.ArrayIndexOutOfBoundsException: 3
at example.common.TestTry.execute(Testtry.java:17)
at example.common.TestTry.main(Testtry.java:11)
Sehr praktisch, da Fehlerart und zeile im Code usw. angegeben wird. Gibts natürlich auch in C# und anderen "dynamischen" Sprachen :).
Re: Eure Erfahrungen mit Fehlerbehandlung
Verfasst: 01.06.2010, 16:34
von zwergmulch
Was ich bei Java aber manchmal sch****(*) finde, sind die "Checked Exceptions". Die sorgen dann meistens für folgenden Code, wenn man in eine Datei schreiben will:
Über den Sinn dessen kann man nun streiten... :twisted:
Edit: Komisch, egal wie viele Leerzeichen ich einfüge - am Ende sieht man davon nichts (in den Code-Tags).
Und Tabs gehen auch nicht - sollte man evt. mit (wie hieß das nochmal: xml-space oder so) verändern.
Re: Eure Erfahrungen mit Fehlerbehandlung
Verfasst: 01.06.2010, 16:43
von Chromanoid
mach mal [ code = java ]
mmh naja nen finally ist schon sinnvoll und den rest kannst du ja einfach von der methode werfen lassen...
Re: Eure Erfahrungen mit Fehlerbehandlung
Verfasst: 01.06.2010, 16:51
von zwergmulch
@code = java : Oh, schon besser... ;-) Danke.
Wenn der Benutzer nun an der Konsole (wahrscheinlich eher nicht) den Stacktrace sieht und das Programm abstürzt, hilft ihm das auch nicht so.
Catch kann man zwar weglassen, aber meistens führt das dazu das der Fehler "verschluckt" wird -
auch nicht das beste. So kann man wenigstens mit System.setErr () das in eine Log-Datei umleiten. Aber mir ging es um den allgemeinen Sinn von Checked Exceptions.
Re: Eure Erfahrungen mit Fehlerbehandlung
Verfasst: 01.06.2010, 16:59
von Chromanoid
naja ich finde checked exceptions eigentlich ziemlich gut, da wird man gezwungen sich mit den möglichen fehlern auseinander zu setzen. und wie gesagt, man kann die meisten fehler ja sonst euch einfach hochreichen und an einer übergeordneten stelle abfangen und dann gleich mehrere auf einen schlag.
Re: Eure Erfahrungen mit Fehlerbehandlung
Verfasst: 01.06.2010, 17:14
von Krishty
:shock: Das ist ja wirklich grausam … wird man zu Checked Exceptions gezwungen, wenn man bestimmte Objekte benutzt (in diesem Fall BufferedWriter) oder kann man sich aussuchen, die zu benutzen?
Ist das, um zu garantieren, dass Ressourcen freigegeben werden, falls Ausnahmen auftauchen? Wenn ja – ohne mal wieder auf Java fluchen zu wollen – in C++ wären das fünf saubere Zeilen … dann zwar ohne schicken Stack-Trace, aber … óÔ
Mein Java-Kurs dauerte nur ein Semester, darum sorry, falls die Fragen dumm sind …
Re: Eure Erfahrungen mit Fehlerbehandlung
Verfasst: 01.06.2010, 17:21
von Seraph
Krishty hat geschrieben:Seraph hat geschrieben:Wichtig ist denke ich, ihm die Wahl zu lassen, was er machen moechte.
Aber Call-Stacks, Exceptions überfordern User – vor allem, wenn sie unerwartet kommen. Und wenn dann noch Fenster zur Texteingabe daneben sind und mehrere Buttons, verfallen die meisten in Panik und drücken X. Ich habe jedenfalls mal gelesen, dass eine Wahl in solchen Fällen das Letzte ist, was ein User will oder braucht (und erst recht der Entwickler).
Wie ich schon schrieb, werden die sichtbaren Infos spaeter fuer den User eingeschraenkt. Solange es aber eine reine Entwicklungsversion ist, wird weiterhin ein Form mit allen verfuegbaren Infos ausgegeben. Und dem User die Wahl zu lassen bezog sich darauf, ob er es abschickt oder nicht. Weil ich habe auch schon Applikationen erlebt, die einfach ohne Nachfrage versuchen einen Error-Report zu versenden. Sprich der User hat die Moeglichkeit zwischen 'Send', 'Cancel' und der Moeglichkeitkeit zu beschreiben, was er denn gerade getan hat. Und ich denke nicht, dass es den User ueberfordern wird.
Re: Eure Erfahrungen mit Fehlerbehandlung
Verfasst: 01.06.2010, 17:27
von Chromanoid
man wird gezwungen, die dinger irgendwie zu behandeln. Sei es das ding weiter zu reichen (per throws in der methodendeklaration) oder per try/catch. Das gilt allerdings nur für nicht-runtime-exceptions (wie "datei wurde nicht gefunden", "auf dateisystem kann nicht zugegriffen werden", "zur datenbank konnte nicht verbunden werden"... o.ä.). man kann dafür getrost auf return errorcodes verzichten, was auch seine vorteile hat...
http://java.sun.com/docs/books/tutorial ... ntime.html
Re: Eure Erfahrungen mit Fehlerbehandlung
Verfasst: 01.06.2010, 18:22
von Krishty
Das ist echt ein dicker Hund … ich dachte bisher, dass Java irgendeine Form von RAII realisieren würde – hättet ihr mir das nicht
vor dem „Ist Java wirklich so schlecht?“-Thread zeigen können? :D
Nagut, weiter im Text:
Seraph hat geschrieben:Sprich der User hat die Moeglichkeit zwischen 'Send', 'Cancel' und der Moeglichkeitkeit zu beschreiben, was er denn gerade getan hat. Und ich denke nicht, dass es den User ueberfordern wird.
Ich halte immernoch dagegen. Ich versuche, irgendwelche Zahlen zu dem Thema zu finden, aber immer, wenn ich was mit „x“ eingebe, werden nur Pornos gelistet …
User lesen
nie etwas. Nicht, wenn sie entspannt sind, und erst recht nicht, wenn sie gerade wütend sind (wie eben nach einem Absturz). Ich glaube nicht, dass die Entscheidung über den Error-Report dem User von Vista
unbewusst entzogen wurde. Ich würde zumindest das x ausblenden und das „Send“ per default aktivieren, oder die Buttons zufällig vertauschen :)
Also gut: Ich denke, für alles vor dem RC-Status reicht es, wenn man bei kritischen Fehlern ein Log anzeigen lässt. (Wie man es
nicht machen sollte: einfach schließen und vorher die Zwischenablage mit der Fehlermeldung überschreiben, wie in S.T.A.L.K.E.R. … aber es gab ja zum Glück noch zwei andere Arten, auf die das abstürzen konnte :) ) Danach je nach Kundenkreis und Bezahlung entscheiden – bei Gamern und garnichts wird kein Fenster mit einer Verbeugung drin sein, aber sicher eine Dialogbox, sobald ich sicher bin, dass die sich auch jemand durchliest.
(Wie ist das eigentlich mit Windows Error Reporting? Wenn ich da Einsicht bekäme, käme ich auch ohne Dialogbox an die Abstürze, oder?)
Beim nächsten Start mit der Sitzung weitermachen, soweit möglich, ist gut. Erfordert manchmal mehr, manchmal weniger Logik. Aber falls der Status von vorher überhaupt erst zum Absturz geführt hat, ist es katastrophal … wieder User fragen?!
Achja, ich habe das Fail-Early vergessen (sorry, Alexander) …
… wie sich das einsetzen lässt, hängt stark vom Programmumfang und der Programmdynamik ab. Gehen wir von einem relativ kleinen, dialogbasierten Programm aus, ist es mit einigem Aufwand möglich, alle Ressourcen am Anfang zu sammeln – wenn die Ressourcen in Verzeichnissen gepackt sind, sogar relativ einfach (Checksumme).
Gehen wir aber von dem Umfang eines modernen Computerspiels (1 GiB +) aus, wird es happig, falls nicht zufällig eine Infrastruktur wie Steam bereit steht, die sowieso Buch über alle Ressourcen führt. Da könnte man vielleicht noch mit x64 beikommen – beim Programmstart das komplette Programmverzeichnis in den Speicher einblenden und verifizieren. Das wollte ich sowieso schon immer mal machen :)
Und
unmöglich ist es dann, wenn der größte Teil der Abstürze auf das Konto von kaputten Skripten geht – z.B. dass es immer crasht, wenn eine Spielfigur in eine bestimmte Situation kommt. Da ist man einfach machtlos und, je nach Größe der Spielwelt, auch ein kompletter Ast von Speicherpunkten verloren (als Negativbeispiel sei wieder S.T.A.L.K.E.R. mit den kontextabhängigsten Abstürzen dieses Jahrtausends genannt) … ich würde sagen, dass die meisten Games heute und in der Zukunft in die Richtung von 2) (zu groß) und 3) (zu dynamisch) gehen. Und für die kleine Basis der Ressourcen macht man es ja gewissermaßen eh schon, weil man die die ganze Laufzeit über benutzt.
Re: Eure Erfahrungen mit Fehlerbehandlung
Verfasst: 01.06.2010, 21:16
von eXile
Also meinerseits werden benutzt: Asserts, Logfiles und (was noch gar keiner nannte) eine Konsole. Damit meine ich so ein Teil, wie man es noch aus den guten, alten Zeiten von etwa Q3Test kennt. Wenn ein fataler Fehler auftritt, spring die Konsole auf die volle größe des Fensters, und zeigt als Text an … dass man in der Logdatei gucken soll :P. Sorry, ich war bisher zu faul, eigene Fehlermeldungen zu implementieren.
Exceptions verwende ich, je nach Projekt, manchmal sehr viel, und manchmal gar nicht. Das hängt auch sehr stark von den verwendeten Libraries ab, und wie feingranular ich die Exceptions fangen kann – bzw. ob es überhaupt sinnvolle Exceptions zum Abfangen gibt.
PS: Krishty, du sprichst mir mit deiner Kritik an diesem ganz speziellem Spiel vollkommen aus der Seele ;)
Re: Eure Erfahrungen mit Fehlerbehandlung
Verfasst: 02.06.2010, 00:08
von Seraph
Krishty hat geschrieben:Seraph hat geschrieben:Sprich der User hat die Moeglichkeit zwischen 'Send', 'Cancel' und der Moeglichkeitkeit zu beschreiben, was er denn gerade getan hat. Und ich denke nicht, dass es den User ueberfordern wird.
Ich halte immernoch dagegen. Ich versuche, irgendwelche Zahlen zu dem Thema zu finden, aber immer, wenn ich was mit „x“ eingebe, werden nur Pornos gelistet …
User lesen
nie etwas. Nicht, wenn sie entspannt sind, und erst recht nicht, wenn sie gerade wütend sind (wie eben nach einem Absturz). Ich glaube nicht, dass die Entscheidung über den Error-Report dem User von Vista
unbewusst entzogen wurde. Ich würde zumindest das x ausblenden und das „Send“ per default aktivieren, oder die Buttons zufällig vertauschen :)
Und ich bleibe dabei :P, ich finde es besser dem User die Auswahl zu geben, ob er etwas senden moechte oder nicht. Ich finde es auch rechtlich etwas bedenklich, etwas ohne das Einverstaendnis des Users Daten ins Netz zu senden, insbesondere wenn vielleicht noch mehr Daten als nur die reinen App-Daten versendet werden. Wenn man mir z.B. nicht die Wahl ueberlassen wuerde und ich haette noch die Chance dazu, wuerde ich wohl den Crash-Report killen statt auf 'Senden' zu klicken, schon allein aufgrund der Tatsache, dass es mir nicht freigestellt war. Aber wir koennen hier auch gern verschiedener Meinung bleiben, es sei denn Du findest eine Statistik, dass 95% aller Programme den User zwingen, das koennte mich u.U. ueberzeugen. :)
Re: Eure Erfahrungen mit Fehlerbehandlung
Verfasst: 02.06.2010, 00:46
von Krishty
Seraph hat geschrieben:Wenn man mir z.B. nicht die Wahl ueberlassen wuerde und ich haette noch die Chance dazu, wuerde ich wohl den Crash-Report killen statt auf 'Senden' zu klicken, schon allein aufgrund der Tatsache, dass es mir nicht freigestellt war. Aber wir koennen hier auch gern verschiedener Meinung bleiben, es sei denn Du findest eine Statistik, dass 95% aller Programme den User zwingen, das koennte mich u.U. ueberzeugen. :)
Okay, korrigier mich wenn ich fallsch liege, aber:
Seit Vista ist Error Reporting standardmäßig aktiviert. („Default settings: By default, error reporting is enabled on clients running Windows Vista.“) Jedes Mal, wenn eine Anwendung kracht, erzeugt Windows einen Dump (XXX.exe funktioniert nicht mehr — es wird nach einer Lösung gesucht — Informationen über das Problem werden gesammelt) und sendet ihn (möglicherweise zeitverzögert) an Microsoft.
Dort kann sich jeder, der dessen Programm zertifiziert ist, registrieren um die Dumps seines Programms einzusehen. Verhindern lässt sich das, indem der User in der Sekunde nach dem Absturz noch schnell auf Abbrechen klickt, die Funktion manuell abschaltet oder während der Windows-Instllation nicht die standardmäßigen Sicherheitsoptionen auswählt. Falls aus dem Web noch mehr Infos angefragt werden als ein simpler Dump, wird der User gefragt, ob dieses Mehr an Inforamtionen übermittelt werden soll.
Daher würde ich zwar nicht sagen, dass 95 % aller Programme ohne Nachfrage einen Fehlerreport senden, aber über 50 % der Abstürze mit steigender tendenz dürfte die Quote heute bestimmt schon liegen. Und in der Windows-Datenschutzerklärung steht drin, dass du einverstanden bist dass MS und den registrierten Partnern diese Infos übermittelt werden. (Dass diese Möglichkeit des Fern-Debugings wegen der Signierung und so für einen Hobbyprogrammierer out of touch ist, muss ich wohl nicht sagen.)
Wenn es einer besser weiß, bitte mit Quelle korrigieren. Habe nämlich Mühe, Material zum Thema zu finden.
Re: Eure Erfahrungen mit Fehlerbehandlung
Verfasst: 02.06.2010, 09:49
von Alexander Kornrumpf
Ich habe es nun deaktiviert, vor allem aus dem von Steffen genannten Grund, ich möchte gefragt werden. Wenn es die Option gäbe von "always send" auf "always ask" umzustellen, hätte ich vermutlich die gewählt. Auf die Schnelle habe ich das aber nicht finden können.
Aber nochmal zum Thema ich glaube nach dem ganzen hin und her, eigentlich sind es zwei Fragen:
Sollte der User informiert werden?
Hier würde ich sagen entweder:
mit einer Auswahl was er/sie tun kann um das Problem zu beheben. Windows versucht das an manchen Stellen. Meistens sind das die offensichtlichen Sachen a la "Stellen Sie sicher dass der Drucker auch wirklich eingeschaltet ist" aber ich behaupte mal dass das vielen Menschen hilft.
oder (wenn das nicht geht):
ähnlich wie Firefox mit einer höflichen "Sorry das hätte nicht passieren dürfen, wir versuchen alles damit sie beim Neustart an dieser Stelle fortfahren können" Meldung
jedoch nicht:
mit irgendwelchen Informationen, die der User sowieso nicht versteht, wie in Win98 "Schwerer Ausnahmefehler an Adresse 0xcdcdcdcd" wo alle immer gesagt haben "Wieso Ausnahme? Das passiert doch ständig."
Sollte der Entwickler informiert werden?
Da bin ich Steffens Meinung. Das sollte der User entscheiden. Ich gehe (Stichwort Kontexabhängige Fehler) davon aus dass man in den meisten Fällen relativ viel Kontext braucht um wirklich eine Diagnose stellen zu können und den ggf nicht hat. Deswegen bin ich nicht 100% überzeugt, dass dieses Reporting viel bringt. Vielleicht täusche ich mich aber auch.
Re: Eure Erfahrungen mit Fehlerbehandlung
Verfasst: 04.06.2010, 01:57
von dronus
Ich benutzt Java, vielleicht etwas speziell. Ich wandele fast alle Exceptions in RuntimeExceptions um, d.h. dass ich sie nicht catchen muss und die Anwendung aussteigt. So gibts sehr wenig fehlerbehandelnden Code und immer sehr präzise Meldungen.
In bekannt wackelig, aber unwichtigen Codeteilen (z.b. Soundengine, De-Luxe Rendereffekte) fange ich die Exceptions ab, wenn die Funktion ein Signal vom Hauptthread ist, sonst lass ich den Thread abstürzen, dann gibts eben keinen Sound.
Re: Eure Erfahrungen mit Fehlerbehandlung
Verfasst: 04.06.2010, 03:13
von Krishty
Alexander Kornrumpf hat geschrieben:mit einer Auswahl was er/sie tun kann um das Problem zu beheben. Windows versucht das an manchen Stellen. Meistens sind das die offensichtlichen Sachen a la "Stellen Sie sicher dass der Drucker auch wirklich eingeschaltet ist" aber ich behaupte mal dass das vielen Menschen hilft.
Es hilft sogar
enorm vielen. Das Problem ist nur, dass der Aufwand dafür riesig ist: Auf Code-Ebene haben wir nur mit Fehlern à la „Time-Out“ und „Zugriff verweigert“ zu tun. Die Fehlerbehandlung muss also um eine Kontextanalyse erweitert werden (Tritt ein Time-Out beim Ansteuern des Druckers auf? Dann ist der Drucker vielleicht nicht eingeschaltet), es müssen in bester Doku-Manier aussagekräftige Dialoge geschrieben, getestet und in alle Produktsprachen übersetzt werden – also ein kompletter Layer um den eigentlichen Code herum. Für Hobby-Spieleentwicklung ist das einfach zuviel des Guten (allein, die möglichen Fehlerursachen direkt im Quellcode zu listen verdoppelt die Dateilänge). Realistisch gesehen bleibt nicht viel mehr als Entschuldigungsfenster :(
Alexander Kornrumpf hat geschrieben:jedoch nicht:
mit irgendwelchen Informationen, die der User sowieso nicht versteht, wie in Win98 "Schwerer Ausnahmefehler an Adresse 0xcdcdcdcd" wo alle immer gesagt haben "Wieso Ausnahme? Das passiert doch ständig."
Zu eXiles Vergnügen wieder S.T.A.L.K.E.R. (sieben Buttons, vier Textfelder, aber nicht der leiseste Hauch einer Ursache):
Alexander Kornrumpf hat geschrieben:Sollte der Entwickler informiert werden?
Da bin ich Steffens Meinung. Das sollte der User entscheiden. Ich gehe (Stichwort Kontexabhängige Fehler) davon aus dass man in den meisten Fällen relativ viel Kontext braucht um wirklich eine Diagnose stellen zu können und den ggf nicht hat. Deswegen bin ich nicht 100% überzeugt, dass dieses Reporting viel bringt. Vielleicht täusche ich mich aber auch.
Ja,
sicher sind nicht alle Reports hilfreich. Bei Microsoft ist der Tenor, dass 80 % der eingehenden Abstürze von 20 % der Bugs ausgelöst werden und dass schon die schiere Masse hilft, diese schwächsten Glieder sehr schnell zu finden. Ohne Zahlen können wir aber alle nur mutmaßen (und entfernen uns auch mal wieder von der Spieleentwicklung).
dronus hat geschrieben:So gibts sehr wenig fehlerbehandelnden Code und immer sehr präzise Meldungen.
Das ist die optimale Mischung … bei mir wird an Ort und Stelle jedes Detail ins Log geschrieben. Die Exception dienen dann nurnoch dazu, das Stack-Unwinding auszulösen und RAII übernimmt den Rest, bis der
catch-Block im Einstiegspunkt erreicht wird.
dronus hat geschrieben:In bekannt wackelig, aber unwichtigen Codeteilen (z.b. Soundengine, De-Luxe Rendereffekte) fange ich die Exceptions ab, wenn die Funktion ein Signal vom Hauptthread ist, sonst lass ich den Thread abstürzen, dann gibts eben keinen Sound.
Ich habe weder wackeligen noch unwichtigen Code.
Re: Eure Erfahrungen mit Fehlerbehandlung
Verfasst: 04.06.2010, 18:42
von ponx
Schrompf hat geschrieben: Return Codes sind für alle Funktionen, bei denen ein Scheitern ein im normalen Ablauf zu erwartendes Ergebnis ist. Z.B. so Sachen wie "gib mir das XYZ zu diesem Namen" - da kommt halt ein Null-Pointer oder eine Referenz auf ein als invalid markiertes Objekt zurück. Das finde ich einfach bequemer, als einen TryCatch-Block drumrum zu bauen, und ein bisschen Performance spart es auch.
Schrompf, wie macht man sowas konkret, also eine Referenz als invalid markieren ? Ich benutz bei sowas bis heute immer Pointer, weil ich sonst nicht weiß wie ich auf NULL testen soll. Bei enums hab ich das schon so gemacht, also z.B.:
...da klappt das ganz gut, aber was mach ich bei structs und Klassen ?
Noch was zu den Exceptions: Beim
Google C++ Style Guide sind sie komplett verboten - das hatte mich gewundert, ich hatte Exceptions auch immer für guten Stil gehalten. Ich selber benutz sie auch so selten wie möglich, weil ich's irgendwie unübersichtlich finde.
Re: Eure Erfahrungen mit Fehlerbehandlung
Verfasst: 04.06.2010, 18:47
von Seraph
@Google: Das erklaert auch, warum ihre Applikationen immer ohne Meldung crashen. :D Na gut, meine Erfahrungen mit Google Apps liegen schon ein paar Jahre zurueck, aber damals habe ich mich echt gefragt, wie die sowas als grosse Firma veroeffentlichen koennen.
@invalide Referenzen: Also so wie Schrompf es geschrieben hat, wuerde ich auf ein Flag in dem Objekt tippen, welches den Status angibt.
Re: Eure Erfahrungen mit Fehlerbehandlung
Verfasst: 04.06.2010, 18:50
von Krishty
ponx hat geschrieben:Schrompf, wie macht man sowas konkret, also eine Referenz als invalid markieren ?
Das Objekt, auf das die Referenz zeigt, ist invalid – nicht die Referenz selber (das ist ja gerade das Gute an Referenzen). Hat nur den Nachteil, dass man dem Objekt damit einen „Zombie State“ geben muss (z.B. nullen und eine
IsValid()-Funktion hinzufügen), gegen den man auch hier und da testen muss, was die Programmlogik verkompliziert. Kommt auf den Kontext an, aber in den meisten Fällen ist ein Zeiger auf ein Objekt ohne Zombie State die beste Option.
ponx hat geschrieben:Noch was zu den Exceptions: Beim
Google C++ Style Guide sind sie komplett verboten - das hatte mich gewundert, ich hatte Exceptions auch immer für guten Stil gehalten.
Sind sie auch, aber die meisten Leute kommen schlecht darauf klar. Wenn man durch Exceptions RAII erzwingt muss man z.B. die Regeln für die Initialisierungsreihenfolge von Membern kennen und einhalten, und das tun leider immernoch die wenigsten. Dass Visual C++ dann trotz korrekter Verwendung noch Warnungen schmeißt, macht die Sache nicht einfacher.
Edit: Der Style-Guide ächtet auch Operatorenüberladung und RTTI und fordert
Init()-Funktionen … wahrscheinlich spielen da auch Vorsichtsmaßnahmen gegen Portierungsprobleme und das Abschätzen von Wirkungen (schließlich pflegt Google auch Betriebssysteme und Low-Level-Code) eine Rolle. Die Vorgaben sollten für PC-Entwicklung etwa so unwichtig sein wie die JSF-Richtlinien – der Style kann sich gern daran orientieren, das Programmdesign bitte bloß nicht.
Re: Eure Erfahrungen mit Fehlerbehandlung
Verfasst: 04.06.2010, 21:59
von ponx
Krishty hat geschrieben:ponx hat geschrieben:Schrompf, wie macht man sowas konkret, also eine Referenz als invalid markieren ?
Das Objekt, auf das die Referenz zeigt, ist invalid – nicht die Referenz selber (das ist ja gerade das Gute an Referenzen).
ja, das meinte ich, Danke Krishty ! Mit dem IsValid() ist eine schöne Lösung! wieder was gelernt !
Re: Eure Erfahrungen mit Fehlerbehandlung
Verfasst: 05.06.2010, 11:11
von Helmut
Also ich finde das Programmieren mit Exceptions eigentlich ziemlich anstrengend.
Man muss immer genau im Auge behalten, was passiert, wenn eine Funktion Exceptions wirft. Man muss auf die Reihenfolge der Definitionen achten. Man muss RAII konsequent durchziehen, also im Grunde für jede API, die es gibt, massig Wrapper bauen. Und wenn man mal am Ende einer Funktion etwas Unübliches mit einer Referenz machen möchte, zB eine temporäre Datei löschen oder den Focus wechseln will, muss man das gleich in einen finally Block packen (den es in C++ lustigerweise nichtmal gibt und durch Tricksereien nachgeahmt werden muss).
Um dann noch einigermaßen sauber zu bleiben, wird man natürlich auch noch die Fehler anderer APIs via Return, GetLastError, andere Exceptiontypen, Structured Exceptions und was es noch so gibt in die eigenen Exceptiontypen umwandeln müssen, um am Ende auch eine vernünftige Meldung ausgeben zu können. Umgekehrt wird man auch konvertieren müssen (was meist garnicht geht), wenn man sich in Rückrufprozeduren von C APIs befindet (zB Windowsprozeduren, DllMain, PlugIns, Treiber).
Es gibt es noch einen Haufen Probleme, weil Exceptions die Standardlibrary voraussetzen und nicht richtig standardisiert sind. Bei verschiedenen Versionen in den Modulen hat man also einige Schwierigkeiten.
Zu guter letzt ist auch ein großes Problem von Exceptions, dass man einem Code, der Exceptions korrekt behandelt, dieses oft nicht ansieht. Bei Fehlercodes sieht man schon von Weitem die if Schachtelungen. Zugegebenermaßen denke ich mir auch oft beim Schreiben dieser if Orgien, ob das nicht einfacher geht, aber Exceptions sind leider nicht die Lösung.
Ciao
Re: Eure Erfahrungen mit Fehlerbehandlung
Verfasst: 05.06.2010, 12:54
von eXile
In Bezug auf die von Helmut angesprochenen if-Orgien … häufig findet man ja folgenden Code, gerade wenn man es mit API mit C-Interface zu tun hat:
Code: Alles auswählen
A *a = makeResourceA();
if(!resourceAIsValid(a))
{
cleanUpResourceA(a);
return;
}
B *b = makeResourceB();
if(!resourceBIsValid(b))
{
cleanUpResourceB(b);
cleanUpResourceA(a);
return;
}
C *c = makeResourceC();
if(!resourceCIsValid(c))
{
cleanUpResourceC(c);
cleanUpResourceB(b);
cleanUpResourceA(a);
return;
}
Mit dem
hier könnte man das Ganze dann auch so verpacken:
Code: Alles auswählen
A *a = makeResourceA();
if(resourceAIsValid(a))
FINALLY(cleanUpResourceA(a));
else
return;
B *b = makeResourceB();
if(resourceBIsValid(b))
FINALLY(cleanUpResourceB(b));
else
return;
C *c = makeResourceC();
if(resourceCIsValid(c))
FINALLY(cleanUpResourceC(c));
else
return;
Das ist zwar jetzt auch nicht besonders schön, aber es erspart doch ein paar Zeilen und es sollte vom Wartungsaufwand her besser sein.
Re: Eure Erfahrungen mit Fehlerbehandlung
Verfasst: 05.06.2010, 14:18
von Krishty
Helmut hat geschrieben:Man muss immer genau im Auge behalten, was passiert, wenn eine Funktion Exceptions wirft.
Empfinde ich nicht so … in 99 % der Fälle bedeutet das Werfen einer Exception für den Aufrufer, dass es aussieht, als sei der werfende Code nie aufgerufen worden. Ich kenne die Argumentation, dass man ein Auge auf jeden Nebenausdruck werfen muss, der was werfen könnte – die sieht man überall und habe sie nie verstanden … wenn ich eine Datei wegen einer
bad_alloc-Exception nicht mappen kann ist es doch egal, ob zuwenig Speicher für die Konstruktion des Dateinamens da ist oder für die Reservierung der Pages, oder? Meistens ist es sogar egal ob der Dateiname ungültige Zeichen enthält, die Datei nicht existiert oder die Welt untergeht. Der Fehler ist längst in die Log-Datei geschrieben und wenn es nicht geht, geht es einfach nicht.
Helmut hat geschrieben:Man muss auf die Reihenfolge der Definitionen achten.
Als ob das was Schlimmes wäre … wenn Dinge logisch aufeinander aufbauen, muss man den Zusammenhang auch im Code wiedergeben, und wenn C-Level-Programmierung was anderes erlaubt sehe ich das eher als Schwäche denn als Stärke. Wenn Dinge voneinander unabhängig sind, kann man auch mit Exceptions beliebige Reihenfolgen wählen.
Helmut hat geschrieben:Man muss RAII konsequent durchziehen, also im Grunde für jede API, die es gibt, massig Wrapper bauen.
Helmut hat geschrieben:Um dann noch einigermaßen sauber zu bleiben, wird man natürlich auch noch die Fehler anderer APIs via Return, GetLastError, andere Exceptiontypen, Structured Exceptions und was es noch so gibt in die eigenen Exceptiontypen umwandeln müssen, um am Ende auch eine vernünftige Meldung ausgeben zu können.
Aus Return-Codes und
GetLastError() die Fehler zu extrahieren ist zum einen hochgenerisch und zum anderen müsstest du es bei reiner Verwendung von Return-Codes doch auch machen. Das wenn-einmal-dann-immer-Argument gilt für alle guten Patterns wie
const-Correctness genauso … und die Wrapper sind überschaubar – mit einem 20-Zeilen-Template hat man das Nötigste an COM-Objekten automatisiert und für APIs, die Return-Codes benutzen, beschränkt sich das wrappen auf
if(FAILED(ReturnCode Result = APICall())) PrintError(Result), throw Foo;. Aber ich muss zugeben, dass meine Erfahrungen sich da auf D3D, libpng und Lua beschränken … gibt sicher auch APIs, wo das schwieriger ist. Kannst du mir eine nennen, wo man tatsächlich Structured Exceptions erwarten muss? Ich kenne die nur als Bug-Symptome, nicht als Kommunikationsmittel :)
Helmut hat geschrieben:Und wenn man mal am Ende einer Funktion etwas Unübliches mit einer Referenz machen möchte, zB eine temporäre Datei löschen oder den Focus wechseln will, muss man das gleich in einen finally Block packen (den es in C++ lustigerweise nichtmal gibt und durch Tricksereien nachgeahmt werden muss).
Kannst du ein Beispiel liefern? Code-lokale temporäre Dateien werden beim Aufruf ihres D’tors gelöscht, afaik macht das die WinAPI sogar automatisch bei
CloseHandle(). Ironischerweise ist die einzige Stelle, wo ich bisher
finally benötigt hätte, der Wrapper einer C-API gewesen. Da habe ich das Schreiben des Destruktors prokrastiniert :D
Helmut hat geschrieben:Umgekehrt wird man auch konvertieren müssen (was meist garnicht geht), wenn man sich in Rückrufprozeduren von C APIs befindet (zB Windowsprozeduren, DllMain, PlugIns, Treiber). Es gibt es noch einen Haufen Probleme, weil Exceptions die Standardlibrary voraussetzen und nicht richtig standardisiert sind. Bei verschiedenen Versionen in den Modulen hat man also einige Schwierigkeiten.
Ja, für Systemprogrammierung sind Exceptions ja schon aufgrund der schwer abschätzbaren Wirkungen völlig ungeeignet. Für den Einsatz über DLL-Grenzen sowieso by-Design. Wenn man Plugins und Callbacks für fremden Code schreibt, muss man auch nach dessen Regeln spielen – das sagt aber nichts über die Qualität der Regeln aus …
Helmut hat geschrieben:Zu guter letzt ist auch ein großes Problem von Exceptions, dass man einem Code, der Exceptions korrekt behandelt, dieses oft nicht ansieht. Bei Fehlercodes sieht man schon von Weitem die if Schachtelungen.
Code behandelt Exceptions üblicherweise korrekt, indem er sie garnicht behandelt … mit zwei
catch-Blöcken auf tausend Zeilen reines C++ bin ich momentan sehr zufrieden.
Re: Eure Erfahrungen mit Fehlerbehandlung
Verfasst: 05.06.2010, 22:14
von Helmut
Es war einmal vor langer Zeit ein kleiner Programmierer, der in einer wunderbaren Welt lebte. Sämtliche Funktionen der Win32 API basierten auf Exceptions und RAII. Er war gerade dabei, die Speicherfunktion von MS Paint zu implementieren, dazu genügten zwei Zeilen:
Code: Alles auswählen
void SaveImageToFile(const string& Filename)
{
AUTO_HANDLE out = CreateFile(Filename);
WriteImageToHandle(out);
//Dtor von AUTO_HANDLE gibt den Handle automatisch frei. Yay!
}
Beide aufgerufenen Funktionen benutzen Exceptions, Fehlerbehandlung und Aufräumarbeiten laufen also völlig von selbst. Er freute sich und wollte schon neue coole Features wie Radiergummis implementieren.
Doch dann kam ein Bugreport von einem Betatester, er habe ein Bild gemalt, wollte speichern, gab einen invaliden Dateinamen ein und Paint verabschiedete sich mit einer Fehlermeldung. Das Bild war futsch. Ups sagt da unser Programmierer, da hat wohl sein Kollege, der SaveImageToFile benutzt, vergessen die Exception rechtzeitig abzufangen. Kein Problem, Doku und Code sind schnell gefixt und Win95 wird releast.
Ein Tag nach Release treffen tausende Bugreports ein: Paint habe zwar eine ordentliche Meldung ausgegeben, die alte Bilddatei bei einem Fehler aber komplett leer gemacht. Wieder eine Data-loss Situation, aber unserem Programmierer fällt schnell eine Lösung für das Problem ein:
Code: Alles auswählen
void SaveImageToFile(const string& Filename)
{
AUTO_HANDLE out = CreateFile(Temp);
WriteImageToHandle(out);
MoveFile(Temp, Filename);
}
Immer noch ein sehr schöner Code, etwas verunsichert testet er ihn aber lieber doch und stellt leider fest, dass er immer fehlschlägt: Temp kann ja garnicht verschoben werden, weil die Datei ja noch zum Schreiben geöffnet ist. Gut, müssen wir wohl den Dtor-Aufruf erzwingen:
Code: Alles auswählen
void SaveImageToFile(const string& Filename)
{
{
AUTO_HANDLE out = CreateFile(Temp);
WriteImageToHandle(out);
}
MoveFile(Temp, Filename);
}
Nicht mehr ganz so schön, dafür aber ohne Bugs. Zumindest sieht es so aus...
Long story short: Unzählige Bugreports, 3 Jahre und 10 Morddrohungen später sieht der Code so aus:
Code: Alles auswählen
void SaveImageToFile(const string& Filename)
{
{
AUTO_HANDLE out = CreateFile(Temp1);
WriteImageToHandle(out);
//Wehe jemand entfernt nochmal diesen Block! Dtor von out muss hier aufgerufen werden
}
try
{
MoveFile(Filename, Temp2);
}
catch(SourceDoesntExist)
{
//Datei wird zum ersten Mal gespeichert
}
catch(...)
{
DeleteFile(Temp1); //TODO: Exception abfangen oder nicht?
throw;
}
try
{
MoveFile(Temp1, Filename);
}
catch(...)
{
try
{
MoveFile(Temp2, Filename);//Altes Bild wiederherstellen
}
catch(...)
{
//Diese Exception abfangen, damit Temp1 garantiert gelöscht wird
}
DeleteFile(Temp1);
throw;
}
try
{
DeleteFile(Temp2);
}
catch(...)
{
//Falls es vorher keine Datei unter dem Namen gab, wird Temp2 auch nicht
//existieren und DeleteFile fehlschlagen
}
}
Und Windows 98 muss immnoch ohne Radiergummifunktion auskommen. Genervt fragt sich der kleine Programmierer, ob es nicht ein besseres Fehlermodell gibt...
Zum Glück war alles nur ein Traum, in Wahrheit war die erste Version von SaveImageToFile:
Code: Alles auswählen
void SaveImageToFile(const char* Filename)
{
HANDLE out = CreateFile(Filename);
WriteImageToHandle(out);
CloseHandle(out);
}
Und als dem kleinen Programmierer nach 5 Sekunden auffiel, dass er die Fehlerbehandlung vergessen hatte, kommt er nach einer Stunde müheseligen Codens letztlich auf das:
Code: Alles auswählen
bool SaveImageToFile(const char* Filename)
{
HANDLE out = CreateFile(Temp1);
if(!out)
return false;
if(!WriteImageToHandle(out))
{
CloseHandle(out);
DeleteFile(Temp1);
return false;
}
CloseHandle(out);
if(!MoveFile(Filename, Temp2) && GetLastError() != SourceDoesntExist)
{
DeleteFile(Temp1);
return false;
}
if(!MoveFile(Temp1, Filename))
{
MoveFile(Temp2, Filename);//Altes Bild wiederherstellen
DeleteFile(Temp1);
return false;
}
DeleteFile(Temp2);
return true;
}
"Das hat ja ewig gedauert", denkt er sicht, "warum hat C kein besseres Fehlermodell? Naja, immerhin habe ich jetzt noch genug Zeit um ein Radiergummi zu implementieren."