背景
チーム開発を念頭に置いて『テスト駆動開発』を読みました。テストの無いコードは、境界値の洗い出しすら行われていないコードですから、十中八九バグっていると思います。そう思う僕自身にテストを書く習慣が無かったため、ヒントを求めて定番の古典を読んでみました (原著: Test Driven Development: By Example by Kent Beck, 2002) 。
テストと言えば、僕の中では『低レイヤを知りたい人のためのCコンパイラ作成入門』 (通称 compilerbook) です。この本ではインクリメンタルな開発の重要性が繰り返し説かれています。特に個々のモジュール (lexer, parser, ast, generator) 毎に完成させるのではなく、全てのパスを少しずつ拡張し、小さなプログラミング言語を育てていくスタイルが特徴的でした。
以上の通り、テスト駆動開発 (TDD) によって強い制約を受け、より良い方向に開発を導いてもらうことに期待がありました。
感想
内容が古くて頭に入ってきませんでした。 20% 程度しか吸収できなかったと思います。以下では主に不満点を述べます。
気分が悪くなるかもしれません、ご注意ください!
第 I 部『多国通貨』では、ドルやユーロといった通貨の計算をボトムアップに実装します。最終的に計算式の木を作ることになりますが、それは僕が一番最初に考えた方法であったため、現代の基準では単なるリサーチ不足に見えました。
第 II 部『xUnit』では、 xUnit (JUnit 等をまとめて指す言葉) の基礎的な部分を Python 2 で再実装します。 Java がクラスベースであったり Python (< 2.3) に bool 値が無いなど、余計なノイズが多かったです。僕のほうが本に付き合ってあげた気持ちになりました。
第 III 部『テスト駆動開発のパターン』では、 TDD に利用できる具体的なテクニックが紹介されます。これも有り難みを感じづらく、 ValueObject などは言語設計の問題と理想の間のギャップを埋めるものに過ぎません。そしてリフレクションを勧めてくれるな!
もちろん個々の内容としては面白く役に立つものが多いのですが、大量のノイズに押し流されてしまいました。まとめページがあると嬉しかったです。自分用のメモとしては、以下の通り実戦してみたいと思います:
- まずテストを書き、失敗させるべし
- テストは assertion から入力の順 (最終コードの逆順) に書くべし
- テストを通して API を設計すべし
- テストは assertion から入力の順 (最終コードの逆順) に書くべし
- テストで吟味した設計を元に、プログラムを書くべし
- 実装をべた書きし、コード変更を最小にせよ
- 実装をべた書きし、コード変更を最小にせよ
- テストを通過したらリファクタリングを始めよ
- べた書きを一般化せよ
- コードの重複を削除せよ
- べた書きを一般化せよ
- 以上のサイクルを 5 分以内に行え
付録 C (本書の 10%) は t-wada さんによるテストを俯瞰した解説です。『アジャイルテストの 4 象限』に照らし合わせると、 TDD は左下の象限にあたる (が、『テスト』という言葉の意味が広過ぎて、歴史上正しく意図が伝わらなかった) 模様です。僕が興味ある部分を意訳すると:
- TDD とは開発プロセスであり、プログラムの変更のサイズを自身でコントロールしながらチェックを走らせて行く開発スキルを活かすこと
- BDD とは TDD 中のテストが public API の単体チェックであることを明確にするものであり、ついでにテストの書き方 (
describe
で context を区切るなど) が付いてくる
上記は間違った意訳ですが、ひとまず自分に都合の良く理解しておきます。幸い『テスト駆動開発』は t-wada さんが全てを分かってくれているので、たまに t-wada さんの方を見れば、そこまで迷走せずに済むはずです。
まとめ
名著『テスト駆動開発』を読み、 TDD の文脈が以前より理解できるようになりました。あまりチーム開発とは関係が無く、俺様が都合よく開発するためのサイクルを回すことだと認識しました。そんなに趣味に寄ったトピックだったとは……。
変更の粒度をコントロールし、小さな変更を積み重ねるテクニックは、リファクタリングにおける一般的なテクニックです。テストが無い場合にも適用できると思います。しかしこの手の内容はほとんど吸収できなかったため、時々本書を見返す必要がありそうです。
テスト駆動開発 (TDD) とプロパティベーステスト (PBT) は相性が良いと思います。 PBT ではランダムテストの失敗時に、テストケースが収縮します。したがって初めから抽象的なテストを書くことができ、しかも失敗時には最小の失敗ケースを目にすることができます。
乱数を試す代わりに、最小値から一定値までを網羅的にテストしてくれても良い (単なるランダムテスト、
for
文が良い) 気もします。ここが PBT ライブラリのよく分からないところです。
TDD と PBT を活かして、一段上のプログラマを目指して行きたいと思います。