JAXenter.de

Das Portal für Java, Architektur, Cloud & Agile
X

Wieviel Cyborg steckt jetzt schon im Menschen? Die webinale VISIONS klärt auf.

Exception Handling

Patterns und Antipatterns

Patterns und Antipatterns, es gibt kaum ein Begriffspaar, das symptomatischer die Entwicklung sprachlich verdichtet, die sich seit einigen Jahren in der Softwarebranche abspielt. Immer mehr Frameworks erscheinen auf dem Markt, die wiederkehrende Probleme auf dieselbe Art und Weise behandeln. Der Grundgedanke dafür sind Muster, die eine schablonenhafte Lösung für ein Problem darstellen. Besonders auf der untersten, der idiomatischen Ebene, zeigen Entwurfsmuster ihr ganzes Potenzial. Jeder halbwegs erfahrene Softwareentwickler kennt sie, systematisch katalogisiert wurden sie aber erstmals von der Gang of Four [Gamma, Helm, Johnson, Vlissides: "Design Patterns. Elements of Reusable Object-Oriented Software." Addison-Wesley Longman].

Entwurfsmuster sind wiederverwendbare, kontextspezifische Vorlagen zur Problemlösung. Der Begriff stammt bekanntermaßen aus der Architektur und hat seit einiger Zeit seinen festen Platz in der Welt der Software. Muster ist aber nicht gleich Muster. Ein gutes Muster sollte mindestens ein Problem zuverlässig lösen. Das zugrunde liegende Konzept sollte also hinreichend erprobt sein. Ein Entwurfsmuster soll auf einem realen Design basieren, das heißt, es sollte praxisnah entwickelt worden sein. Weiterhin sollte es über das rein Offensichtliche hinausgehen und damit einen Mehrwert versprechen. Der Benutzer soll in den Entwurfsprozess eingebunden werden. Zu guter Letzt soll es Beziehungen aufzeigen, die tiefergehende Strukturen und Mechanismen eines Systems umfassen.

Im Folgenden werden Antipatterns im Bereich Error Handling vorgestellt. Antipatterns sind Negativbeispiele, die den Blick dafür schärfen sollen, was bei einem erfolgreichen Design zu vermeiden ist. Negativbeispiele gibt es beim Error Handling zwar viele, hier sollen sie aber nur exemplarisch behandelt werden.

Ein häufig zu beobachtendes Antipattern, besonders bei Java-Einsteigern, denen das spracheigene Exception Handling grundfremd ist, ist das Throwing Exception Antipattern. Die Methodensignatur des Beispiels

public void doIt() throws Exception {
    .
}

p>offenbart dem Nutzer des APIs rein gar nichts. Natürlich kann in einer Methode eine Exception auftreten. Eine Exception ist (fast) die allgemeinste Form eines Fehlers. Schlimmer wäre noch, throws Throwable in die Signatur aufzunehmen. Statt der allgemeinen Exception sollte eine spezialisierte Signatur gewählt werden, die der Umgebung eine differenzierte Fehlerbehandlung erlaubt (für weitere Antipatterns siehe auch hier).

Das Destructive Wrapping Antipattern demonstriert, wie im Catch-Block der Stacktrace des Fehlers zerstört wird.

public void doIt(){
  try {
    .
  } catch (MyException e) {
    throw new XYZException("Error"+e.getMessage());
  }
}

Dieses Exception Handling führt zum Verlust des Stacktraces. Was wäre hier zu tun? Man könnte beispielsweise der Exception, die mit throw geworfen wird, ihren Trace per java.lang.Exception.initCause(java.lang.Throwable) mit auf dem Weg geben. Durch die Chained Exception Facility würde der Trace der Exception jederzeit nachvollziehbar bleiben.

Das folgende Antipattern gewährt uns einen düsteren Blick in die Abgründe dessen, was das Exception Handling in Java ermöglicht und leider nicht per Compiler Check ausgeschlossen werden kann.

public void doIt(){
  try {
    .
  } catch (Exception e) {
  }
}

Die Exception wird nicht ausgegeben. Sie verschwindet in der Versenkung und nur die VM weiß, wo sie gelandet ist. Vielleicht weiß es auch der Garbage Collector, keinesfalls aber das restliche Programm. Das verrichtet nichtsahnend seine Dienste, bis es an einer anderen Stelle knallt. Den Weg zur ursprünglichen Fehlerquelle zurückzuverfolgen, wird durch die verschwundene Exception zu einem zeitraubenden Abenteuer.

Während man dem verantwortlichen Entwickler beim vorangegangen Beispiel grob fahrlässiges Verhalten vorwerfen könnte, kann man den moralischen Zeigefinger bei diesem Antipattern weniger selbstverständlich erheben:

public void doIt(){
  try {
    throw new Exception("Just a test.");
  } finally {
    return;
  }
}

Die Exception im Try-Block wird nicht geschmissen. Die Methode wird per return "normal" verlassen. Das Try-Catch-Finally-Konzept ist an dieser Stelle kontraintuitiv. Es gilt darauf zu achten, keine returns in den Finally-Block zu schreiben.

 
Verwandte Themen: 

Kommentare

Ihr Kommentar zum Thema

Als Gast kommentieren:

Gastkommentare werden nach redaktioneller Prüfung freigegeben (bitte Policy beachten).