Design by Contract (DbC)
事前条件、事後条件、不変条件、を契約せよ
プログラム設計の安全性を高めるための設計手法です。
DbCの3つの契約~事前条件、事後条件、不変条件
あなたのクラス/メソッドは、それを使う人に対し、以下の3つの契約を交わします。
- 事前条件 メソッド開始時に、呼ぶ側が保証すること
- 事後条件 メソッド終了時に、呼ばれた側が保証すること
- 不変条件 メソッド開始時および終了時に、オブジェクトが保証すべきこと
事前条件 (precondition)
メソッドを呼び出すときの入力値には、この範囲の値しか受け付けられない、この文字は空であってはいけない、など条件付きとなる場合があります。
例えば「平方根を求める」メソッドなら、その入力は0以上でなければなりません。(そうでないと計算できない)
メソッドを呼び出す側は、メソッドが正常動作する入力を与える、これが事前条件です。
事後条件 (postcondition)
事前条件が満たされると、メソッドが実行され、結果が返却されます。その結果は呼び出し元の求めるものとなっている必要があります。
「平方根を求める」メソッドなら、input=result*result となっていることが、求める結果です。
メソッド側は、メソッドを呼び出した側に期待する出力を返却する、これが事後条件です。
不変表明 (invariant)
メソッドを呼ぶ前も呼び出した後も、クラスがその外部に公開しているすべての操作について、開始時と終了時に保証されるべき性質です。
例えば、balance == sum(entries.amount()) といった条件は、いつでも成立している必要があります。
クラスは、公開するすべての操作について常に約束された状態を守る、これが不変表明です。
表明(assert)による契約の確認
契約を結んだら、その契約が守られているかを確認する必要があります。
契約による設計での、確認の基本は「表明」(assertion)です。
表明とは
表明とは、必ずfalseにならない真偽式です。例えば「平方根を求める」メソッドなら
- 事前条件の表明 input ≧ 0
- 事後条件の表明 input=result*result
となります。
表明が false となったとき、それは契約違反があることを示します。
assertによる表明の実装
C,C++,C#,Java,Pythonなど、多くのプログラム言語では、assert と呼ばれる機構が備わっています。
assert input = result * result
ほとんどの場合、assertは、false となった時点で即時にプログラムが停止します。false、つまり契約違反となるのはバグであり、回復不可能だからです。
このことからも分かるように、assertはバグを検出するためのものです。
通常発生しうる状態(バグでない状態)に、表明(assert)を使ってはいけません。
assertは、どのプログラミング言語でも「リリーズ時は無効とする」オプションが備わっています。
契約による設計の利点
クラスの頑健性があがる
契約による設計は、「クラス内部で何をするか」ではなく、「クラス外部に何を約束するか」に着目します。
結果、そのクラスが持つべき責任が明確となります。外部からの使い方も明確になり、不具合の少ない頑健なクラスができます。
テストによる品質確認が容易
契約による設計によって設計されたクラスは、ユニットテストによる品質確認も容易となります。
そう「契約が守られているか」を確認すればよいのですから。テストケースも明確になります。
テスト駆動開発との相性は抜群です。【テスト駆動開発】TDDの実践方法と、メリットと注意事項
まとめ
クラス設計時にはついつい、その中身をどうするか、に心を奪われてしまいがちです。
そうすると、使う側にとってはいまいち使いにくいクラスができあがります。
「契約による設計」を使うと、クラスを使う側の視点に立った設計ができます。あなたのクラスを強固なものにしましょう。
コメント