Murga

個人的に言いたいコト・主張・気持ち。

防衛的プログラミングと契約的プログラミングの違いがイマイチ分かっていない

防衛的プログラミング防御的プログラミングとかいう手法と、契約による設計だとか契約的プログラミングとかいう手法があるらしい。が、イマイチその違いが分からない。概念的な話ばかりで、コードに落とし込んだ時にどういう違いが出るのかを説明してくれている文献があまり見当たらない。

いくつかの文献を見てみて僕なりの解釈をしてみたが、しっくり来ていないので誰か教えてほしい。

僕の防衛的プログラミングの解釈

  • 呼び出し元も呼び出し先も関係なく、「この変数は null でないこと」「このファイルは必ず存在すること」といったチェックをしている。
  • 例外が発生してもその場でプログラムが止まらないよう、エラーを握り潰すような作り。
  • あらゆる箇所で「バグが起こらないように」とチェックしまくるイメージ。

僕の契約的プログラミングの解釈

  • 引数と戻り値に明確な仕様を決める。チェック処理はメソッド自身の In と Out に留まる。
  • 契約事項はアサーションでチェックする。引数のチェックと、実装の最後で戻り値をチェックする。守られていなかった場合は AssertionError 例外を投げる。
  • アサーションは本番ビルド時は削除される。
  • テストファーストで UT によって、あらゆる引数から戻り値を検証する方法もある。
  • メソッドの使い方を知らない人が使った時に、適切な例外を投げるイメージ。

僕のコードで比較する両者の違い

防衛的プログラミング

function readFile(path, fileName) {
  if(!path) {
    throw new Error('Illegal Path');
  }
  
  if(!fileName) {
    throw new Error('Illegal File Name');
  }
  
  let result;
  try {
    result = fs.readFileSync(path + fileName);
  }
  catch(error) {
    throw new Error('Could not read file');
  }
  
  if(!result.text) {
    throw new Error('Illegal File');
  }
  
  return result.text;
}

// 利用側の処理
const path = getPath();
if(!path) {
  throw new Error('Path is null');
}

const fileName = getFileName();
if(!fileName) {
  throw new Error('File Name is null');
}

const result = readFile(path, fileName);

なんていうんだろう、防衛的プログラミングは、「そのバグが起こりうるのは知ってましたから!対策ありますから!」みたいなイメージかなと思った。だから、throw new Error() の部分は、要件が合えば「上手くいかない場合は空文字を返す」みたいな作りにしても良いのかなーと思った。

で、呼び出し元の方でも、引数として渡す変数のチェックをしていたりして、冗長だけど絶対に「予期していないエラーはない」状態にすることが、防衛的プログラミングかなと思った。

契約的プログラミング

function readFile(path, fileName) {
  assert(!path);
  assert(!fileName);
  
  const result = fs.readFileSync(path + fileName);
  
  assert(result.text);
  return result.text;
}

// 利用側
const path = getPath();
const fileName = getFileName();
const result = readFile(path, fileName);

契約的プログラミングは呼び出し元でのチェックはせず、呼ばれた側が、自メソッド内で入力値チェックと出力値チェックをして終わる感じかなと思った。チェックもアサーションを使うのが特徴的というか、開発時だけエラーが検知できていれば、本番コードからはそのチェック仕様は取り除ける作りなのかな?と思った。

なんか勘違いしてそうなので、ご指摘賜りたく。

参考

セキュアプログラミング―失敗から学ぶ設計・実装・運用・管理

セキュアプログラミング―失敗から学ぶ設計・実装・運用・管理

  • 作者: マーク・G.グラフ,ケネス・R.ヴァンワイク,Mark G. Graff,Kenneth R.van Wyk,新井悠,一瀬小夜
  • 出版社/メーカー: オライリージャパン
  • 発売日: 2004/04
  • メディア: 単行本
  • クリック: 46回
  • この商品を含むブログ (35件) を見る

[rakuten:com-books:10116078:detail]