Refactoring mit Guard Clauses

Immer wieder finden sich Codefragmente, die sich in einer unnötig komplizierten Logik verlieren. Wie schon in Zauberei mit Wahrheiten angesprochen, sind es meist unterlassene Umstellungen im Code durch boolsche Umformungen.

Parameter prüfen

Eine häufige Ursache für die komplizierte Logik, ist die Prüfung der Eingangsparameter. Nicht alle Werte, die ein Parameter enthalten kann, machen Sinn für die Verarbeitung in der Methode. Daher werden sie abgefangen oder umgeformt. Die Bearbeitung von neu hinzugefügten Parameter wird in die bestehende Logik eingeflechtet, anstatt die Logik gänzlich zu überarbeiten.

private String method(String name, int age) {
  String state = null;
  if (name!= null && !name.isEmpty()) {
    if (age > 42) {
      state = normalMethod(name);
    } else {
      state = youngMethod(name);
    }
  } else {
    state = unknownMethod("anonymous");
  }
  return state;
}

Erst 13 Zeilen lang, aber schon recht kompliziert anzuschauen. Viel übersichtlicher lässt sich die Methode schreiben, wenn man alle Sonderfälle am Anfang der Methode behandelt. Das sind die Guard Clauses, die den eigentlichen Methodenaufruf bewachen.

private String method(String name, int age) {
  if (name == null || name.isEmpty() {
    return unknownMethod("anonymous");
  }
  if (age < 43) {
    return youngMethod(name);
  }
  return normalMethod(name);
}

Durch den Einsatz der Guard Clauses, ist die Methode nun besser zu verstehen und weitere Einschränkungen oder Erweiterungen können mit ihrer Hilfe einfacher ergänzt werden.

Derselbe Ansatz könnte auch bei der Überprüfung des Zustandes eines Objektes verwendet werden, doch sollte man dort besser auf State und Strategy Design Patterns zurückgreifen.

Exceptions als Überraschung

Ein sehr ähnlicher Anwendungsfall für Guard Clauses ist der Wurf einer Ausnahme aus dem Dickicht der Methodenlogik.  Auch hier leidet das Verstehen der Methode, wenn die Ausnahmebehandlung nicht an exklusiver Stelle, also vorne, beschrieben ist.

String value = null;
if (name != null && !name.isEmpty()) {
  value = complexLogic(name);
} else {
  throw new IllegalArgumentException("missing name");
}

Auch schon in diesem kurzen Beispiel ist die umgeformte Version mit der Guard Clause übersichtlicher.

if (name == null || name.isEmpty()) {
 throw new IllegalArgumentException("missing name");
}
String value = complexLogic(name);

Die Guard Clause ist ein ein gutes Mittel, um komplizierte Programmlogik zu entflechten und den Code lesbarer zu schreiben.