5 minute read

Welcher Softwareentwickler kennt das nicht?

Trotz des Gesetz von Demeter kommt es immer wieder vor, dass man eine Methode an einem Objekt aufrufen möchte, welches man selbst wiederum erst durch einen Methodenaufruf erhalten hat.

Ein typisches Beispiel hierfür ist die Abfrage der Postleitzahl der Adresse einer Person, um beispielsweise Briefe für einen optimierten Versand nach den Postleitzahlen sortiert zu drucken.

In Java würde das dann etwa so aussehen:

public PlzType getPlzForPerson(Person person) {
    return person.getAddress().getPLZ();
}

Das Problem dabei: Angefangen vom übergebenen Objekt person können alle Zwischenergebnisse dieser Kette von Aufrufen möglicherweise leer sein, also null.

Um hier keine NullPointerException (sog. NPE) zu erhalten, muss man also alle Werte prüfen und endet damit bei deutlich komplexerem Code, selbst bei unserem kleinen Beispiel mit nur zwei aufeinanderfolgenden Methodenaufrufen in der Kette:

public PlzType getPlzForPerson(Person person) {
    if (person == null)
        return null;
    else if (person.getAdress() == null)
        return null;
    else
        return person.getAddress().getPLZ();
}

Seit der Einführung der Klasse Optional in Java 8 gibt es jedoch eine Möglichkeit, die Behandlung von null-Werten in solchen Methodenketten um einiges kompakter zu formulieren:

public PlzType getPlzForPerson(Person person) {
    Optional.ofNullable(person).
               map(Person::getAddress).
                 map(Address::getPLZ).
                   orElse(null);
}

Anstelle von null geben die map-Methoden von Optional einfach ein leeres Optional-Objekt zurück. orElse gibt dann am Ende den Inhalt des Optional zurück, oder eben den hier angegebenen Default-Wert.

Statt des abschließenden orElse, welches den Rückgabewert im Falle eines null irgendwo in der Aufrufkette festlegt, kann man auch die Methoden orElseGet (Aufruf einer anderen Funktion) oder orElseThrow (werfen einer Exception) verwenden.

Die ebenfalls auf der JVM (Java Virtual Machine) basierende Programmiersprache Kotlin vermeidet das Problem der NullPointerException weitestgehend, indem sie null zunächst einmal gar nicht als Wert einer Variable zulässt.

Man kann allerdings Variablen auch in Kotlin explizit als nullable deklarieren, zudem können sich null-Werte natürlich auch durch die Interaktion mit Java-Code einschleichen.

Die Sprache macht den Zugriff dann aber mit ihrem Safe Call Operator recht einfach und elegant:

    person?.address?.plz

Zudem kann mit Hilfe der Nutzung des Elvis-Operators ?: ebenfalls ein Default-Wert angegeben werden.

Ähnliche Mechanismen gibt es auch in vielen anderen Programmiersprachen, beispielsweise in Ruby.

Seit der Ruby-Version 2.3.0 kann man mit Hilfe des Safe Navigation Operator anstatt

    person.address.plz if person && person.plz

auch einfach

    person&.address&.plz

schreiben.

Eine Übersicht zum Safe Navigation Operator in verschiedenen Sprachen ist auf Wikipedia zu finden.

Der Erfinder der null-Referenz, C.A.R. Hoare, hat sich übrigens 2009 auf einer Software-Konferenz bei der Community für diesen Billion Dollar Mistake offiziell entschuldigt.