postconditionという用語の定義に依存します。一般に、事前条件はルーチン入口での入力状態と入力値の関係であり、事後条件はルーチン出口での入力状態と入力値、出力状態と出力値の関係です。
ルーチンは正常終了または例外終了のいずれかで終了できるため、正常終了の事後条件と異常終了の事後条件を定義できます。明らかに、どちらも入力値、入力状態、および出力状態を含みます。主な違いは出力値にあります。最初のケースでは、これはルーチン シグネチャで指定された値であり、2 番目のケースでは、言語によって異なります。あなたの例では、NoPathException
、しかし、メモリ割り当てエラー、スタックオーバーフロー、または署名で指定されていないその他の例外またはシグナルがある場合はどうなりますか? 例外を伴わない有効な結果が常に存在することを保証する前提条件を持つことは、実際に可能であるように思われるかもしれません。しかし、これは当てはまりません。たとえば、外部世界への通信、並行性などがある場合です。また、前提条件の計算コストが高すぎる場合、同じ作業を 2 回行うのは見栄えがよくありません。呼び出しは適用可能であり、サプライヤー側で結果を得るために本質的に同じ計算を行います。
Design by Contractの哲学によれば、事後条件は、クライアントがルーチンを呼び出した後に安全に信頼できるものです。例外的なケースに戻ると、実用的な観点から、プログラムが実行を継続できるように異常な事後条件を十分に強くすることは理にかなっていますが、署名で指定されていない、または指定できないケースを十分に弱くすることは理にかなっていますが、実際には可能であり、許可されています。
したがって、言語がすべての可能な例外的なケースを本当に保証しない限り、最も重要な部分は、関連付けられたオブジェクトを使用不能にしない出力状態です。これは、明示的または暗黙的な事後条件で、またはクラス不変条件として表現できます。
の具体例getPath
については、パスが存在しない場合が正常、つまり発生する可能性が想定されます。一部のガイドラインでは、通常の終了ケースを示すために通常の値を使用することを推奨しています。ここでは value になりますnull
。を使用すると、結果が null であるかどうかがチェックされない場合null
など、呼び出し側で他の問題が発生する可能性がありますが、そのような例外がないことを保証する一部の言語 (たとえば、 Eiffelの void-safety ) では、これを示す方法として推奨されます。パスの不在 (戻り値の型はその場合になります)。NullPointerException
detachable PATH