assertについて調べていたら、契約プログラミングという言葉に行き着いて、それについても調べました。
わたし訳だと、デバッグビルドでは特定の値を強制するコードが実行され、リリースビルドではその検査をするコードが含まれないという方法みたいです。
C/C++ではassertがこれの役割を果たしています。assertはただのプリプロセッサマクロなんですが、契約プログラミングをサポートする言語もあるそうです。
(wikipedia):
http://ja.wikipedia.org/wiki/%E5%A5%91%E7%B4%84%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0
D言語も契約プログラミングをサポートする言語の一つだそうで、事前条件 (precondition) 、事後条件 (postcondition) 、不変条件 (invariant)を完全にサポートしていました。中でも不変条件はメソッド一つ一つに検査する関数を挿入するのは骨が折れます。
(参考):
http://www.kmonos.net/alang/d/2.0/cppdbc.html
事前条件と事後条件は、コンストラクタとデストラクタを使えば簡単に実装できると思います。
D風に書くと(名前とかだけ)
template
struct contract {
contract(T const& arg, std::function in, std::function out)
: arg_(arg), out_(out)
{ in(arg); }
~contract() { out_(arg); }
private:
T const& arg_;
std::function const out_;
}; // struct contract
といった感じでしょうか。Squirrelのスタックを監視するコードもこんな風に書きました。デストラクタは便利です。
Boost.ScopeExitを使えばもっとマシなコードになると思うんですけど、よく知らないので今回は使っていません。
そういえば、assert内では副作用のあるコードを入れられないのがけっこう不満だったんですが、BOOST_ASSERTのページ読んでいて、BOOST_VERIFYという副作用のあってもいいマクロを知りました。早速、使ってます。(
http://www.boost.org/doc/libs/1_48_0/libs/utility/assert.html )
テストを書くよりも契約プログラミングの方がわたしには書きやすいので、こっちの方をどんどん使っていこうかと思います。