Contract Programming

Contract Programming (dt.: vertragsbasierte Programmierung) in D umfasst einen Satz von Sprachkonstrukten, die die Quellcodequalität durch bestimmte Prüfroutinen (sog. Contracts) erhöhen und korrektes Verhalten sicherstellen sollen.

Contracts stehen nur im Debug-Modus zur Verfügung und werden im Release-Modus nicht ausgeführt. Deshalb sollten sie nicht für die Überprüfung von Benutzereingaben eingesetzt werden.

assert

Der assert(...)-Ausdruck bietet die einfachste Form des Contract Programming und prüft ob eine bestimmte Bedingung eingehalten wird, anderenfalls bricht das Programm ab.

assert(sqrt(4) == 2);
// optionale benutzerdefinierte Fehlernachricht
assert(sqrt(16) == 4, "sqrt is broken!");

Contracts bei Funktionen

in und out erlauben formalisierte Contracts für Eingangsparameter und Rückgabewerte von Funktionen.

long square_root(long x)
in {
    assert(x >= 0);
} out (result) {
    assert((result * result) <= x
        && (result+1) * (result+1) > x);
} body {
    return cast(long)std.math.sqrt(cast(real)x);
}

Der Inhalt des in-Blocks könnte auch im Rumpf der Funktion stehen, auf diese Art wird aber die Intention viel klarer. Im out-Block der Funktion kann der Rückgabewert mit out(result) erfasst und entsprechend geprüft werden.

Überprüfung mit invariant

invariant() ist eine spezielle Memberfunktion von struct- und class-Typen, der die Überprüfung des Objektzustands während dessen gesamter Lebenszeit erlaubt.

invariant() wird zu folgenden Zeitpunkten ausgeführt:

  • nach Ausführung des Konstruktors
  • vor Ausführung des Destruktors
  • vor Eintritt in eine Memberfunktion
  • nach Beendigung einer Memberfunktion

Überprüfung von Benutzereingaben

Da alle Contracts im Release-Build entfernt werden, sollten Benutzereingaben nicht mit Contracts überprüft werden. Darüber hinaus können asserts weiterhin in nothrow-Funktionen verwendet werden, da diese fatale Error werfen.

Die Laufzeitentsprechung zu assert ist std.exception.enforce, die auffangbare Exceptions wirft.

Weiterführende Quellen

rdmd playground.d