Design by contract (2)

dbc.lisp をほんの少しだけ使ってみた。※以下の例はいまいち。

;; stack pop
(defgeneric stack-pop (st)
  (:method-combination dbc))
;; pop の本体
(defmethod stack-pop ((st stack))
  (vector-pop (items st)))
;; 事前条件 スタックは空でないこと。スタックが空なのに pop を呼び出したら呼び出した側の責任。
(defmethod stack-pop :precondition ((st stack))
  (not (stack-empty st)))

不変条件は、定義しておけば、自動的にメソッドの呼び出し前後に実行される。

現時点での感想。

 もちろんフレームワーク無しでもやれることだが、徹底してくれるのが嬉しい。本体はシンプルに、事前事後条件は明確に分離して書ける、のは奇麗だ。教科書にのってるような簡潔さを保ちつつ、実際は業務のプログラムのように泥臭くチェックをしている。

  • つまらないバグを減らしてくれるとは期待できる。

ただ、かなり意識的に条件を書けないと無意味。

  • 強い型の言語の型も契約の一種?
  • でも結局ランタイムでのエラーチェックでしかないのだろうか?

後でもうちょっと良い例を考える。