契約による設計 (DbC)

関数に入るとき, 関数から出るとき, あるいはクラスの特定の状態において, 絶対に成立していなければならない条件をプログラムに記述することで, バグの発見 を容易にすることができる.

なお, -release オプションをつけてコンパイルすればテストコードを含まないバイナリ を生成する.

事前・事後条件 (関数)

inout.d

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
import std.stdio;
import std.math;

double squareRoot(double x){
  in{
    assert (x >= 0);
  }
  out(result){
    assert( (result * result) == x);
  }
  body{
    return sqrt(x);
  }
}

void main(){
  writeln( squareRoot(100) );
  // writeln( squareRoot(-100) ); // AssertError InException
  // writeln( squareRoot(5) ); // AssertError OutException
}

事前条件 in, body 節に入る直前に実行される.

事後条件 out, body 節から出る直前に実行される.

事前・事後条件 (インタフェース)

契約は interface にも書くことができる. その際は body 節はない:

interface I{
  int foo(int n)
    in{
      assert(n > 0);
    }
    out(result){
      assert(result < 100);
    }
}

不変条件

import std.stdio;

class Date{
  uint month;
  uint day;

  this(){
    month = 1;
    day = 1;
  }

  void setDate(uint m, uint d){
    month = m;
    day = d;
  }

  invariant{
    assert(1 <= month && month <= 12);
    assert(1 <= day && day <= 31);
  }
}

void main(){
  Date date = new Date;
  date.setDate(10, 7);
  // date.setDate(13, 7); // AssertError
}

不変条件 invariant, コンストラクタ完了直後, デストラクタ実行直前, public/export メンバ関数の実行前後にチェックされる.

Table Of Contents

Previous topic

マルチスレッドプログラミング

Next topic

遅延評価