Dの契約プログラミングはコードベースが期待通りに振る舞うことを確実にする サニティ・チェックを反映させることによりコードの質を向上させることができる 言語構成体群を含みます。契約はデバッグモードでのみ利用でき、 リリースモードでは実行されません。したがってユーザの入力を 検証するのに使われてはいけません。
assert
Dの最も単純な契約プログラミングの形はassert(...)
式で、
これは一定の条件を満たすかをチェックし、
そうでない場合はAssertionError
でプログラムを中断します。
assert(sqrt(4) == 2);
// 任意のカスタムアサーションエラーメッセージ
assert(sqrt(16) == 4, "sqrt is broken!");
in
とout
で入力パラメータと関数の返値の契約を形式化することができます。
long square_root(long x)
in {
assert(x >= 0);
} out (result) {
assert((result * result) <= x
&& (result+1) * (result+1) > x);
} do {
return cast(long)std.math.sqrt(cast(real)x);
}
in
ブロックの中のコンテンツは関数の本文中に表現することもできますが、
この方法のほうが意図が明確です。out
ブロックの中で関数の返値は
out(result)
でキャプチャしそこで検証されます。
invariant()
はstruct
やclass
型の特殊なメンバ関数で、
オブジェクトのライフタイム全体におけるその状態のサニティ・チェックを行うものです:
invariant()
はメンバ関数を抜けたあとに呼ばれます。
すべての契約はリリースビルドで削除されるため、ユーザ入力は契約を使って検証されるべきではありません。
加えて(訳注:例外ではなく)致命的なErrors
を投げるため、assert
はnothrow
関数で使うことができます。
実行時のassert
の類似物はstd.exception.enforce
で、
これはキャッチできるExceptions
を投げます。