2013-12-16 34 views
32

コード契約をデバッグするときはどうしたらよいですか?私は方法の前提条件を確認したいと思うし、もう一方を選択するのは混乱している。私は、障害シナリオをテストし、例外を予想したいところで単体テストを行います。Debug.Assertとコード契約の使用

同じメソッドでDebug.AssertとCodeコントラクトを使用することをお勧めします。もしそうなら、コードを書かなければならない順序は何でしょうか?

Debug.Assert(parameter!= null); 
Contract.Requires<ArgumentNullException>(parameter != null, "parameter"); 

または

Contract.Requires<ArgumentNullException>(parameter != null, "parameter"); 
Debug.Assert(parameter!= null); 

その背後にある任意の論理的根拠はありますか?

答えて

28

これは別のものです。デバッグアサートは、コードがデバッグとしてコンパイルされている場合にのみ実行されるため、デバッグ時にのみチェック/アサートされます。考えているのは、開発中のコードに対してこれを「健全性チェック」に使用することです。コード契約は、デバッグまたはリリースで使用できます。彼らは、メソッドの前後の条件がメソッドの期待に従うことを保証します(契約を満たす)。同様の機能を提供するテストフレームワークもあり、テストコンプライアンスをチェックするために設計されています。

コードを開発するとき(および後でメンテナンスの開発時に)特定のことを期待したいときは、Debug.Assertを使用します。

デバッグとリリースの両方で条件が満たされるようにする場合は、コード規約を使用してください。契約では、プログラムが「正しい」ことを確認するのに役立つ静的分析の特定の形式も許可されます。

単体テストの作成時に、テストフレームワークアサーションを使用します。

+0

私は全く同意しますが、debug.assertとcode contractを同じ場所で使用することを選択した場合、それは特定の順序であるべきですか? – CarbineCoder

+0

そのようにダブルチェックを行う理由がわかりません。注文はやり方ではありません。もし私がそれをやっていたら、Debug.Assertを最初に開発用のデバッグ支援ツールとすると思います。 – Dweeberly

+0

Debug.Assertはリリースコードには含まれませんが、コード契約が適用されます。だから私は、コード契約と並行してdebug.assertが必要になるケースがあると思います。間違っているかもしれません。したがって、疑問。 – CarbineCoder

22

私はDebug.Assertと新しく書かれたコードの前提条件を強制するためのコード契約(IMOコード契約はDebug.Assert)の両方を個人的には使用しません。より包括的なチェックを提供します。コードが実行される前にの実行可能な静的検査がに実行されます。 Debug.AssertContractsの両方で重複した前提条件チェックを維持するのは面倒です。

理由:

  • あなたが再コードにあなたがDebug.Assertまたはthrowコードでコード化されている可能性のある従来の前提条件を必要としない - あなたは、既存の前提条件のチェックコードを保つことができるとterminate it with Contract.EndContractBlock()
  • あなたはがNoneに設定された契約実行時間チェックを使用してビルドする場合、/d:DEBUGを除いてビルドされている場合と同じチェックされていない「リリースモード」の動作を得ることができます。 Ref 6.2.1 in the Docs
  • 契約では、「無効な状態が検出されました」という意味で、開発者はコード内で表現力を高めることができます。帯域外のパラメータ(Contract.Requires)のためにそれは直接でした。そうでない場合は、Contract.AssertまたはContract.Assumeは一般的な状態をチェックでき、メソッドを終了したときの状態の "保証された正確さ"はContract.Ensuresを使って表すことができます。 Invariantsは、常にその状態を保持しなければならないことを表明します。
  • そして、スタティックチェックでは、コードをビルドするときにこれらのコントラクトを強制することができます。これにより、ランタイムを待たずにデザインタイムやコンパイル時間の警告でバグを拾うことができます。コンプライアンス違反を探すためにContinuous Integrationに契約チェックを追加することができます。

1つの警告:あなたが意図的に契約に違反するユニットテストを書くしようとしている場合、あなたはContractExceptionに対処する必要があるかもしれない - ジョンスキートはこのよくhereを説明します。例えばテストのセットアップでContract.ContractFailed handlerをハンドラに配線し、ハンドラにSetHandledを呼び出してから、あなたのUTで捕捉してアサートできるパブリック例外をスローします。

+2

良い説明。今私はそれを得る。一貫して使用される場合、開発者がアプリケーションの状態について途中で想定していることに非常に明確になります。そして、それはちょうどケーキのアイシングです。ケーキは最初からすぐに入れやすい、より詳細で完全な例外処理ルーチンです。 – jeremcc

+0

「Contract.Assert」がリリースビルドで終わらないことを確認するためのソリューション全体の構成設定があった場合にのみ、それらを使用します。さもなければ私は 'Debug.Assert'を使用します。なぜなら、リリースビルドに漏れないことを知っているからです。コード契約の設定保守は、IMOの最大の欠点です。 – orad

+0

パブリックインターフェイスの前提条件と事後条件に関する私の前のコメントを追加する私は消費者コードの使用のためにリリースモードにそれらを含める理由を知ります。しかし、私はどのような場合でもリリースモードでアサーションを含める必要がある理由は何もありません。私はそれについて十分に知らされていないかもしれません。 – orad

関連する問題