なんちゃってアジャイルでATDDをしていた

東口和暉氏(以下、東口):先ほど、2015年はなんちゃってアジャイルをやっていたという話を自己紹介でしていたと思うんですけど、そのときはATDDされていたんですか? 

kyon_mm氏(以下、キョン):そうですね。けっこうその頃はしていました。この当時、開発真っ最中だったのがフレームワークだったんですけど、IDEにプラグインも提供していたやつなんですよ。IDEってけっこうバージョンアップが激しいじゃないですか(笑)。

OSとの組み合わせもありますし、Windowsの環境でやっていたので、ユーザーホームのパスの長さよって、256文字の制限も出てくるんですよ。だからIDEとかツール使った開発って、パラメータがめちゃくちゃ多くて。

今回IDEのこのバージョンに対応していくぜっていったときに、ある種のパラメータに関して自動テストがないと死んじゃうよねというのがあって。フレームワーク自体はけっこうユニットテストをしやすい領域ではあるんですが、IDEとWindowsのパスの長さや、OSの設定って、ユニットテストではやりにくいじゃないですか。

そうなると自動テストがけっこう重要で、IDEの自動起動などを含めた自動テストを書いてから、ある種のバージョンアップのテストをして開発をやっていましたね。

東口:なるほど。

キョン:そういう意味で言うと、いわゆるRSpecのBDDなどの文脈をまったく無視したATDDの文脈でのテストをメチャクチャやっていたという感じです。

東口:IDE Windowsだとそのへんが大きな壁になってくるんですね。

キョン:そうですね。例えばユーザーネームを略語で3文字以下で作っていたときはいいけど、ツールをインストールするとWindowsってユーザーホームにAppDataとかなんとかがボコボコボコって増えていくじゃないですか。それらのパスが256文字を超えるケースが出てきて、そもそも起動できない。え~!? みたいな。

東口:それはユニットじゃどうにもできないですもんね。けっこう重要な製品の条件だったりするとなおさら。

キョン:そうなんですよ。そういったところでも、いいアジャイル開発はしていなかったんですが、パフォーマンステストもけっこうやっていたし、自動テストはいろいろなことをやっていました。

なのでその頃は技術的にはけっこうやっていました。XPの良さはあまり引き出せていなかったんですが、いわゆるテストツールやテスト手法はけっこうやっていた時期ですね。

東口:今、2014年に戻るとして、違うアプローチをしますか?

キョン:そうですねぇ……でも変わらないかな(笑)。あの当時、最善の選択をしていたとは思いますね。2021年に同じプロダクトをやってくれと言われたら、ツールセットがけっこう違うので進め方はぜんぜん変えられますけど。あの当時の文脈だと、あれが最善かなぁという気がしなくもないです。

東口:確かにツールセットにけっこう依存しますね。『ATDD by Example』の最後のほうに、IDEがこれだけ進化したんだから今こういうファクタリングができるという話があって、2012年から少しずつIDEの変遷期というか、そういう時代になったんだなと思いました。

『ATDD by Example』を読んだとき「幼稚園児でもわかるよ」と思った

キョン:そうですね。こういうことを自分なりにいろいろやってきたのもあって、『ATDD by Example』って「は!?」って感じだったんですよ。「何言ってんの? こいつ」みたいな感じだったんです(笑)。

今はぜんぜんそういうふうには思わないんですけど、読んだ当時はこんなの幼稚園児でもわかると思っちゃって。ATDDやBDDなどが、ユニットテストじゃないもののTDDであるというのはいろいろなブログでも言及されていて。特にDan Northとか、Gojko Adzicとか、いろいろなアイデアをブログに載せたり、メーリングリストで議論したりとかしていました。

TDDをわかっていれば、話自体はすごくシンプルだし、やってみればわかるぐらいのレベルの話なんですよね。テストのレベルを上げるだけだよねという感じで。

『ATDD by Example』には行間があって、それ(ATDDやBDDの概念)を補完してくれるものなのかなって思っていたんですよ。そういう期待があったんですが、読んでも読んでもすでにWeb上で言われていることがただ書かれているだけという感じになっていて。

『ATDD by Example』は、体系的には書かれていないんですよね。まさしくExampleだから、基本的に「こういった条件だったらどうだろう?」というシナリオが進んでいく。 そういうふうに進んでいくので、じゃあそれをわざわざやる意味って何だっけ? と当時は思っていました。いろいろ知っている側からすると、体系的になっていないから、人にもおすすめしにくい。

例えばTDDを知っている人に、ATDDの説明を30分くらいしたとして、それ以上のものがなにかあるのかなと思ったときに、(それ以上の)感想を抱ける本ではなかったというのが今でもちょっと残念だなと思うところです。ATDDを30分でザクっと説明できない人にとりあえず『ATDD by Example』を渡したいという動機はあるのかもしれないけれど、これを読んで本当にATDDが理解できたて思えるのかな、みたいな(笑)。読んだあとに、「お、これで俺はATDDを理解したぜ」っていう達成感と、30分誰かが教えてくれたときの達成感は同じくらいじゃない? って思っちゃう。

東口:あの本はこの土日に、この会のために「ん?」と思う気持ちをすごくグッとこらえながら読み続けていました(笑)。比較的最初のほうはテスターであんまりプログラミングの経験もなくてもやれるんだよ、みたいなメッセージが強い内容になっていますね。

2つ目が、TDDとATDD、それぞれを補完するように開発をするための例としてキョンさんが資料の中で挙げられていたような信号機のシステムが挙げられていて。正直、どういうことだ? って思いました。今、いい資料だからこれでわかるよって出せるかというと、ちょっと出しにくいという感覚があって。

キョン:ですよね(笑)。

東口:この感覚をもってキョンさんの『自動テストの誤解とアンチパターン』の資料を読んでいくと、あの本が書いていた例におけるドメインは何を指そうとしていて、どうだったの? みたいなことを解説していますよね。

キョン:そうそう。

東口:それで、この資料の背景がわかってつながった(笑)。資料の中ではアプリケーションドメインとソリューションドメインで2分別する方法がありますというところから始まっていたと思うんですけど、あの本の例って、実際どう分析されたんですか? ちょうど出している資料のところです。

キョン:「TDDの自殺」のところですよね。

東口:自殺する直前……っていう言い方はめっちゃ悪いですけど。

キョン:自殺する直前(笑)。アンチハラスメントポリシーになったりするのかな。物に対しては勘弁していただきたく。人を傷つける意図はないです。

東口:ただの一般的な事象です(笑)。

キョン:アプリケーションドメインはざっくりと言うとソフトウェアシステム導入によって変化させたい領域のことです。ソリューションドメインは解決ドメインと呼ばれるもので、例えばソフトウェアシステムの個々の技術や組み合わせ方のことです。これはいわゆるHowですよね。アプリケーションドメインがWhatやWhyで、ソリューションがHowとイメージするとわかりやすいと思います。

『ATDD by Example』のいわゆるCucumberみたいにGiven、When、Thenで書いているところは、アプリケーションドメインのすごく小さなところですよね。例えばECサイトを作るとして、割り引きのロジックがあるとするじゃないですか。その割り引きのロジックに関する、こういうときにはこの割り引きがここに効いてというような表ですよね。デシジョンテーブルを書いた部分があの本で説明されている部分なので。

東口:そうですね。

キョン:アジャイルで言うと、ユーザーストーリー視点で考えるとどうなんだっけ? とか、ここがこうなっていてというところの説明にはまったくなっていないから、例もすごくチープなんですよ。そこもね、ちょっと人に勧めにくいんですよね。

すごく小さなアプリケーションだったら、ソリューションドメインとアプリケーションドメインがほぼ1対1くらいのレベルの話を『ATDD by Example』では例にしているので、わざわざATDDって言う必要があるんだっけ? と思っちゃう人も、たぶんいるんだろうな。

東口:これはTDDでいいんじゃないかって思いました。2つ目の例は特に思いましたね(笑)。

キョン:そうですよね。

東口:あの例だと2つ目のときって、FitNesseでやっていて、アプリケーションドメインのテストを書いて、その実装をして、GlueCodeという仮実装みたいなところで1回通して、GlueCodeにTDDサイクルを回して、うまくドメインができてきたらProductionCodeに持っていくという方法をとっていたんだなぁっていう。

ここにこういう方法を取るんだなぁと思いつつ、この方法を取ったということは、テストのレイヤーがほぼ一緒であるという前提があるなと。テスト自動の戦略としても、同じレイヤーに2つのツールを使って何をやりたいんだろうと思って。

キョン:言うじゃないですか、東口さん(笑)。

東口:このモヤモヤを言語化するのにめっちゃ時間かかりました(笑)。テストの実装言語とProductionCodeの実装が同一言語であるという前提がそこにあるのかというと、Cucumberはそれがいいよねと言っているけど、別にそれが必須でもないことを考えると、これが必ず使える方法でもない。

受け入れテストのレイヤーを上げると考えたら、これはほぼホワイトボックステストになっているけれど、それが本当にテスト戦略としてやりたいことだっけ? とかいろいろが頭をよぎったときに、これは僕が瑣末な詳細に頭を捉えられすぎているだけなのか、それともみんなが思ったことなのかというのを今日雑談をしたかったんです(笑)。

『ATDD by Example』が書きたかったこと

キョン:なるほど。もともとGlueCodeがProductionCodeになるっていうのは、FitNesseとかでよくある話ですよね。

普通のTDDで、例えばさっきの割引のアルゴリズムを作りたいときに、テストコードを書いて、プロダクトコードにいろいろ実装していって、試す前にまずテストコードのすぐ上やすぐ下にテストとして、実行されないメソッドを生やしてみて、このメソッドはうまく動くんだっけ? みたいなことをやっていって。

1個のテストファイルの上で仮の関数を作って動かして、「あ、こういう感じじゃん!」って。やっぱり1画面で見ると早いですからね。

それをProductionCodeのクラスやメソッドの中に貼り付けて動かして、「そうそう、こういう感じ、こういう感じ」ってやって成長させていくというのは、昔からあるTDDの手法なんですけど。それをATDDに持ってくると、こうなるっていう話ですね。

東口:そこの起点で発展させるとこうなるという解釈なんですね。

キョン:そうなんですよ。だからこれをやりたいっていうより、TDD仕草に慣れている人の、あのやり方をATDD、FitNesseでやるとこうなりますよねっていう説明なんですよね。

東口:なるほど! TDD仕草をそのまま発展させてATDDでやると、同じようにやることになるのか(笑)。

キョン:そうです。じゃあなんでわざわざこれを書いたんだっていう話になるんですけど(笑)。言語のレイヤーが分かれるものにおいて、これをやるメリットはなんだっけ? って言われると……あんまりはない。

FitNesseはTestImpl、GlueCodeっていうところで、UnitTestより開発コストが大きくなるわけですよね。特にSpecBDDのフレームワークより大きくなるので。

そこの開発速度を上げたいなら、GlueCodeの開発を早くする必要がある。ふだんUnitTestを書いている人たちが書きやすいコードのほうが開発が早く進むので、例えば、開発者がJUnitでやっているんだったら、Javaで書くいるほうがGlueCodeの生産性がいいですよねってなってJavaにしたいとなります。

そのうえで、このGlueCodeをさらに早く書こうと思ったときに、TDD仕草を使うと、こういうことになるといういう図ですね。

東口:そういうことを書きたかったんですね。今のキョンさんの解説を聞いて理解しました。

キョン:そうです。説明してほしいって思うんですけど(笑)、2009年や2012年はそういう説明はいらないだろうっていう世界観なので。

(次回へつづく)