SE Can't Code

A Tokyo based Software Engineer. Not System Engineer :(

Reproducing Failures.

ソフトウェアに不具合があった場合、不具合の元となるバグを再現することによってデバッグ実験の観察を行わなければならない。実験の結果、バグに対する修正を行うことになるが、修正に対してチェックするためにはバグを再現させる必要があり、再現性なくしてバグのFIXはあり得ない。

Bug's Category

バグは大きく4つに分類することができる。

#Bug's CategoryDetail
1Bour Bug明確な条件下で反復するバグ
2Heizen Bug検出するプログラムによって動作を変えたり消えたりするバグ
3Mandel Bug根底原因が複雑性/非決定性で不明瞭なバグ
4Schroding Bugプログラムが全く動かないことに気づくまで現れないバグ


これら各分類に対してバグの性質を当てはめて、対応を考える必要がある。例えば通常実行とデバッガでの実行とで動作が変わるHeizen Bugの場合だと、デバッガのテスト実行の際の条件との差異を洗い直すといったところに当たりをつけるといった対応が簡単な例となる。

Abstraction level

ユーザインタラクティブな機能におけるバグの再現性はキャプチャリプレイツールを利用する。キャプチャリプレイツールは、ユーザによるイベントの発生といった外部入力値をキャプチャをして、入力間に対して自らを挿入するレイヤのような働きをする。キャプチャリプレイツールには二つの機能がある。

  • イベントをログに出力するキャプチャ機能
  • ログを元にイベントを再現するリプレイ機能

ここで問題となるのは、どの抽象化レベルのイベントをキャプチャするのかという問題である。例えば、マウスのクリックイベントをキャプチャしようとした時に、Web上の位置を指すピクセル位置でキャプチャを取った場合、リプライツールによる再現はできない可能性を生む。サイズやスピード、プログラム自身の変更によって左右される抽象化レベルは再現性が低いために、イベント自身の振る舞いを元にしてキャプチャを取るようにする。つまり、キャプチャがスクリーンのレンダリングから独立する抽象化レベルを選択すると良い。

Record and Replay

バグの再現性担保のために事前にログへの保存と再現用のスクリプトを作る。実行されたファンクションを文字列として保存し、eval関数を用いて再実行を行い、traceと同様な出力形式となるメカニズムにする。

このようなメカニズムを取ることで、プログラム間のインタラクションのみでなく、プログラムとその環境間のインタラクションも記録できる。大事なことは、実行された処理をリストやマップといった構造された形式で外部保存して、常にリトライを行えるようにしておくということである。
またこれらは静的な要素に対するdebugと言えるが、非決定論的な動的要素に対しては決定論的に制御可能となるように意識して再現させる必要がある。例えば、時間や乱数生成、非決定的にスレッドを切り替えるマルチスレッドのスケジュールに対する対応等が挙げられる。

Capturing Coverage

プログラムの特性の集合から、統計学的にそのプログラムの実行特性を捉えることができる。例えば、必ずパスする実行においてはf( )関数が呼び出されず、必ず失敗する実行においてはf( )関数が呼び出されていた場合、f( )関数にバグが埋め込まれている可能性を推測できる。
下記のスクリプトは実行された行に対して印をつける処理を行っている。アサーションの実行をチェックすると一つだけ失敗している処理が判明し、問題となる箇所はそれぞれの処理についている印を元にして原因箇所の洗い出しを行うことができる。


Phi Coefficient

debugにおける適用範囲と実行結果の統計的相関を計算するためにはファイ係数を用いる。ファイ係数は、相関のインジケーターとして知られているピアソンの積率相関係数を2行×2列のクロス表に適用したものである。

{ \displaystyle
\phi = \frac{ad-bc}{\sqrt{r_1r_2c_1c_2}}
}

分子である一つの対角の値(ab)が高く、もう一つの対角の値(bc)が低い場合はファイ係数が高くなり、値が1に近いほど相関が強くなる。プログラムの各行に対してファイ係数を計算し、相関の強さによって各行をランク付けすることで、失敗と適用範囲の相関の強さを表すことができる。


現場からは以上です。


From

www.udacity.com

Remove all ads