コードコントラクトと検証

.NET Framework 4 より、本格的にコードコントラクトがサポートされるようになったそうだ。
とはいっても、実際に検証するのは別のツールであって、コードにコントラクトが書けるように、標準のインターフェイスが準備されたことだ。

System.Diagnostics.Contracts名前空間以下のクラスを使用する。

public int Divide(int a, int b)
{
    // 事前条件
    Contract.Requires(b != 0);

<pre><code>return a / b;
</code></pre>

}

要するに、Debug.Assert() していたような所をこれに置き換えていく。事後条件の場合は Contract.Ensures() を使う。戻り値をチェックしたい場合は、Contract.Result() で戻り値が参照出来る。
例えば、負の数が許されない加算であれば、

public int Add(int a, int b)
{
    // 事前条件
    Contract.Requires(a &gt;= 0);
    Contract.Requires(b &gt;= 0);

<pre><code>// 事後条件
Contract.Ensures(Contract.Result() &amp;gt;= 0);

return a - b;
</code></pre>

}

という具合だ。

この時点で、「非常に魔術的」な香りが漂っている。特に、事後条件の Contract.Result() で戻り値が参照出来るだとか、そもそも事後条件が除算処理の手前にあったりして、本当にこれでいいのか?という感じがする。
実は、最初にインターフェイスが準備されただけ、と書いたのはこの部分の事で、このコントラクト定義を実際に使うには以下の条件を満たす必要がある。

・コンパイル時シンボル「CONTRACTS_FULL」が定義されていないと、Contractクラスのメソッド呼び出しは全て削除され、バイナリには一切含まれない。
・コントラクトの検証は、能動的には行われない。Debug.Assert() のように、書いた場所で直にコードが確認するわけではない。
 実際には一部の評価は行われるが、結局のところは「バイナリリライター」と呼ばれるライブラリが介在する必要がある。

で、それでは、Debug.Assert() と比べて何が嬉しいのか?という話になるのだが(ようやく本題)、コードに書かれたコントラクトをメタデータ(とMSIL?)から抽出して、その情報を元にごにょごにょ出来るようになるというところが違う。
Microsoftの実装では、「Pex」というプロジェクトでコントラクトを利用している。Pexは、ユニットテストコードを自動的に生成するツールとライブラリで、コードからコントラクト定義を抽出して、事前・事後条件などからユニットテストが実行すべきテストパターンを計算、「テストコード」を吐く。

恐ろしいww

いや、もちろん、完全な自動化テストは不可能ということは分かっているのだが、特にこの場合はどれだけコントラクト定義が綿密に書けるかということと、いかに普段からテスト可能コードを書けるかと言う事に尽きるのだが、それにしてもとうとうやっちまったかという感じがする。
PexはVS2010のProfessional以上で使用可能で、MSDNサブスクライバダウンロードから入手可能。また、Ultimateでは標準で入っているので、Microsoftとしてももはやこのプロジェクトは実験段階を超えていると判断しているようだ。

より詳しく知りたい場合は、以下のサイトを参照されたし。

MSDNマガジン:クラスにソフトウェア コントラクトを導入する
MSDNマガジン:Visual Studio 2010 における Code Contracts の設定
Microsoft Reserch: Pex and Moles (なにげにMolesも凄いのだが)
VS2010 後の世代のプログラミング (2) Pex

他にも、コントラクト定義を使ったこんなのもある。

Contractor.NET | A .NET validation and specification strengthening tool

.NET Framework 4 未満の互換ライブラリを書いているのであれば、ここにある前身バージョンを使えば、コンパイルは通るようになります。
(.NET Framework 2 からOK。ただし、バイナリリライターはないので、検証は出来ません)

DevLabs: Code Contracts