Objekte anstatt Null-Referenzen

Können Sie sich noch an den Milliarden-Dollar-Fehler von Tony Hoare erinnern?

Jedenfalls bringt die Null-Referenz (in C++ der Null-Zeiger) viele Programmierer zur Verzweiflung. Denn man tappt immer wieder in die Falle, das eine Referenz Null sein kann. Wenn man diese nicht vor der Benutzung prüft, gibt es einen Absturz. Und dieser Fehler führte weltweit seit seiner Erfindung zusammen gerechnet wohl zu eine Milliarde-Dollar Kosten.

Sie erleben den Fehler und umgehen diesen deshalb so oder ähnlich:

void bar(Type r) {
   if(r != null)
      r.foo();
}
TypeList r = search();
if(r != null)
   r.foo();

Die if-Abfragen sind doch unnötiger Ballast und haben nichts mit der eigentlich zu lösenden Aufgabe (Algorithmus) zu tun. Diese if-Abfragen machen nur deutlich, dass die API oder Programmiersprache anscheinend nicht vertrauenswürdig genug ist. Überall sind diese „Stützräder“ und machen den Code unleserlicher und lenken vom eigentlichen Code ab.

Tony Hoare sagte mal, das er den Fehler beging, Null-Referenzen überhaupt erfunden zu haben. Dann wäre doch die Lösung, diese erst gar nicht zu verwenden?

Vermeiden Sie Null-Collections

Es ist wichtig, das die API die sie entwickeln oder benutzen, klar das Null-Objekt-Pattern unterstützt. Am einfachsten lässt sich das Ganze bei Collections lösen (in C++ die Container). Sagen wir mal, sie müssen eine solche zurück geben:

 public List getList() {
   // wenn es keine Liste oder keine zutreffenden Elemente gibt,
   // geben viele Programmierer Null zurück:
   return null;
}

List result = getList();
if( result == null)
   return;
for(int i=0; i<result.size(); i++)

Nein, geben Sie einfach eine leere Liste zurück! Dann kann der Benutzer direkt ohne Bla-Bla damit arbeiten:

public List getList() {
   // wenn es keine Liste oder keine zutreffenden Elemente gibt,
   // geben Sie eine leere Liste zurück:
   return new List();
}

List result = getList();
for(int i=0; i<result.size(); i++)
  // Schleife wird bedingt übersprungen. Alles OK!

Sieht doch schon viel einfacher aus, oder?

Eine if-Abfrage ist in dem Fall auch nicht effizienter.

Verwenden Sie das Null-Object-Pattern

Nun gibt man ja nicht immer eine Collection zurück. Wenn Sie Interfaces oder Abstract Base Classes (ABC) haben, können Sie daraus ein Null-Object definieren. Ein Beispiel:

interface IType {
   public void foo();
}

// Konkreter Typ, wie sonst auch:
class TypeA implements IType {
   public void foo() {
        // mache was TypeA normalerweise macht.
   }
}

// Null-Object:
class NullType implements IType {
   public void foo() {
       return; // mache nichts!
   }
}

Letztendlich ist das Null-Object eines, welches bei Aufruf nichts tut. Dieses Objekt kann dann gerne als Parameter übergeben oder zurück gegeben werden.

Wenn möglich, kann man Null-Objekte als Singleton und Immutable implementieren. So könnte man auch Performance und Resourcen einsparen, wenn es ein Null-Objekt pro Typ nur einmal gibt.