クロコさんの発言
TDDの学習を始めるときに、プログラミング言語はマスターしておかないと始められないのですか?
この疑問に関しては、みなさんいろいろ意見があると思います。
まず、TDDをマスターしていて言語をマスターしていないのか、言語もTDDもマスターしてしていないのかで全然状況は違うと思います。
私自身はTDDをある程度マスターしていると考えていますが、私はプログラミング言語をマスターするために、TDDをやってみることがあります。ちょっとピントのずれた回答かもしれないんですけれど。
全然経験がないプログラミング言語があるときに、どういうやり方をしていくかというと、どんな言語にも、だいたいテストコードのサンプルとテスティングフレームワークがあるわけですね、たとえばSmallTalkだったらSUnitがありますし、.NETだったらNUnitがあります。
私は、そういったテスティングフレームワーク[1]を探し、テスティングフレームワークを使って学習テストを書いていくことで、その言語を知っていくというやり方をよくやっています。
私は『テスト駆動開発入門』(Kent Beck 著/テクノロジックアート 訳/長瀬 嘉秀 監訳/ピアソン・エデュケーション 刊)を写経したとき、同時にRubyも学習しました。
当時、Javaはもうずっと仕事で書いていたんですね。そして、『テスト駆動開発入門』をJavaでそのまま写経するというのをすでに1回やってみていました。
Javaに対してRuby自体はちょっと触ったことがある程度だったんですけども、Kent Beckの書いているJavaのMoneyのコードをJavaでそのまま写すのは一度やったので、もう一つ新しい言語マスターするために、新しい言語で写経してみようと思い立ち、実際にRuby(『テスト駆動開発入門』の第1部)とPython(『テスト駆動開発入門』の第2部)で写経をやってみました[2]。
自分が学びたい言語でテスト駆動開発で学習テストを書いてみることで、段々言語の基本的な機能などが覚えていけるのではないかと考えています。
ですので、「TDDをマスターするために、言語のマスターが必要か」という質問に対しては、私の答えはまだ答えになってないと思うんですけど、「言語マスターするために、テストとかテスト駆動開発を私は積極的に利用しています」とは言えます。
あと、Kent Beckは、プログラミング言語をマスターするためには、その言語のテスティングフレームワークを作ってみろと言っているんですね。だから、Lispをマスターしたいなら、LispUnit(LUnit?)を自分の手で作ってみる。JavaScriptマスターしたいんだったら、JSUnit私家版を作ってみる。
テスティングフレームワークを作るため何が必要になるかというと、その言語のリフレクション機能ですとか、たとえばevalの機能ですとか、そのプログラミング言語のメタプログラミング機構の知識が必要になります。
そして、言語のメタプログラミングの知識は、その言語そのものを深く知るきっかけになります。テスティングフレームワークを作る際に得られた知識自体が、その言語に対する理解をもっとぐっと深めると考えています。
たとえば今ActionScript 3をもっと知りたいというときには、自分でAS3Unitを作ってみてください。すると、ActionScript 3の言語仕様に対する理解がぐっと高まると思います。
私自身の経験を話しますと、「なでしこ」という日本語プログラミング言語があるんですけど、なでしこをもっとよく知りたいなっていうときに、単純な「なでしこユニット」を自分で作ってみて、それでなでしこがちょっとわかったという経験があります。
ただ、私の今の回答も、質問の回答になっていないと思うんですね。TDDのマスターのためには言語のマスターは必要ですかという質問ですけど、当初の質問の意図自体はどういったものなのでしょうか。もう少し詳しく聞かせてください。
クロコさんの発言
新人のころ、まずTDDを学習したいときに、足がかりがつかめなかったんです。
そのとき、ではまず言語を覚えてからTDDでちょっと学習を進めてみようか、みたいなことがあったりすると思うんですね。まったく何も知らない人にTDDを強要しても、何もできないだろうというのがあったりして…。そしたらまず何からいけばいいだろうかという…。
そうですね。プログラミング言語の初心者というよりは、まったくのプログラミング初心者に、テスト駆動開発を教えることができるかというと、まず最初にプログラミングの基礎は最低限習ってもらわないといけないと思うんですね。
ただ、私は早い段階で自動テストのしくみ自体は教えるようにしています。なぜかというと、結局のところテスト駆動のやり方、もう少し正確に言うとユニットテストのやり方が、学習者に対するフィードバックが一番早い方法だと考えているからです。
たとえば、「ループ、繰り返し」や「条件分岐」を覚えてみましょうとか、クラスの作り方、メソッドの呼び方を覚えておいてくださいなどというときに、単純にやってみてくださいというのではなくて、たとえばテストを渡す、そのときは私がテストを書くんですけれども、こういうテストを通るようなプログラムを書いてみてくださいとか、「次にこういうものを作るので一緒にテストを書いてみましょうか」とペアプロしてみるとか、そういった形でまず学習のための足がかりをつかみます。
ですから、新しい言語を覚えるときになぜTDDで学習してみたかというと、学習というのは基本的にはフィードバックサイクルだと思っているからなんです。「こうやったらこう動いた、そうやったらこうなった…」というフィードバックを回していく基本的なしくみとして、私はテスト駆動のしくみを重要なものだと思っています。
家永さんの発言
実際に書いたプログラムが期待通り動いているっていう確認方法が、初心者の最初は、System.out.println(標準出力)でやっていくと思うんですけど、もう一つの段階によってはTDDっていうか、自動テストのしくみで動作確認ってのがあるのかなと。
「テストを動作確認という視点で捉える」という意見をいただきました。私もまったく同意見です。結局のところプログラムの開発に動作確認は絶対含まれると思いますので、私は自動テストのしくみは初心者にもすぐに受け入れられると思っています。