2016年6月5日日曜日

「テスト書け」が馬の耳に念仏になる原因

vgs-cpuをgithub上でモリモリ設計中。
https://github.com/suzukiplan/vgs-cpu

この記事執筆時点のcommit
https://github.com/suzukiplan/vgs-cpu/commit/29f8cbe684dd1489fcb3a8b3cfffbbc52a6757cd

CPUのコードを書くのって完全なる単純作業です。
こういう単純作業だと割りとバグを作りこみ易いです。
なので、こういう場合はテストを書くのが重要。

という訳で、このリポジトリを git clone して make を叩けばテストを流すようにしました。(※Mac or Linux限定で、Windowsには対応していませんが...)

プログラムを書いたことがあれば、「テスト書け」なんて耳にタコができるほど言われることで、馬の耳に念仏状態かもしれませんが。

テストを書く目的は、
1. バグの早期摘出
2. エンハンス時のデグレード防止
の2つしかありません。

1の理由は、後工程で見つけると原因を特定するのに掛かる時間(摘出コスト)が指数的に増加するためです。これは古典的なウォータフォールだろうが、アジャイルだろうが同じことです。

vgs-cpuのレジスタAに対するスタック操作(push/pop)、メモリ移動(load/store)、インクリメント、デクリメント、NOT演算のコード規模はだいたい100ステップぐらいですが、テストを書いてみて摘出できたこの部分のバグは以下の3件です。

bugfix: notの演算結果が不正
https://github.com/suzukiplan/vgs-cpu/commit/9b4f49235a60d63202a0f753d1233768284f4810

bugfix: inc, dec, not で プログラムカウンタ の インクリメント漏れ
https://github.com/suzukiplan/vgs-cpu/commit/f31ddfbf9f355a590e78448c858f905e1c81e47e

bugfix: VGSCPU_OP_POP_A4 (2byte -> 4byte)
https://github.com/suzukiplan/vgs-cpu/commit/53ca01c247086f886758a4bb7dfc3a4931849558

これらを早期に潰すことで、最小のコストで品質を担保できます。

で、スタック操作(push/pop)、メモリ移動(load/store)の命令群には、この後メモリ検査のエンハンスが入る予定ですが、これらのテストを全て自動化しておくことで、エンハンスを入れた時にデグレードが発生しないことを保障する訳です。

ちなみに、「単純作業だと割りとバグを作りこみ易い」と上述しましたが、だいたいの人が1ks(千行)のプログラムを書いた時に作り込むバグの件数というのは、統計的に10〜15件なので、100行で3件(ksあたり30件)という具合に実際多い。

ただし、ある程度作り慣れてくると、バグの作り込みパターン(バグ知見)が脳内に蓄積されることで(主に同件の)バグを作り込む確率が減ります。

プログラムを書く時、面倒臭いから 全部作ってから後でテストすれば良い という考え方の人が結構居ると思います。少し話は飛びますが、プロジェクトの特性として「新規性」というものがありますが、これは要するに「無いものを新たに作る」という事です。既にあるものなら、わざわざ新規に作らなくても既にあるものを使えば良いですからね。で、新規性という特性を持つ以上、バグ知見が十分に足りていない可能性がものすごく高いという事は自明です。(成熟度が低い組織だったり新規性が高い分野のものづくりをすると、似たようなものを作るケースも多々ありますが)

だから、今回のvgs-cpuの開発では、スタック操作(push/pop)、メモリ移動(load/store)、インクリメント、デクリメント、NOT演算のだいたい100ステップぐらいのコードが出来たところで、一旦開発を止めて徹底的にテストすることにしました。バグ知見が十分に溜まったところであれば、テストを省略しても問題無いと思います。バグ知見が十分に溜まったところでもガリガリテストを書くのは過剰品質(テストを作るコストが品質に寄与しない)という感じになります。

「テスト書け」が馬の耳に念仏になる原因はソコにあります。