この記事はTDD Advent Calendar 2013の16日目の記事です。 前日はid:grimroseさんの「javascript-mochaのskeletonを作ってみた #TddAdventJp」でした。
TDDが僕に教えてくれたこと
先日、同僚の先輩と飲んでいるときにふと始まった話題が、自分の約1年半くらいのTDD歴を振り返るきっかけになったので今回はそれをネタにしてみます。*1
同僚(以下、同)「俺たちは受託でシステム開発をやってるからこの機能を実装したらいくらって感じで仕事してるけど、例えば自社開発してるスタートアップだと何億とかって単位で資金調達してガーッと開発して、当たらなかったらどんどん機能消すみたいだね。」
僕「○○さん(元同僚)がこないだ言ってましたね。100個くらい機能作って2〜3個当たればいいほうだって。」
同「そう、あの話おもしろなーと思ったんだよね。」
僕「でも僕思うんですけど、たぶん100個の機能作るためにはそもそもアイデアの段階で消えてった機能がもっとたくさんあるはずで、そこから本当に実装する100個をどう選ぶかというところが最近興味あるんですよね*2。開発に着手するのってその時点でコストじゃないですか。もっと早い段階で見込みのない機能は選択肢から外せればいいな、と。」
同「へー、そんなこと考えてるんだ。でも何でその視点を持ってるのに末並君はTDDが好きだとか言ってるの?」
僕「え、どういうことですか?むしろ僕はそのあたりの視点をTDDから学んだと思ってるんですけど。」
TDDの「テスト」はDevelper Testing、しかし...
TDDの文脈における「テスト」はDeveloper Testing、つまり開発者が自分たちの開発プロセスをより効率的に進めるために記述するもので、品質の評価をするためのテストとは明確に異なります。これについてはほとんどのTDDerの方は納得しているかと思いますので説明は不要だと思います。
ただ、それは別にTDDが開発者"だけ"のための手法であることとイコールではありません。 我々がTDDを用いるのは高品質なソフトウェアを継続的にユーザに届けたいからであり、それは発注者やQA担当者の利益となんら対立はしません。
確かにTDDはその名前の通り、第一義的には開発を駆動することがその価値でありその効用を直接得られるのは開発者ですが、TDDが我々に教えてくれることはもっと多く、そこにはより広い世界が広がっています。
より少ないテストで価値を生み出す
2009年と若干古いですが、TDDの提唱者であるケントベック氏の発言をまとめた以下のような発言があります。
Kent Beck氏、ごく短期のプロジェクトではテストを省略することを提案
また、同氏は以下のような発言も残しています。
http://stackoverflow.com/questions/153234/how-deep-are-your-unit-tests/153565#153565
I get paid for code that works, not for tests, so my philosophy is to test as little as possible to reach a given level of confidence (I suspect this level of confidence is high compared to industry standards, but that could just be hubris). If I don't typically make a kind of mistake (like setting the wrong variables in a constructor), I don't test for it.
私はコードが機能するかに注意を払い、テストには払わない。私の哲学は、信頼できるレベルに達する程度で可能な限りテストを少なくするということだ。(信頼できるレベルというのは業界標準と比べて高いのではないかと思う。ちょっと思い上がりかな)。もし典型的なミス(コンストラクタで違う変数をセットするような)をしないなら、私はそれをテストしない。
ユーザはテストコードではなくプロダクトコードが生み出すエクスペリエンスに対してお金を払っているのだから、テストは少ない方が好ましいということです。
テスト自動化からTDD、そしてその先へ
自動化されたテストを持たなかったチームがテストを自動化し始めるとそれに快感を感じ、テストを書くことに夢中になります。予期せぬ変更の影響をテストが見つけてくれたときにはもうそれなしで開発をすることなど考えられなくなるでしょう。
ただ、それはまだテストが開発を駆動しているとは言えません。
回帰テストはTDDがもたらす恩恵のひとつではありますが第一義的な価値ではありません。TDDの第一義的な価値は分析/設計にあります。自分が今開発しようとしているものは何なのか、何のために必要なのか、どういう仕様を満たせばよいのか、どのような異常系が考えられるか、そういったことを考えるきっかけを与えてくれるのがTDDです。
「テストが書きにくい」と感じたときに向き合うべきはテストコードではありません。ユーザにとって価値の源泉たるプロダクトコードとこそ向き合うべきです。設計がよくないということをテストが教えてくれているのですから。
そうしてプロダクトコードと向き合った先に、さらに広い世界があるのだと思います。
TDDの先にある世界
TDDをきっかけにプロダクトと向き合った結果、その先に見えてくるものは人それぞれでしょう。プロジェクトの性質にもよるでしょうし、その人の嗜好性にもよると思います。
僕の場合は以下のようなところに興味を持ちました。
- オブジェクト指向設計/開発
- リファクタリング手法
- 単一責務化によるテストのメンテナンシビリティ向上
- RDB理論
- アプリケーションコードよりも信頼性の高いリレーショナルデータモデル
- データをDBに守らせることによってテストコードの量を削減
- 人間中心設計(HCD)
- 「テストコードを書く」よりも低コストな分析/検証方法
- 「開発」という高コスト施策の前に必要性を検証する手段
これらは技術領域としてはTDDと直接関係ないですが、いずれも僕はTDDから学んだと思っています。
バトンタッチ
ポエムのようなエントリで失礼しました。 次は@kidachi_さんです。よろしくお願いします。