"TDD" Boot Campに参加してきた


http://www.flickr.com/photos/lassekoskela/4202802224/in/set-72157623041486184/

"TDD" Boot Campに参加してきた。TDD = Test Driven Development = テスト駆動開発を実践しよう、というイベントである。

このイベント、前評判が高く、即日定員オーバーになったと聞いている*1。私は幸運にもTwitterのTLを眺めていたら定員まであと5人の時点でキャッチできたのである。有用すぎるぞ、Twitter。そしてその評判に負けない、実戦的で実に有益なイベントだったと思う。
TDDというのはなかなかに実践が難しい。JUnitでテストケースを書いておけばTDD、なんて単純なものではない。TDDはツールやテクニックではなくプロセスであり、これまでの開発習慣を大きく変えねばならない。それでうまく導入できず長らくつまづいている自分にちょっとしたテコ入れをしたかったので、迷わず飛びついた次第。

前半戦

id:t-wada氏、および特別ゲストのLasse Koskela氏によるプレゼンテーションである。

Session 1

id:t-wada氏によるオープニングとなるプレゼンテーションは、なるほどこれがZenってやつか、とうならされるわかりやすい表現で、内容もTDDへの導入としてこれ以上ないものであった。スライドはこちらに公開されている

曰く、TDDでは「テスト失敗」「テストをパスするコードを書く」「リファクタリングする」という3つのアクションをすばやく回転させて(黄金の回転*2)、漸進的に洗練させて「きれいで動くコード」を作っていく、とのこと。

不安がある場合はそれが顕在化しないことを祈るのではなく、この回転に乗せてしまう、つまりテストとして書き起こしてこれを突破するコードを書くことで解消していく。そうして「健康」を獲得し、さらに維持していくための取り組みがTDDであるという。まさかここで「健康」などというフレーズが出てくるとは。しかし不思議としっくりくる。

このプレゼンテーションあらばTDDの修得 = テスティングフレームワークの使い方を覚えること、という初歩的な誤解はあっさりと砕かれ、続く実践に取り組む姿勢も変わろうというものだ。単なる挨拶とは異なり意義のあるオープニングであった。

Session 2

Lasse氏のプレゼンテーションの前半は、TDDの効果についての説明と、TDDを実践するために必要なものについての話である。

TDDを行うためには、次の3つが必要だという。

  1. 設計センス
  2. リファクタリング技術
  3. ツールの習熟

リファクタリング技術」が挙げられている点が重要である。id:t-wada氏の説明でもリファクタリングは黄金の回転に組み入れられていた。TDDにおいて、リファクタリングは余裕があればやるという取り組みではない。TDDにリファクタリングは必須なのだ。

また、「ツールの習熟」が挙げられている点は興味深い。ツールはいちいち考えることなく、手足のごとく使えてしかるべきである。そんな雑事からは自分の頭を解放し、より重要な事柄、例えば設計などを考える余裕を持たせるべきなのだ。

後半はレガシーコードでTDDするにはどうするか?というテーマであった。

レガシーコードでTDDを実践するのは難しい。なぜなら、既存のテストコードが存在しないからだ。また、レガシーコードはそもそもテストケースを書きやすい構造になっていないことが多い。そのためテストコードを書けるようにリファクタリングする必要があるが、リファクタリングするためにはテストケースが必要である。鶏が先か卵が先か?

そこで、次の手順に沿ってTDDを導入するのがよいらしい。

  1. 変更点を探す
  2. テストすべき箇所を探す
  3. "縫い目"を入れる
  4. 現在の動作の再現テストを書く
  5. 失敗するテストを書く(ここからTDD!)

"縫い目"とは、テストのための処理を差し込むための箇所である。例えば、privateメソッドをprotectedにすればオーバーライドによるテスト用処理への差し替えが可能になる、といった変更可能ポイントを指している。Tシャツの袖を付け替える場合、袖の根本の縫い目をほどいて別の袖に付け替えるだろう、というメタファーらしい。

そして、実際にレガシーコード(今回はCobertura)へのテストケース追加デモが行われた。extract methodやアクセス権限を緩めるといった安全な変更("縫い目"の挿入)から始めて、徐々にTDDへの準備が整う様は圧巻であった。

ところで、この取り組みでアクセス制限を緩めた場合、テストが終われば元に戻したくなるかもしれない。メソッドをprivateにしているのはそれなりの意図があってのことだろうから。その場合、「戻すべきだが、元の形に戻すわけではない」そうだ。リファクタリングを繰り返して、より洗練された形に直すのだ。

ちなみに、Lasse氏は続く実習のお題にも取り組んでおり、本イベントの最後にそのコードが公開された。Ruby + Test:Unitによるものであったが、テストケース作成のエッセンスが凝縮され、さらにRuby動的言語としての性質をうまく活用した、とても参考になるコードであった。TDDの達人ってすごいな。参加者にはメーリングリストを使って配布されたのだが、どこかで公開されてるのかなぁ?

後半戦

参加者みんなでノートPC持ち込んで、実際にペアプログラミングしつつTDDを実践しよう、という内容で、一度のペア交代を入れて都合2人の方とペアプログラミングさせていただいた(@kappa4さん、@sanematさん、その節はどうも!)。

ちなみに言語はRubyを選択、テスティングフレームワークRuby界に確固たる地位を築きつつあるRSpecである。*3お題は「LRUCacheを作る」。基本的にハッシュ(Map)なのだが、最近利用したデータを指定したサイズまでキャッシュしておく構造を持つ。また、余裕のあるペアにはさらに仕様変更が言い渡されていた。*4

ペアプログラミングは有益である。自分一人では得られなかった視点が得られるし、それによりくだらないミスは即座に修正される。また、なにか詰まることがあっても、相談にのり、一緒に立ち向かってくれる相手がいる、というのは非常に心強い。

そして、テストファーストという取り組みは非常にすばらしい。コーディングしている時点で「ユーザとしての視点」が強制的に導入されるため、自然ときれいなインタフェースおよび十分なエラー処理が書かれるようになる傾向があると思う。実際、私のペアで書いたコードはエラー処理を優先することになった。

こうしたメリットについては書籍を読めばそう書いてあるものだが、ちゃんと取り組んでそれを体感できたのが大きい。

さらに有用な取り組みとして、プロジェクターを利用したコードレビューがすばらしかった。各ペアで書いたコードをスクリーンに映して、他の参加者の方々にレビューしてもらうのである。添削してもらえるのも、人のコードを読むのも勉強になる。しかも、日常ではまず見られないであろう、まったく同じ機能の別実装である。比較対象としてこれ以上のサンプルがあるだろうか?この手の技術イベントは必ずコードレビューを含めるべきだと思った。せっかくエネルギーが高い人々が集まるというのに、自分だけコード書いて終わりにするなんてもったいない。むしろ無意味。

ちなみに私がペアで作成したコードはGithubに上げてある。履歴が適当すぎるのは勘弁。もともとバージョン管理していなかったのだが、とある事情により公開サーバにコードを置かねばならなくなってやっつけでコミットしたのである。

総括

以上、私が奮闘して興奮している様子が伝わっただろうか?伝わらないかもしれないが、実際に集中しすぎて終了時間には極度に疲弊し、懇親会ではまともに話すことができなくなるほどだった。技術イベントにはいくつか出ているし、その中には実習を伴うものもあった。しかし、気づいたら20時過ぎてました、というほどにのめり込んだものは初めてである。単なる"写経"ではない実戦的な内容だし、参加者のみなさんのモチベーションも技術力も高く、自分もグイグイ引っ張られた。

重ねて言うが素晴らしいイベントだった。これは是非とも第二回の開催に期待したいところ。

*1:別のイベントの懇親会id:t-wadaさんに伺ったところ、運営側でも予想外の事態だったそうで。

*2:Steel Ball Runですな!

*3:ちなみに参加者の半数がJava選択、あとはC#Rubyで、1ペアだけPythonであった。

*4:http://d.hatena.ne.jp/t-wada/20091219/p1 のスライドの最後にお題がまとめてある。