うさぎ組

ソフトウェア開発、チームによる製品開発、アジャイル、ソフトウェアテスト

TDDの自殺 #kyon_mmAdvent

はじめに

僕は熱心にTDDを勧めているエンジニアです。
ですが、この2年でTDDが銀の弾丸ではないことも気付き始めました。
その気づきの一つがこのTDDの自殺です。
先にFacebookで投稿したところ、評価をもらえたので投稿します。
「読み手を選ぶエントリーです、(`・ω・´)キリッ」
これを読んで「kyon_mmも落ちたものだ」と思ってもらっても構いませんし、「迷惑な話だ」ということであれば僕に猛抗議をしてもかまいません。

TDDとはなにか

TDDは開発者を支援するフレームワークと定義します。

TDDは「開発者の意図を確認すること」「開発者が心地よいコードを書き始める事」を支援するフレームワークです。

TDDの基礎
TDDを支えるものとして次の要素があります。
客観的で頻繁にも実施できる検査群、確認し易い検査結果群、RED,GREEN,REFACTORのライフサイクル。
これらによって、「開発者の意図を確認すること」「開発者が心地よいコードを書き始める事」という目的を達成します。

詳細にはこちらになります。

TDDを明確に定義する - うさぎ組
はてな
TDDを明確に定義する 2 - うさぎ組

TDDの自殺

ここで対象とするTDDでは検査群がテストコードである場合とします。


TDDは開発者の関心のスコープを明確にしてくれますが、
それが達成できているのは、その関心というのをテストコードに表現するからです。
ですが、これは実はゆるやかにリスクを抱え始めています。
つまりテストコードに関心があるということです。


ここで、前提とすべきことがあります。
それは、解決したい問題と解決方法というのは1対1の関係、つまり等価であるというのが理想であるということです。
そのためにリッチなDSLが開発され、簡潔にかけるプログラミング言語が開発されています。Webフレームワークやなどもその役目をもっているでしょう。


プロダクトコードに関心を書きたいはずが、書けないという現状を脱するために、TDDではテストコードにその関心を先に書いています。
つまり、「解決している事」は「テスト」にあって「プロダクト」にも同じことが書いてあるのです。
これはコピペされているということを言っているのではありません。
おそらく、プロダクトコードは短いコードでたくさんの事に対処できるように書かれているはずなので。
つまり、解決しようとしている事が両方に書かれているということです。


TDDはテスタビリティを上げるというメリットをとる一方で、アプリケーションドメインをテストコードに流出しがちになるというデメリットをはらんでいます。
たくさんの場面、つまりアプリケーションドメインがテストコードに流出する場面はたくさんありますが、もっとも共感を得られやすい場面はモックやスタブです。
モックやスタブを書いているときに「モックやスタブのテストをしているのではないだろうか」「モックを書いているようでプロダクトを書いているのではないか」と感じる場面があるはずです。
解決すべきパターンが多くある、汎用的にする必要がある。いろいろ書くうちに、それはほかに動作するモジュールを書いているような気分になります。
まさにこのとき、あなたが解決しようとしている問題、つまりアプリケーションドメインがモックやスタブに漏れ出しています。


モックやスタブはTDDにおける典型的な例なのですが、まさにこういった行為はTDDのあらゆる場面に潜んでいます。

まとめ

TDDをすることによってソフトウェア開発におけるアプリケーションドメインがプロダクトコードから遠ざかりがちになる。
そして過ぎれば、プロダクトにはアプリケーションドメインのない抜け殻しか残らなくなる。
TDDは自身のその役目ゆえにプロダクトコードを自殺に追い込んでいることに気付かない。たいていは気付いた時には自殺してしまっている。
抜け殻のプロダクトコードにおいて、TDDは何を支援しているのでしょうか?本来の「開発者の意図を確認すること」「開発者が心地よいコード(プロダクトコード)を書き始める事」はどこにいってしまったのでしょうか。
RED, GREENというゲームを楽しむことに熱中し、タスクが解消されることに熱中しているうちに、そのTDDは本来のTDDではなく、すでにただのゲームになり下がっています。
プロダクトを自殺に追い込むことよって、TDDも死にます。これを僕はTDDの自殺と名付けました。
プロダクトコードを殺さないためには、TDDとうまく付き合う必要がある。
そう思うようになりました。




補足

Facebookにて先行公開したときに、「アプリケーションドメインがテストコードにのみ存在するというのはどういった状況か?」という質問をいただきました。

次のように回答しました。
kyon_mm

ここで、ドメインと言っているのは、「アプリケーションドメイン」になります。
ドメインの分け方として「アプリケーションドメイン」と「ソリューションドメイン」というものがあります。

そして、ここで言っている理想というのは両ドメインが同一になることです。

「アプリケーションドメインがテストコードにのみ存在するというのはどういった状況か?」というのは、言い換えれば
「テストにのみアプリケーションドメイン」が表現されていて、「プロダクトにはソリューションドメインのみ」という状況です。
ひどい例で言えば、「リファクタリングされていないプロダクトコード」といったイメージです。
で、TDDにはREFACTORがあるのですが、その方向がアプリケーションドメインをプロダクトに埋め込む行為であれば、テストとプロダクトの両方にアプリケーションドメインが存在することになりますが、そのときに、どう表現されるべきかという論はほとんどないように思います。