TDDBC 札幌 2.1 開催しました

シルバーウィークの後半に札幌にてTDD(テスト駆動開発)の体験型イベントであるTDDBC(札幌版)を開催しました。

TDDBC 札幌 2.1 であること

ナンバリングが変な事になっていますが、札幌では今回で通算5回目の開催になります。近年、テスト駆動開発は開発手法として非常に重要なスキルの1つと考えられていますが、なかなか開発現場で実戦する機会はありません。自分で学習していくことも可能ですが、見よう見まねで学習するよりも同じような志*1を持っている人が集まって、同じ目標に向けて学ぶ方が効率が良いものです。1人で悩むよりもみんなで悩み、解決できるような人がイベントにいると安心ですから。

TDDBCは、テスト駆動開発を実際にやってみるためのイベントです。TDDの伝道師である id:t-wadaさんが講師を務め、午前中に座学、午後に演習というのが基本スタイルとなっています。しかし、TDDやアジャイルなどのムーブメントもあり、全国各地でTDDBCが開催されていく中、和田さんに依存しない形でTDDBC(もしくはそれに類するイベント)を開催し、TDDを学ぶ場所を作っていかなくてはならないという課題も議論されています。また、TDDBCはテスト駆動開発の入門的な位置付けが強かったイベントですが、開催を重ねていくうちに応用的な内容やSCMや自動化を絡めたモアTDDBCも要求として生まれるようになりました。そんな背景の中、TDDBC札幌2.1は企画されています。

これまで良いプログラムを設計するためにテスト駆動開発をどう取り込むかという事をテーマとしていましたが、TDDBC札幌 2.1 では良いシステムを開発するためにどのようにテスト駆動開発を取り込んでいくかをテーマとしています。良いプログラムと良いシステムは必ずしも一致しません。極論を言えば、良いシステムとは「顧客の要件を満たすシステム」であり、例えどんなにコードが汚くとも、バグが顧客に発見されず、要件を満たしていれば良いのです。勿論、メンテナンスという観点ではコードの可読性などは重要ですが、綺麗なコードを書くというのは開発者目線なのです。

TDDBC札幌2.1では、ユースケース駆動開発(ICONIX)とATDD(受入テスト駆動開発)を良いシステム設計としてのアプローチとして採用し、会議室予約管理システムという業務アプリケーションでありがちなシステムを題材としました。これまでのTDDBCではキャッシュ可能なKey−Valueコンテナ(LRUキャッシュ)やファイルシステムのIOなどプログラム的にも少し複雑なプログラムを題材としています。それに対して、今回題材とするシステムはプログラムとしては非常に単純で有り、フレームワークを活用すれば実装コードは数行程度でしょう。事前準備として画面モックアップユースケースシナリオは作成済みですが、「どのようなコンテキストでのテストが必要か?」という点に集中して、テスト設計をする必要があります。

講演1

TDDBCの午前中はTDDの基礎を学んだり、デモを見たりと講演です。
今回、力不足ながら私が基調講演をさせていただきました。はじめにTDDとTDDBCに関する要点を話しています。


自分なりに和田さんのこころを伝えられるように努力したつもりですが、やはり経験とスキルがまだまだだなと実感しました。また、和田さんがTDDBCで話していることを劣化再生している段階であり、自分の言葉で自分なりのTDDを伝えられるようにならないと思います。
続いて事例紹介ということで、東京からゲスト参加でJava/Slim3のTAも行って貰った @sue445 さん、札幌のゆとりPython使いでPython/DjangoのTAをやってもらった @giginet さんによる事例紹介セッションを2本挟みました。

お二人ともありがとうございます。
これらの前半の講演については Ustream録画もされていますので、時間のある方はどうぞ。

講演2

後半の講演は、今回のテーマであるユースケースやユーザシナリオからどのようにテスト駆動開発に落とし込むかという事を、私からユースケース駆動開発を絡め、 @mrkn からRubyのATDDフレームワークである、Cucumber を使ったデモという形で行いました。

前半の自分のセッションは概論的な部分で、システム開発による外部設計の位置づけと、ユースケースがどのような意味と価値を持つかを話しています。簡単に言えば、「システムの利用者視点での外部的な振る舞いを、顧客が理解可能なシナリオ(利用例)で記述する。それを満たすことが受入テスト(機能テスト)に相当し、それを設計段階で定義しよう」という事になります。それらの受入テストはプログラムとして自動的に繰り返し実行できる方がベターであり、その1つの方法がCucumberという流れでmrknに引き継ぎました。実は事前打ち合わせは簡単にしかやっていなかったのですが、上手い形に講演が連携できたかな、と思います。面白い所としては、自分の説明したユースケース駆動開発はどちらかと言えばウォーターフォール的な側面が強い設計手法ですが、mrknの行ったデモはまさにアジャイルの手法です。しかし、本質は変わらず、利用者視点で具体的なシナリオであるため、違和感なくどんな開発プロセスでも共通する設計の肝なのです。
後半はデモということでRubyという特定言語に依存する形になる部分は懸念点でもありましたが、実際にはユースケースからCucumberのシナリオに落とし込むまでは言語がどうという話がまったく関係なく、それらのシナリオを実行する部分(ステップ)からRuby/Railsに依存していくという流れになっているため、今回のテーマと非常に相性の良い形となりました。今回の演習は、Ruby,Java,PHP,Python,Smalltalkという5言語5フレームワークで行われましたが、ユースケースは全チーム共通です。同じ事を受入テストでやるとして、どのように実装していくか、その部分が大きすぎればTDD(RubyでいえばRSpec)に落とし込んでいくという流れが伝わったのであれば幸いです。
尚、最後の振り返りや感想などを聞いても、今回のTDDBCでは「Cucumberすごい!」という声を多く聞きました。実際に導入していくにはTDDよりも高い障壁が多いと思いますが、ATDDも学ぶべきスキルとして認識してもらえた事は大きいと思います。

これらの講演についても Ustream録画もされていますので、時間のある方はどうぞ。

講演3

演習の谷間に休憩的な意味も含めて、3本柱と自動化の講演を行いました。最初に15分ほど3本柱のセッションを行い、さぼてんさんこと@cactusmanさんに自動化とJenkinsについて話して貰いました。

TDDBCと言えばバージョン管理や自動化も欠かせない要素です。札幌開催ではバージョン管理についてはあまり突っ込んでやってはいませんが、自動化については重みをおいてやっています。そこで、さぼてんさんにJenkinsの話をして貰いたくゲストとして来札して頂きました。内容としては比較的に入門者向けな内容ですので、普段から自動化/Jenkinsを利用している人にとっては少し物足りなかったかもしれません。個人的に興味深いなと思ったのは、インストーラなど導入の敷居を低くするために色々と頑張っている点です。まずは使った貰ってなんぼというのはWordpressの例を見ても、オープンソースとして重要な要素です。最近は、Jenkins本体のアップデートやデグレた時のバージョンダウンなども管理コンソールから出来るようになり、より便利になっています。また、今回得た収穫としては、あえてローカル環境でJenkinsを使い、TDDのテストを裏で回すという運用方法です。これは分散SCMを使っている時などは特に有効な手法だと思うので、是非研究したいですね。

こちらはUst録画失敗しました・・・ごめんなさいorz

演習

午後の演習は各チーム3−4名(うちTA1名)でチームを組み、ユースケースを元に開発を行いました。今回は1時間の演習+20分程度のレビューを4セット行い、4ユースケースを実装する目標で行いました。実際には中々進捗が良くないチームもあり、3ユースケース程度が標準的だったのではないかと思います。これはフレームワークに関する習熟度とテストをどの単位で作っていくかについて悩む時間の差だったと感じます。
Ruby/Ruby on Railsチームは、ATDDを実戦すべくCucumberを使い、実装はほとんどRailsのscaffoldを利用していたようです。したがって、プロダクションコードはほとんど書いてません。2チームありましたが、Cucumberに慣れる部分で時間をとられていたようですが、テストシナリオがユースケースから自然に落とし込める部分は一番楽だったように見えました。難点を言えば、シナリオが単純すぎて、そしてRailsが優秀すぎて、プロダクションコードはほとんど何も書かなくて良いため、TDDで行うRSpecによるユニットテスト部分をあまりできなかった所かもしれません。最後に感想の1つとして、「以前TDDBCでJavaやった時よりもスムーズに書けた」といった話がありましたが、これは言語の特徴もありますが、テストコードを書くというスキルがついてきている点と「何をテストすべきか?」が見えたかどうか?に依存する部分かな、と思います。複雑なプログラムをTDDする時に一番難しい事は、どの部分をどのようにテストとして切り出して、何を検証するかと設計する事なのです。
Java/Slim3チームは、JUnitを使いTDDを実戦していくようなイメージでした。DaoやController等を作り、クラス単位で必要なコンテキストを考えテストを書いていくのは、Javaらしいなと思います。各クラスの設計などは色々と試行錯誤していたようで、レビュー時に引数が現在の仕様依存である部分についてツッコミを入れたところ「今回はこれで、次に修正が必要なときにはパラメータ化する」といった割り切りを行っていたのは興味深いところです。この辺り、最初から仕様変更に柔軟に対応できるように過剰設計したりしがちですが、時間とのトレードオフもありますし、Javaならばリファクタリングのリスクが低いという点を考えると、ありな選択なのでしょう。
PHP/Symfony2チームは、まだリリースされて間もないフレームワークということで、TAが事前に地雷を踏みまくって準備していた点もあり、個人的にはMVPを差し上げたい所です。色々とdisられたりTDDBCでは人気のないPHPですが、Symfony2のソースを見る限り、RailsSlim3などとそれほど遜色のないテスト機能やscaffold機能を持つフレームワークのようです。レビュー時にテストコードなどを参照しても、なんとなく読めるというのが印象に残りました。
Smalltalk/Seasideチームは、今回はそれほどSmalltalk無双とはならなかったようです。やはりあまり利用していないフレームワークを使っている部分での調査などに時間を消費され、慣れてきた頃には中盤過ぎていたといった感じでした。ただ、調査の時に1回もぐぐらず、内部環境で調査が完結するあたりはSmalltalkスゲェという部分です。また、SeasideではHTMLオブジェクトを駆使してページを構築するのですが、HTMLテンプレートはつかえない(オブジェクトじゃないし)、というあたり面白いフレームワークです。多の言語のモダンなフレームワークと比べると機能的にも物足りない部分もあったようで、その辺は今回の題材には不利だったのかもしれません。
Python/Djangoチームは、自動化の講演と前日のJenkins勉強会のためにゲスト参加されていたさぼてんさんを含め、相変わらずフリーダムにやっていたようです。最初の段階で、どの部分からアプローチしていけばいいかという点はアドバイスしましたが、それ以外ではほとんど自由奔放にやっていました。最初に悩んでいた部分は、どんなテストから書いていくかという点であり、この部分は慣れるまで解りにくい部分かと思います。特にユニットテストを意識していると、「あるクラスのあるメソッドを作るためにテストを書く、インプットとアウトプットを考えてインターフェイスを決めて・・・」となりがちです。しかし、特に受入テストレベルであったり大きめな単位でテストを書けるときには、最初にテストのコンテキストを考えるべきです。つまり、「こういう状況の場合、何が必要か?これをインプットしたら何がアウトプットされるか?」といった状況です。副作用や前提条件のない「足す」といった機能の場合はコンテキストが特にありませんが、ユースケースレベルの受入テストから落とし込む場合は、前提条件が肝になってきます。

*1:最近、「意識が高い」というフレーズを使うと絡まれるので志にしましたw