TDDBootCampFukuokaに参加してきたので、TDDについて改めて考えてみた。
6/15(土)、6/16(日)の2日にわたって開催された、TDDBootCampFukuokaに参加して来ました。 課題については他の参加者の方が説明されているので、コードだけ共有しておきます。1日目はgithubを使っていなかったため> < 、2日目の分だけ・・・
https://github.com/shimesaba-type0/ruby_rspec
(ペアの@shimesaba_type0さんがレポジトリ上げてくださいました!)
2日にわたる@t_wadaさんの公演と、その後の課題の実践を通して、TDDについての自分の考えが深まったので、 現時点でのTDDについて理解をまとめておこうと思います。
※ 講演の内容のまとめではなく、あくまでも講演を受けての@koichi222の考えです。
まず参加前の僕の状態について書いておきますと、
- 仕事でrails & rspecでの自社サービスを開発
- ケースの濃淡はつけてもよいが、テストは必ず書くルール
- テストを書いておくと元の入出力と同じことが保証されるので安心してリファクタできる、というのを一番のメリットに感じていた
- テストファーストについてはあまりメリットを感じておらず、実装の後からテストを書くことが多かった
といった感じでした。なので
- テストファーストにこだわる意味って本当にあるのか?
- うまくテストの強弱の付ける方法はあるのか?
などについて考えるヒントが得られればいいなぁということを参加前に考えていました。
TDDの定義について
このエントリにおいては、
・TDD =「開発者が」「動くキレイなコードを」「効率的に書く」ことを目的としたテストを用いた開発手法
と定義したいと思います。テストファーストを必須とする狭義のTDDについて言及するときは、明示的に記述することととします。
TDDがしてくれること、してくれないこと
まず、誤解していた部分が多かったTDDがしてくれること、してくれないことについて
まとめてみます。
TDDがしてくれること
・TDDは、開発者が設計をせずに実装をし始めることを防いでくれる
特にテストファーストで行うTDDの場合にいえることですが、テストを記述する
=設計を記述することになります。(※1)後先考えずコードを書き始めてやみくも
に突撃することで、後ほど右往左往して苦い思いをした経験がある方も多いと思い
ます。TDDは設計のプロセスを開発に組み込むことで開発者が無駄な遠回りしない
ようにしてくれます。
・TDDは、開発者が意図した設計から外れた実装をすることを防いでくれる
TDDはテストケースとコード実行結果を照らし合わせることで、意図した設計、実装
の通りにコードが動作していることを確かめてくれます。Red→Green→Refactorの
サイクルはなるべく早く回すべき、というのはこのフィードバックこまかく受け取る
ことで異変にいち早く気づき、軌道修正するためです。
TDDがしてくれないこと
・TDDは、設計と実装の質を保証するのものではない
TDDによって取り除かれるのは意図した設計、実装になっているのか?という不安だ
けです。逆に言えば、そもそもその設計がよい設計なのかどうか?という点に関して
評価してくれるものではありません。これを実感した2日目の課題を例に上げて説明
します。2日目の課題は、wikiエンジンの実装といういきなり取り組むのは難しい大き
な問題で、コードを書き始める前にどの項目をどういった順番でどうテストするか?
について考える必要がありました。参加者の中であった良いアプローチとしては、
・まず1行の文字列を入力したらhtmlを返してくれるパーサを実装し、そのループで
複数行の場合を表現しよう
といったものがありましたが、このように、問題をどう定義し、分割していくか?と
いう設計のプロセスについてはTDDはヒントを与えてくれるわけではありません。
あくまでも実装が意図通りになっているかどうかを確かめてくれるだけなので、設計に
ついて考える能力はTDDとは別で引き続き磨く必要があります。
・TDDは、ソフトウェアの品質を保証するものではない
TDDというのは、開発者が効率的に開発するためのテストを用いた開発方法
(developing test)であって、ソフトウェアの品質を保証するものではありません。
そんなのあたりまえじゃん!という方にはここは読み飛ばして頂いて構わないので
すが、勘違いされやすい部分だと思います。和田さんのプレゼンにあった下のスライ
ドがわかりやすいです。
tddbc tokyo 1.5 基調講演(http://www.ustream.tv/recorded/15889068)より引用
勘違いされやすい理由として、TDDを行うことで品質が保証される場合もある、
ということがあります。それは、元々良い設計が意図されていた時です。TDDはその
意図が実装されているのを保証するものとなるので、結果的にソフトウェアの品質は
保証されることになります。ですが、それはあくまでよい設計のソフトウェアが品質が
高いのであってTDDがソフトウェアの品質を高めているわけではありません。
いつTDDするのか?
今で
これはシンプルに答えられます.
- 開発者が不安があるとき、不安がなくなるまで行う
開発者の不安を取り除くことで、開発効率を上げる、というのがTDDの根本の考え方です。では、テストファーストで行うTDDについてはどうでしょうか?
個人的には、以下のケースは特にテストファーストのTDDがおすすめできると考えています。
- プログラミング初心者が設計の習慣をつけるトレーニングがしたいケース
- 問題が大きすぎるor複雑なため、設計が出来上がって実装するのでなく、設計しながら実装したいケース
まとめ
・TDDは「開発者が」「動くキレイなコードを」「効率的に書く」ことを目的としたテストを用いた開発手法
・TDDを行うことで、設計と実装が意図通りになっているかの不安を取り除くことができ、開発効率が向上する
・よい設計をするための能力を上げるためには、TDDの習得とは異なる部分での努力が必要
長くなってしまいましたが、以上が現時点での僕の考えるTDDです。
主張がクリアになるようになるべく曖昧な表現は使わないようにしたつもりですが、
理解が不十分な部分、異論がある部分ありましたらぜひご指摘いただければと思います!! ※2
最後に
普段なかなかTDDについて考える機会をいただいて大変有意義でしたし、
なにより参加していて本当にたのしかったです!!!(懇談会含む)
講演していただいた@t_wadaさん、
主催頂いた @Spring_MTほか運営スタッフの皆様、
会場を提供いただいた AIPさん、
本当にありがとうございました!!!
次は自分が主催したいなぁ。(ぼそっ
※1@t_wadaさんは仕様の記述と言われていたと記憶しているのですが、僕は仕様を実現するためにどのクラスにどのようなメソッドを書き、どんな入出力を返すか考えることは設計の領域と考えているため、ここでは設計の記述と書かせて頂きます。
※2 テストに関する書籍は「The Rspec book」を読んだくらいで、TDDに関する書籍はケント・ベック本を読み始めたばかりと基本的にまだまだ勉強不足なので、抜けている観点がある可能性が高いです。。