先週末のわんくま東京勉強会、ひさしぶりに懇親会に出たなり。
ま、それはそれとして、中さんのセッション: Spec# は面白かたあるよ。
DbC(Design by Contract:契約による設計) / PbC(Programming by Contract:契約プログラミング)
はEiffelやDあたりがサポートしてるんだけど、そいつをC#でもやっちまえって魂胆ね > Spec#
従来
class Base {
public virtual int func(int x) {
Debug.Assert(x > 0 && x < 10); //事前条件: x = 0..9 でなければならない
....
int result = ごーにょごにょ
Debug.Assert(result >= 0); // 事後条件: 0以上を返すことをここに誓う
return result;
}
}
なんてな Assert で利用者が守るべき契約(事前条件) 提供者が守る契約(事後条件) を
コード上に明記しよう。そうすることでより堅牢でバグの少ない(あっても直ちに判明する)
コードを書こうや、と。
# 不変表明(invariant)ゆーのんもありますがー
ここで問題となるのが、派生クラスで func をoverrideしちまったとき、
Base::funcに埋め込まれた契約条件がoverride側に適用されんです。
で、こいつの解決策のひとつがNVI(Non Virtual Interface)ってイディオム。
「利用者にvirutalなメソッドを晒すなボケェ」てことっす。
んじゃどーするかっちゅーと:
class Base {
public sealed int func(int x) {
Debug.Assert(x > 0 && x < 10); //事前条件: x = 0..9 でなければならない
int result = do_func(x);
Debug.Assert(result >= 0); // 事後条件: 0以上を返すことをここに誓う
return result;
}
protected virtual int do_func(int x) {
return ごーにょごにょ;
}
}
こーしておく。派生クラスはfuncから呼ばれてる do_func をoverrideするのね。