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!");
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.
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:
Da alle Contracts im Release-Build entfernt werden, sollten
Benutzereingaben nicht mit Contracts überprüft werden.
Darüber hinaus können assert
s weiterhin in nothrow
-Funktionen
verwendet werden, da diese fatale Error
werfen.
Die Laufzeitentsprechung zu assert
ist std.exception.enforce
,
die auffangbare Exceptions
wirft.