Exception Handling

Exception Handling: Konzepte und Regeln

Die nachfolgenden Konzepte und Regeln lassen sich zwar nicht immer konsequent umsetzen, sollen aber eine Anregung sein, wie man einen Error-Handling-Code übersichtlich und effizient gestalten kann. Es lassen sich leicht drei grundlegende Konzepte identifizieren, die beim Error Handling Anwendung finden sollen:

  • Konzept 1: Minimalinvasiv
    Eine Fehlerbehandlung sollte minimalinvasiv erfolgen. Das Abfangen des Fehlers sollte demnach möglichst geringe Auswirkungen auf den normalen Programmablauf haben.
  • Konzept 2: Klare Fehlerbehandlung
    Die Fehlerbehandlung sollte klar konzipiert sein. Sie sollte sich auf erkennbare Programmabschnitte konzentrieren, die ggf. mit dem Facade-Pattern modelliert werden.
  • Konzept 3: Erweiterbarkeit
    Zu guter Letzt soll das Design der Fehlerbehandlung erweiterbar sein. Während der Entwicklung treten Fehlerszenarien auf, die in das Error Handling integriert werden müssen.

Die folgenden drei Regeln sollen bei der Implementierung berücksichtigt werden, sie sind eher idiomatischer Natur:

  • Regel 1: Kontraktprüfung
    Zu Begin einer Methode sollten zuerst alle Kontraktprüfungen gemacht werden, dann geht man zum eigentlichen Code über.
  • Regel 2: Fehlerbehandlung konzentrieren
    Um den Code gut lesbar zu gestalten sollte man versuchen, so viel Code am Stück zu schreiben wie möglich und diese Blöcke mit Try/Catch-Anweisungen zu versehen, wobei dann mehrere Catch-Anweisungen hintereinander stehen können.
    Hierzu bietet es sich an, die Fehler in kritische und unkritische Fehler einzuteilen. Kritische Fehler führen gewöhnlich zum Abbruch der Aktion oder ggf. des Programms, unkritische Fehler können vielleicht durch eine angemessene Fehlerbehandlung behoben werden, z.B. durch eine Benutzer-Interaktion oder eine Wiederholung. Alle kritischen Fehler werden in einem äußeren Try/Catch-Block behandelt, die unkritischen Fehler in einem oder mehreren inneren Blöcken.
  • Regel 3: Cleanup
    Alle abschließenden Handlungen, wie z.B. das Schließen von Ressourcen, sollten in einem Finally-Block stattfinden.
public void doIt() {
  // zuerst Kontraktprüfungen
  if (istKontraktVerletzung) {
    throw new RuntimeException("Kontrakt Verletzung!");
  }
  // Anweisungen mit kritischen Fehlern
  try { 
    try {
      // Anweisungen mit unkritischen Fehlern
      (...)
    }
    catch (UnkritischeException1 ue1) {
      (...)
    }
    catch (UnkritischeException2 ue2) {
      (...)
    }
    ...
  catch (KritischeException1 ke1) {
    (...)
  }
  catch (KritischeException2 ke2) {
    (...)
  }
  ...
  finally {
    try {
      // cleanup
      (...)
    }
    catch (CleanupException ce1) {
      (...)
    }
    ...
  }
}

Das Codebeispiel veranschaulicht den Cleanup im Finally-Block. Ausnahmen, die im Finally-Block entstehen, werden auch dort behandelt.

Die Kunst der Ausnahmenbehandlung

Die hier vorgestellten Mittel sollen dabei helfen, Programmcode übersichtlich zu gestalten und eine Fehlerbehandlung und -suche möglichst sauber implementieren zu können. Allheilmittel sind sie natürlich nicht. Sie dienen allerdings dazu, das Programm robust gegenüber Fehlern zu machen, die bei der Entwicklung und während der Ausführung entstehen können.

Abschließend wird zusammengefasst, was in diesem Artikel genannt wurde. Die Vermeidung von Antipatterns vereinfacht vor allem die Fehlersuche, denn es gibt genügend Möglichkeiten, die konzeptionell sehr guten Eigenschaften der Java Exceptions, wie Stacktraces, abzuschneiden oder ad absurdum zu führen (z.B. durch ein return im Finally-Block). Generell ist es empfehlenswert, sich mit Antipatterns vertraut zu machen, um den Blick für schlechten Code zu schärfen.
Auf der Seite der Patterns ist es sinnvoll, das Abprüfen von Kontrakten stringent zu implementieren. Ein Kontrakt sollte nicht nur im Javadoc-Kommentar genannt werden. Dort kann er als Nice-To-Have verstanden werden, insofern der Nutzer des APIs den Javadoc-Kommentar überhaupt liest.

Wenn Sie noch das Facade Pattern beherzigen, dann sind Sie tendenziell auf der sicheren Seite. Das Facade Pattern ermöglicht es, Methoden zu schreiben, ohne den API-Benutzer mit einer Flut von Exceptions zu konfrontieren. Ferner kann der Code besser strukturiert werden, da schon einige Fehlerquellen durch Kontrakte vordefiniert werden. Zu guter Letzt verwenden Sie noch die genannten Exception-Handling-Konzepte und -Regeln, die zusammen mit dem Facade Pattern eine praxisnahe Lösung ergeben.

Eric Schmieders, M.A., kam Ende der 90er zum ersten Mal mit Java in Kontakt und hat sich seitdem eingehend mit den drei verfügbaren Editionen beschäftigt. Derzeit befasst er sich bei einem international tätigen Dienstleister der Automotiv-Branche mit Java-basierten Testsystemen, Qualitätssicherung und Wissensmanagement. Außerdem ist er als Autor und als freiberuflicher Berater in dem Bereich Wissensmanagement tätig.
Kommentare

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht.