Uncle Bob 2013年3月6日
前回のブログ記事「 スタートアップの罠 」は結構な騒ぎを巻き起こした。罵倒と賛同様々な声があったが、その中にあって頑なに賛同をしないグループもいた。この一ヶ月分のマサカリは既に投げ尽くしてしまったし、ここで全ての批判をまとめるつもりはない。でもその中の一つ、ちょっと一言いっておくか、と私に思わせるものがあった。
そいつは実践主義対教条主義という、例の古い議論だ。簡単に言うと、私が教条主義に過ぎる、という批判だ。要するに「TDDというのはいくつかのケースでは確かに素晴らしいのかもしれんけれど、大体はコストが高すぎてやってられない。だからお前ははもっと実践的な、賢い選択をしやがれ」というものだ。
一見これは非常に説得力のある。兎にも角にも実践的であることは重要だ、そうだろ? だから、もしTDDを使えば締め切りが守れないとあんたがわかっていて、んでもってTDDを止めることで締め切りが守れるんだとすれば、TDDを止めるだろう。当然だ。
うん、そこに疑問の余地はない。そして実際、それが正しい行動であることもある。このブログの目的は、私がどんな時にTDDのコストが高すぎると考えるか、それを表明することだ。
けどその前に、私は一つの主張をしたい。TDDはプログラマーのための規律であり、それは会計士にとっての複式簿記や、外科医にとっての無菌消毒に当たるものだ。会計士が複式簿記を使わない場合があるか?外科医が無菌消毒をしない時は?
その答えは両方共、イエスだ。会計士は自分の個人的な小切手帳やレストランの会計のチェックには複式簿記を使うのか、私には疑問だね。一つ目については証明できる。私は自分の小切手帳の管理に複式簿記を一年間使った。でも結局は、その努力は起こりうるリスクに見合わないことに気づいた。二つ目については、レストランの会計に複式簿記を使うのはやり過ぎだと皆同意してくれるよね?
外科医の無菌消毒にしてもそうだ。私は何年か前に腕からおできを取り除いてもらった。そのとき看護婦である妻は、手術を見学していたんだ。手術は医者のオフィスで局所麻酔でしたのだけれど、医者の準備中に、妻は彼が無菌消毒をしていないことについて質問していた。医者は、この程度の手術に値する「手洗い」はおこなっている、と答えた。彼女はその答えに納得し、手術は完了した。
数日後、手術跡が炎症を起こし痛くなった。跡の一つは膿んでいて、再度跡を開き洗浄する必要があった。これが「手洗い」のせいだったのかはわからないけど、今の私なら、手術をする医者には「消毒」ではなく無菌消毒をするように主張するだろうね。
それでも、先ほどの主張はまだ正当だ。TDDが高コスト過ぎるから、より低レベルの規律を代わりに用いるべき時というのはあるんだ。そういったケースは非常にレアだし、規律が不便そうに見えるからだけで使いたくない、ってのを「実践主義」という表現に置き換えちゃいけない、ということに、私の話から気づいてもらえたんじゃないかな。
では、私がTDDを行わない時はいつなのか。
- ゲッターやセッターにはテストを書かない。それは普通は馬鹿馬鹿しいことだしね。ゲッターやセッターは他のテストにより間接的にテストされるものだし、そいつらを直接テストする意味はない。
- メンバー変数へのテストは書かない。これらも間接的にテストされるものだ。
- 一行の関数や明らかに重要でない関数はテストを書かない。これらもまた間接的にテストされるものになる。
- GUIのテストは書かない。GUIはいじくってやらないといけない。こちらでフォントサイズを変え、あちらでRGB値を変え、こちらでXY位置を、そちらで幅を変え...という風に触ってちゃんとした位置に収めてやらなければ。これらをテストファーストで行うのは愚かだし、時間の無駄だ。
- しかし、GUIコードの重要の操作は、テスト可能なモジュールに移動させておかないといけない。私はテストされない重要なコードを許さない。だから私が書くGUIコードは、データを取ってきて画面上に配置するだけの、グルーコードよりも小さいものになる。(MVVMやMVPについての記事を参考にしてほしい。)
- 一般的に、試行錯誤して「いじくり回して」やらなければいけないようなものは、テストを書かない。しかし、確信を持ってテストできるコードから、それら「いじくり回す」コードを隔離している。
- 上記のような状況下では、コードをいじくり回してちゃんとしたものを作ってから、それを検証するテストを書いている。
- あるいは、一度「いじくり回した」コードを消してから、テストファーストで書き直す、ということもしてる。
- どれを選ぶかは君の判断だよ。
- 2・3ヶ月前に、100行ほどのコードを、全くのテストなしに書いた(なんと!)
- そのプログラムは一回きりで、一度使われれば捨てられるものだった。(私のビデオの一つで用いる特別なエフェクト用のものだった)
- そのプログラムは全て画面描画に関するもので、純粋なGUIアプリケーションだった。なので私は全ての物を、いじくり回してちゃんと配置してやらなければなかった。
- 私が使ったのはClojureだったので、REPLがあった!REPLを通してプログラムを育てながら実行することができたから、全ての行の結果を目で見て確認できた。これはTDDではなく、EDD(Eye Driven Development:目駆動開発)だったね。
- フレームワークやデータベースやウェブサーバーなどのサードパーティソフトウェアは、普通はちゃんと動くものとみなしてテストは書かない。これらはモックにして、自分のコードに対するテストを書く。
- もちろん、サードパーティソフトのテストを書くことはある。例えば…
- 壊れていると感じた時
- モックが必要ないくらいに、サードパーティソフトが高速で、かつ結果が予測可能な場合
- もちろん、サードパーティソフトのテストを書くことはある。例えば…
これらは完全じゃない。他にも私自身がテストを書かない場面というのは有ると思うけれど、でもこれらのリストの意図することは明白だろう。実用性はTDDにも影響する。全てが教条じゃない。
でも、私は教条を尊重する。そうするに足る理由があるからね。実用性のため時には教条が上書されることも有りうるけれど、TDDを使うために考えうる限りの手を尽くすこと無しに、重要なプロダクションコードを書くことは決してないだろうね。
👍