IDDD本で契約プログラミングという言葉が出てきて、ちょっとよくわからなかったので調べつつ、Goのコードに落とし込んだらこうなるのかな、というまとめ
契約プログラミング
「不変条件」、「事前条件」、「事後条件」で構成される「契約」を考慮してクラスを設計することで安全性を高めようというもの。
不変条件(precondition)
クラスが持つ公開された全てのメソッドの開始・終了時点でクリアすべき条件。ざっくりいうと「クラスのメンバに対する条件」。なお、Wikipediaによると、
ただしコンストラクタ[注 7]の呼び出しに関しては、事後条件としてのみ適用され事前条件として保証する必要はない[13]。
事前条件(postcondition)
メソッド開始時にクリアすべき条件。ざっくりいうと、「メソッドの引数に対する条件」 + 「不変条件」
事後条件(invariant)
メソッド正常終了時にクリアすべき条件。ざっくりいうと「メソッドの返り値に対する条件」 + 「不変条件」。
Goでの実装
Goの構造体に対して契約プログラミングしようとすると、それぞれの関数・メソッドに対しては以下のチェック処理の実装が必要になるのかなーと思う。
- コンストラクタ(関数)
- 事前条件チェック: 引数チェック ※1
- 事後条件チェック: 戻り値チェック + フィールド値チェック(不変条件)
- フィールド値の変更を伴わないメソッド
- 事前条件チェック: 引数チェック + フィールド値チェック(不変条件)
- 事後条件チェック: 戻り値チェック ※2
- フィールド値の変更を伴うメソッド
- 事前条件チェック: 引数チェック + フィールド値チェック(不変条件)
- 事後条件チェック: 戻り値チェック + フィールド値チェック(不変条件)
※1: 不変条件チェックがないのはそもそもまだインスタンス化してないわけで、そもそもできないし。
※2: 不変条件チェックがないのはフィールド値の変更を伴わないならやってもしゃーないし(とはいえ本当に変更してないよね?という意味も込めてチェックするのはありなのかもしれないけど)
これを踏まえて、以下の状況を例として実装してみた。
- 「得点」フィールドのみを持つ「学校のテスト」構造体
- 得点は0〜100の間
- コンストラクタ定義する
- 加算メソッドを定義する
参考