Error Handling //2474

Mal ein paar Sätze zum Error Handling, d.h. Reaktionen auf Laufzeitfehler.
Ihr habt euch bestimmt schon gewundert, oder gar geärgert, wenn ihr eine Anwendung laufen lasst, und ihr kriegt eine völlig nichts sagende Fehlermeldung.
Warum wird da nicht ausgegeben, was genau den Fehler auslöste?
Tja, Fehlerbehandlung ist so eine Sache ..

Wenn man als Entwickler ein neues Softwareprojekt beginnt, so ist das Behandeln aufgetretener Fehler anfangs nebensächlich. Hauptsache, das Programm läuft überhaupt erst mal. Zum Testen und Ausprobieren nimmt man Eingabeparameter, die funktionieren, und macht auch nur Nutzereingaben, die zielführend sind.
In der späteren Praxis ist das nicht mehr so. Ein komplexes Programm DAU-sicher zu machen, würde nach Pareto viel mehr Aufwand bedeuten, als es Nutzen bringt.
Aber auch bei ganz regulären Nutzereingaben und Aktionen können Exceptions auftreten, die abgefangen werden müssen.

Um nicht immer ganz abstrakt schreiben zu müssen, ein einfach nachvollziehbares Beispiel:
In einem Programm kommen unter anderem in einer bestimmten Funktion mehrere Divisionen und eine Quadratwurzelberechnung vor. Je nach Eingabedaten kann es dabei zum Teilen durch 0 oder zum Ziehen der Wurzel aus einer negativen Zahl kommen. Lässt sich jeweils vorher abprüfen, oder man überlässt es der FPU. Egal, kommt hier nicht drauf an.
In jedem Fall tritt eine Exception auf. Der Nutzer wird per Meldung informiert, dass etwas beim Rechnen schief ging. Die Ausführung der gesamten Nutzeraktion wird abgebrochen. Der Nutzer erfährt aber nicht, ob eine Divisionen oder die Radizierung der Grund ist.
In komplexeren Fällen muss das Programm vielleicht überprüfen, ob bestimmte Dateien vorhanden sind, diese einlesen, das Format validieren, mit den gelesenen Daten herumrechnen, diese Dateien verändern, und irgendwo anders hinschreiben, in der Registry lesen oder schreiben, blablabla ..
Da kann soviel schiefgehen. Die Crux ist, dass der weitere Programmablauf unterschiedlich sein muss, je nach dem, an welcher Stelle die Prozedur ausgestiegen ist. Wenn man die Eingabedateien schon nicht laden konnte, braucht man sie nicht mehr auszuwerten. Wenn bei der Auswertung etwas schief läuft, braucht man sie nicht mehr neu abzuspeichern. Wenn das abschließende Schreiben der Datei nicht klappt, muss man dennoch dynamischen Speicher, Handles, was weiß ich, wieder freigeben und finalisieren.
Oder die oben exemplarisch beschriebene arithmetische Funktion wird von mehreren Stellen aus aufgerufen. Selbst wenn sie korrekt ausgibt, was das Problem war, weiß man immer noch nicht, von wo aus dieser Call kam.
Das ganze kann beliebig kompliziert und ineinander verschachtelt sein. Ein sauberes, detailliertes Error Handling ist extrem aufwendig, und rentiert sich meist nicht, so dass es in der Entwicklung gerne vernachlässigt wird.
Der zusätzlich Zeitaufwand dafür ginge ins Unermessliche. Und Zeit ist Geld. Wollt ihr für eine Software-Anwendung das Mehrfache ausgeben, bloß um bei sehr selten auftretenden Fehlern genauer zu wissen, was jetzt konkret schiefging?

Auch bei Abläufen, die normalerweise klappen, können sporadisch Fehler auftreten.
Zu den möglichen Ursachen im eigenen Quellcode können noch Fehler im Betriebssystem, dem benutzen Framework, Third-Party-DLLs, oder sonstwo hinzukommen. Das lässt sich niemals vollumfänglich überblicken.
Manchmal fehlen die Rechte, manchmal ist es ein Resourcenkonflikt, .. Oft kann der Entwickler selbst nicht direkt erkennen, was nicht funktionierte. Schließlich kann man nicht jede einzelne API-Funktion auf ihren Rückgabewert hin prüfen (oder gar GetLastError() checken), und entsprechend reagieren.
Und man muss auch berücksichtigen, dass ähnliche Fehler (z.B. fehlgeschlagene Dateioperationen) an unterschiedlichen Codestellen passieren können. Auch wenn man erfährt, dass z.B. eine bestimmte Datei nicht geschrieben werden konnte, weiß immer noch nicht umbedingt, wo dies im Sourcecode steht, und warum nicht (vielleicht war sie von einer anderen Anwendung geblockt, oder der Speicherplatz reichte nicht aus, oder oder oder).

Das sind solche Dinge, mit denen man leben muss.
Wenn ich eine neue Software spezifiziere, versuche ich von vornherein, einigermaßen aussagekräftige Fehlermeldungen (d.h. Fehlercodes, die dann sprachabhängig in Meldungen umgesetzt werden können) vorzusehen (auch wenn das aus Entwicklersicht erst mal völlig lästig ist). Das ist immerhin besser, als das Error Handling erst später hineinzuflicken. Trotzdem ist es nur bis zu einem gewissen Grad sinnvoll.

Über Anne Nühm (breakpoint)

Die Programmierschlampe.
Dieser Beitrag wurde unter Uncategorized abgelegt und mit , , , verschlagwortet. Setze ein Lesezeichen auf den Permalink.

13 Antworten zu Error Handling //2474

  1. keloph schreibt:

    ich hatte mal das problem, bei abgezinsten sparbriefen am laufzeiten ende den zinsanteil zu rechnen, die genauseste formel arbeitet leider mit der laufzeit in potenz, was am ende die register überlaufen liess und unsinn produzierte. da es hier um steuerrelevante dinge ging, musste das mit einer plausi und unterschiedlichen pfaden und formeln bearbeitet werden. war das einzige mal, dass ich im studium erlerntes direkt einsetzen konnte 🙂 mein chef machte immer den ellenbogen test, eingabemaske aufrufen und dann mit ellenbogen die tatstatur bearbeiten. die fehlermeldungen mussten so gebaut werden, dass ein unwissender dennoch etwas sinnvolles reinklopfen konnte.

    Gefällt 1 Person

  2. Ochmonek schreibt:

    Schon seit ein vielen Jahren hätte ich gerne eine gute Fehlerbehandlung. Klassisches Beispiel: „Drucker druckt nicht“

    Hardwarenahe Ebene: Signal von Sensor 4711
    Zwischenebene: Kein Papier in manueller Zuführung
    Hardwarenahe Ebene: Signal von Sensor 1234
    Zwischenebene: Kein Papier im Papierfach
    Benutzerschnittstelle: Bitte Papier einlegen

    Solange sich Papier im Papierfach befindet, sieht der Benutzer nichts von den Fehlern, in der manuellen Zuführung. Die werden einfach im Erfolgsfall wieder verworfen.

    Im Fehlerfall sieht der Benutzer nur „Bitte Papier einlegen“. Normalerweise reicht das. Im Hintergrund hängt aber noch der gesamte Fehlerbaum an der Meldung. Wenn dann Papier eingelegt wird, kann der gesamte Fehlerbaum gelöscht werden.

    Einer von 1000 Anwendern hat aber Papier in der manuellen Zuführung. Er ruft die Hotline an und die kann sich den Fehler bis zur Zwischenebene ansehen. Der Benutzer versichert glaubhaft, dass sich Papier in der manuellen Zuführung befindet. Techniker und Entwickler haben Zugriff auf den gesamten Fehlerbaum. Der Techniker kann dann vor Ort den defekten Sensor 4711 austauschen.

    Aber wie du schon schreibst, meistens rentiert sich so etwas nicht. Und wie in diesem Beispiel ist es oft nicht möglich, dem Benuter eine korrekte und verständliche Fehlermeldung zu präsentieren.

    Die einzige intuitiv bedienbare Benutzerschnittstelle ist Muttis Brust. Alles andere muss erlernt werden.

    Gefällt 1 Person

  3. aranxo schreibt:

    Es stimmt jetzt nicht ganz, dass man nicht rauskriegen kann, wo der Fehler passiert ist. Dazu muss man eben den CallStack lesen (wenn in der Sprache die Exceptions den zur Verfügung stellen). Die letzte Methode, die von Dir bzw. dem Team stammt, ist es meistens, danach werden noch irgendwelche Framework-Funktionen protokolliert.

    Das Thema ist für mich schon seit längerem durch, jedenfalls für .NET. Ich hab eine hübsche kleine DLL gebaut, die sich ganz vorne in der Main-Prozedur den allgemeinen Errorhandler für alle unbehandelten Exceptions krallt. Selber kann man natürlich immer noch Errorhandling machen, aber wenn was durchrutscht, bleibt es bei dem allgemeinen Handler hängen.

    Der poppt ein Fensterchen auf, wo der Text der Exception steht. Wenn man mehr wissen, kann man das Fenster aufklappen und mehr Infos inklusive CallStack sehen. Das ganze wird auch in einer Log-Datei protokolliert, ein Screenshot gemacht und wenn man ihn richtig konfiguriert hat, schickt er gleich dem Entwickler eine Mail mit Log-Datei und Screenshot. Davon muss der User natürlich vorher wissen, selbstverständlich ist das freiwillig. 😉

    Gefällt 1 Person

    • Du hast ja völlig recht.
      Der Entwickler kann beim Debuggen über den Callstack rückverfolgen, wo der Fehleraufruf herkam.
      Mir ging es hier aber um die Sicht des Anwenders, der ein Programm laufen lässt, und dann eine Meldung bekommt, die höchstens verwirrt, aber nicht weiterhilft.

      Globale Exception Handler haben ihr Grenzen, und auch das Loggen in einer Datei ist so eine Sache.
      Gerade in unserer Branche sind erfahrungsgemäß viele Anwender überfordert, eine eventuelle Logdatei zu verschicken. Da müsste dann ein Admin miteingebunden werden, was für kleinere Probleme weit übertrieben wäre.
      Denkbar wäre es, bei einzelnen Fehlern eine Mail automatisch zu verschicken, aber einerseits steht dem der Datenschutz im Weg. Zum anderen haben die betroffenen Rechner häufig gar keinen Zugriff auf das öffentliche Internet.

      Gefällt 1 Person

      • aranxo schreibt:

        Klar, der Anwender ist immer irgendwie aufgeschmissen. So ein Tool kann ja auch mehr oder weniger nur verhindern, dass die Anwendung kommentarlos abraucht oder netterweise mit einer nichtssagenden Fehlermeldung vorher.

        Wenn man Software nicht für die Außenwelt, sondern die eigene Organisation schreibt, können Chefs schon darauf dringen, dass die automatische Mail an den Entwickler geschickt wird. Aber auch da muss man meist den Anwender fragen, was er denn versuchte zu tun bzw. wobei er gescheitert ist.

        Gefällt 1 Person

Kommentar verfassen

Trage deine Daten unten ein oder klicke ein Icon um dich einzuloggen:

WordPress.com-Logo

Du kommentierst mit Deinem WordPress.com-Konto. Abmelden /  Ändern )

Google Foto

Du kommentierst mit Deinem Google-Konto. Abmelden /  Ändern )

Twitter-Bild

Du kommentierst mit Deinem Twitter-Konto. Abmelden /  Ändern )

Facebook-Foto

Du kommentierst mit Deinem Facebook-Konto. Abmelden /  Ändern )

Verbinde mit %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.