PHPカンファレンス2013に行ってきました。Zucksの中の人によるハイパフォーマンスを実現する運用方法の紹介、内容もプレゼンもクオリティ高くてびびりました。(小並感)
個人的に一番つぼったのはEmergent Design with PhpSpecです。PhpSpecの開発者のMarcello DuarteさんによるphpspecとBDDについての講演でした。正直、自分の中でBDDってなんだかよくわかってなかったりphpspecってrspecのphpインポート版じゃないの?*1とか思ってたんですが話を聞く中で納得した部分が結構ありました。スライドはこちらEmergent design with phpspec。英語ですがシンプルで分かりやすかったです。
昨日聞いた話を自分の中でまとめる意味も込めて下に書きます。詳しくは上のスライドを見てください。聞きかじっただけの知識だったり独自解釈入ってたりで間違ってるところもたくさんあると思います。ご了承しろ( ´_ゝ`)ください。
BDD
BDD(Behavior Driven Development)は日本語では振舞駆動開発と呼ばれる開発手法です。ここでの振舞というのは、オブジェクト間のメッセージ通信、つまりオブジェクトがどういう入力を受け取り、どういう出力を行うのかということを示します。BDDでは、この振舞に着目した開発を行います。手順としては
要求(Spec)を元にテストを作成する。
テストが通るようにコードを書く。(ここでは積極的にモックを使いコード量を抑える。)
振舞が変わらないように(テストが通るように)コードのリファクタリングを行う。
の繰り返しです。
このようなサイクルを踏むことで、作りたいもの(要求=spec)を少しずつ取り入れながら徐々に要求を追加していく・必要なものから順に取り込んでいくアジャイル開発が出来るという寸法らしいです。*2またこのような手順を踏むことでオブジェクトの役割・責任・メッセージに基づいた変更にやさしい設計が可能になるらしいです。*3
何をテストすべきか
一口に要求といっても全部をテストしていたらキリがありません。そこで、どういう基準でテストを行うべきか決めるために、メソッドで何が起こるか考えます。何でも出来るといえば何でも出来るのですがオブジェクトの振舞という観点から考えると次の5つにまとめられます。
値を返す。
状態を変更する。
何かを表示する。
例外を投げる。
処理の移譲(デリゲート)を行う。
このうち、状態の変更は最終的な振舞(入力や出力)ではありません。また、表示はデリゲートの一種だと考えます。こう考えると、実はメソッドでは
値を返す。
例外を投げる。
処理の移譲(デリゲート)を行う。
の3つしか起こらないと考えることが出来ます。なので、この3つの処理に着目すれば、オブジェクトの振舞を監視するテストを作成することができます。3つのうち値や例外に関してはassertionなどで簡単にテストを行うことが出来ます。残るデリゲートはモックを使ってテストを行います。そしてデリゲート先で、また振舞に基づいたテストを行います。
リファクタは何をすればいいのか
リファクタリングといっても色々あるので、どうしたら変更に強い構造を作れるのかという問題が出てきます。講演ではリファクタリングの際のシンプルなルールが4つ挙げられていました。
phpspecについて
phpspecは当初rspecのphp版として開発されていましたが、rubyのような自由度はphpには無い(むしろruby wayとphp wayは異なる)ので書き換えたそうです。
目指すところは
使って楽しい
設計のための
邪魔にならない
(モックを利用した)TDDを行える
PHP流の
ツールということでした。
composerでインストールできるらしいのですぐスタートできそうです。 スライドにもありますが、インストール後まっさらな状態で
$ bin/phpspec describe Some/Class
とするとテストが出来ます。 その後
$ bin/phpspec run
としてテストを実行すると、当然クラスが存在しないのでテストに失敗します。このときphpspecが
Do you want me to create `Some/Class` for you?
と聞いてくれるのでyで答えるとクラスを作ってくれます。siriか! 次にメソッドのテストを書いてrunすると、これもメソッドが無いので作るかどうか聞いてくれます。メソッド等の作成が終わった時点でようやくコードを書きます。モックを使って出来るだけ簡単に書くのがポイントらしいです。以上の流れを繰り返して開発を行っていくのが基本スタイルらしいです。
まとめ
phpspecはテスティングツールではなく開発ツールとして使うことを想定されていることがクラス作成機能から伺えます。またphpunitと比べてテストに失敗した時のエラーメッセージが抑えられているのも特徴のようです。Behatとの住み分けとか気になりますが、書き方を考えるとBehatは受け入れテストとしてのBDD、phpspecはTDDの延長としてのBDDをそれぞれ提供するのかなと感じています。*4phpspecについては、どのようにphp wayなのかとか、モック周りはどうなっているのか、などの部分はまだ理解できていません。使っていく中で理解を深められたらなーと思っています。
BDDってつまりどういうこと?という疑問は、設計ってつまりどういうこと?という深い問題に直結しているので恐らく色々な解釈があると思います。色々な方面から学びながら理解を深めたいと思います。
っていうかアジャイルとかなんだとか言い出す前に普通の設計経験が少ないので精進します。
*1:最初はそうだったらしい。今は全部改修済みだとか
*2:ウォータフォール型の開発では、全ての要求を最初の段階で取り込もうとしてしまう。こうすると量が膨大になってしまう。しかも実際に提供されるのはそのうち61%、実際に使われる機能は27%しかないらしい!
*3:この辺は個人的にもっと勉強が必要
*4:このへんはhttp://www.phpspec.net/docs/introduction.htmlに記述があります。