2014/12/13(土)「Code Retreat in Sendai」に参加しました。

プログラマ向けイベント「CodeRetreat」が仙台で初開催とのことなので、行ってきました。

CodeRetreatは「コンウェイライフゲーム」をテーマに、
主にペアプログラミング、TDDの学習を行うイベントです。

1回45分のセッションを6回行う、なかなかハードなイベントです。
セッション後には毎回コードを削除して、次ははじめから行ったり、
セッションごとにペアや使用する言語を変えて行うため、
新しい考え方に触れることができます。

セッションごとのテーマ

セッションごとにテーマが設定されており、
同じライフゲームを記述するにも、毎回悩まされました。

Session1.特に制約なし
Session2.テストコードとプロダクトコードの入力者を分ける。
Session3.5分ごとに入力者を交代する。(後に、2分ごとに変更)
Session4.プリミティブな値の使用禁止。
Session5.if文,Switch文使用禁止。for文,while文使用禁止。
Session6.変数はすべてimmutableにする。

関数型言語を使って

使う言語に特に制約がなかったため、Haskellの使用を提案したら、
意外と周りの食いつきが良かったです。
割と適当な説明ばかりしていたと思うので、
皆さんに十分に関数型言語の魅力を伝えられなかったと大いに反省しています。

あと、Session4~6のテーマはオブジェクト指向開発に合わせたテーマでしたね。
関数型言語では、再帰関数を積極的に使う文化があるため、Session5のfor, while文使用禁止はほとんど影響ありません。
Session6の「変数すべてimmutable」については、Haskellの場合、デフォルトで変数がimmutableなので、普段通りにコードを書けます。mutableな変数を扱う方が大変です。

オブジェクト指向派の方との意見のギャップは良い刺激になりました。
オブジェクト指向的な設計がどのようなものなのか、
他の人の話を聞いて、普段とは違う考え方に触れられました。

テストの粒度

TDDの初手として、
今回のテーマで最も上流となる(と思っている)テストから書き始めました。
ライフゲームの初期状態を受けとり、
次の状態を返す関数のテストを書きました。
しかしそれだと、テストの粒度が大きすぎて、
テストが通るまでに時間がかかり過ぎる、と指摘を頂きました。

確かに、「このテストでは粒度が大きすぎて、そのテストが通った時点でほぼ実装が完了している」と思いました。
ですが、「粒度を細かくした時の、分割が妥当であることをどのように保障するのか」という疑問が浮かびました。

TDDの基本として「プロダクトコードを書く前にテストコードを書く」というものがあります。
しかし、この前提として、「設計が十分にされていること」があるのではないか、と思いました。

HaskellにおけるTDD

Haskellだと、TDDに設計フェーズをプラスして、サイクルを回せるのでは、と考えてます。
ここの考えはまだ試作です。

Haskellの場合、「型を基づく設計」が可能です。
関数を定義する際に、実装をundefinedにして、型のみを定義することができます。

そのため、以下のような手順によって「設計⇒テスト⇒実装」のサイクルが回せるのではないか、と考えています。
1.作成したい関数の型を定義する。
2.1の関数を実行するときのテストを用意する。(テストは失敗する)
3.1の実装を記載する。必要であれば、新しい関数を型のみ定義する。
4.3で定義した関数のテストを用意する。(テストは失敗する)
5.2のテストを無効化(コメントアウト)する。
6.3の実装を記載する。
7.4のテストが通ったなら、5で無効化したテストを有効化する。

まとめ

いざ、書いてみたら、全然考えがまとまっていないことがよく分かりました。
オブジェクト指向と関数型の違い」や「関数型言語とTDD」は興味深いところなので、
一度整理してみたい話です。

あまり、CodeRetreatの参加レポートっぽくはありませんでしたが、
お題となった「コンウェイライフゲーム」のHaskellコードをイベント後に作成してみました。
TDDでの開発ではないので、テストが若干おろそか気味。

toshimana/lifegame · GitHub

Code Retreatでは、思考をpanic zoneに持っていくことで普段より多くの学びを得ることを目的としていますが、イベントが終わった今がまさにpanic zoneに陥ってます。
このpanic状態をうまく解決して、よりよい開発ができるようになりたいです。