Yokohama.rb でCosVONをペアプロしてみた話 #yokohamarb


@ryonext と。僕の前職で一緒の会社だったらしいのですが、実際に仕事を一緒にやったことはありませんでした。
僕の書いたコードをまだいじることがあるらしいので今回ペアプロできる機会があって初めて一方通行でなくなった感じなのかなwww

一部の人には節子それペアプロちゃうと突っ込まれましたが、上記の経緯もあってちょいと変則的にしようと決めていました。

コミットを追いながら、ペアプロの流れと意図の解説と振り返りをやろうかなと思います。

## @Nabetani による問題

http://nabetani.sakura.ne.jp/yokohamarb/2014.01.cosvon/

CosVON(Commna Separeted Value Object Notation)でだいたいわかると思います。

問題みた瞬間に、あぁ面倒なことは気にしなくていいので短時間でささっと作るのにいい問題だなと思いました。
特に「値のあるセルの右に空でないセルがあった場合の動作は未定義」とか、「Hash のキーが重複しているような CoSVON を読み込んだ場合の動作は未定義」とかかなりゆるふわでいい感じだと思いました。

また、見た瞬間99%くらい実装が固まったのですが、その頭にある実装を元にテストデータを見ると、テストデータがよく考えられてできているなぁとニンマリ。

Yokohama.rbの参加は1年3ヶ月ぶりだったのですが、前に行った時も多分 @Nabetani さんが問題出してくれて楽しかった記憶があるので、こういう問題が定期的に用意されているYokohama.rb++ですね。

## [初手：bundle gem](https://github.com/ryonext/cosvon/commit/277bcf2ed914d3d96c6c9aa7e5a3e81dca8031d7)

今思い返せば、`bundle gem CosVon` してしまったのが良くなかったですね。
`cosvon` にした方がよかったと思います。

`bundle gem`しただけで、@ryonextがコミットしましょうといったのでコミット。
僕のいつもの流れとしては、gemspecのsummaryとかdescriptionとかを直してからinitial commitとやるので、このタイミングは新鮮でした。

## [2手目：add rspec](https://github.com/ryonext/cosvon/commit/5d3cec078c281ad02a0602ec49460899913af096)

正確には、初手でやらなかったgemspecのsummaryとdescriiption（およびauthor)の編集と、rspecの追加。
どうせならrspec3でやろうぜとbetaでやってみました。

`rspec --init`でテンプレを作成。

## [3手目：Cosvon 使えるよねのテスト](https://github.com/ryonext/cosvon/commit/026edd1d07843212c68bd476a19d515aab4ae57c)

TDDで最初に書くライブラリのテストとしては、ライブラリの名前空間がちゃんとロードされていることのテストですね。

```ruby:spec/lib/cosvon_spec.rb
describe Cosvon do
  it { true }
end
```

よく書くのはこんな感じのコードです。Cosvonモジュールがなかったり、テストでうまくrequrieできないと落ちます。

なお、ここのコミットと同時に`CosVON`を`Cosvon`に修正してます

(@ryonext ファイル名の修正できてないじゃん！）

## [4手目：テスト自動実行](https://github.com/ryonext/cosvon/commit/7cef46472166ab7b68ed5ed7ead9480991b27430)

[いつぞやのAdvent Calendarでも書きました](http://qiita.com/okitan/items/25238a9b836c14d52cbd)が、テスト自動実行というのは大事。特にこういう短時間での作業にはね。

なお、最近全く guard-rspec とか使ってなかったので、コンソールでの入出力が進化していて感動しました。

ここまででガリガリ書いていく準備が整ったので、本格的に開発をはじめていきます。

## [5手目：first spec](https://github.com/ryonext/cosvon/commit/40d580a7d8b16356281a5040a601d03b623b8f5b)

一般に時間がかかるのは、このTDDの最初のREDになるテストを書くまででしょうね。
要はどういうインターフェースにするかを決めて、最初にドッグフーディングしてある程度納得しないと、first specできたよーってコミットにはならないからです。

今回の場合どういうインターフェースにしようかねぇと決める際に、オレオレではなく、既にあるライブラリを真似ればいいじゃんってことにしました。
似たようなライブラリとして、yaml、またそもそもCosVONはCSVなので、csvのインターフェースをみてどうするか考えようぜとなりました。

僕的にはyamlで行きたかったのですが、@ryonextがcsvでいいじゃんって言い出したのでcsvにすることにしました。

なので、[るりま](http://docs.ruby-lang.org/ja/2.1.0/class/CSV.html)をみて、`CSV.parse`のような感じにすることにしました。

データは問題からさくっとコピペしてfirst specが完成。

### [6手目: 実装](https://github.com/ryonext/cosvon/commit/822eff0fec9a5975926709ec130699fa91550f2c)

実は（一人で）一番迷ったのはこの問題を特上でcsvを使うか使わないかだったんです。だってcsv使うと簡単すぎるでしょw
`Hash.[]`に食べさせやすいように2重配列返ってくるしw

なんですが、@Nabetaniさんが用意したテストデータの3番目が真面目にcsvパースできないと死ぬようなデータだったので、あぁこれはcsv使えよって出題者が言っているのかなと思ってcsv使おうという風にしました。
多分このテストデータが一番下にあるのであったらcsv使わなかったと思う。

あと、ヒアドキュメントをインデントしているのに気付かず、テストが最初通らずに若干焦りました。rspec の diff を狭いターミナルで見ると、改行されているように見えて、あれなんで改行？って思って、じゃあ`CSV.parse`の返り値どうなっているかみてみようってことで`tapp`を使おうということに。
たぷぷたぷぷと連呼してたのはこのあたりですねw

@cielavenir さんから`tapp`じゃなくて`p(obj)`みたいな感じでやるといいよ教えて貰ったのですが、自分はワンライナー厨なので、1行に`tapp`たくさん埋め込みたいので、`p`を使うのは限界があるなぁと思いました。

### [7手目: CosVON宣言のチェック](https://github.com/ryonext/cosvon/commit/470844994429688fcbf0fb8c413a5e4962ee9d34)

6手目を実装している途中に、1行目がないときって例外投げるよねぇという話になったのですが、正常系の実装している途中に異常系のテストケース追加するのは、よくないよねぇってことで、6手目ではこういうテスト書くことというTODOだけ書いて、正常系の実装が終わってからの実装。

ちなみに、仕様を見落としていたのですが、

> 最初の行には CoSVON:0.1 と、書かれている。また、 
CoSVON:0.1,,,"",, のように、コンマや、空のセルが何個か続いていても良い。 
言い換えると。 
最初の行の最初のセルには CoSVON:0.1 と書かれており、それ以外のセルは、空である。

なので、ここでの実装ではだめですね。

### [8手目: テストたくさん追加](https://github.com/ryonext/cosvon/commit/1bc52a37c530f5e14cee4339680bf95084ce61a6)

実装できたのでテストケースを追加していきます。csv無双で、3番目のテストデータは軽くパスして、6手目ではあえてスルーしておいた空の文字列とかnilの文字列とかが入ってくる場合まで順調に進撃。

ここらでテストデータを追加しやすいようにパラメタイズドになるような仕組みを導入。
パラメタイズドに改造しながら、本来のテストというのは、テスト目的に対応するテストデータを作るから、こんな単純なループにしたらだめだよーとかしゃべってました。
まぁ今回は@Nabetaniさんがうまいことテストデータを作ってくれているので、ひとまずはそれで十分ですね。

### [9手目：続テストたくさん追加](https://github.com/ryonext/cosvon/commit/cd0876e5a97e4019105072ff7496b1fcbfe6c5a3)

テストデータを全部追加し終わったというところでタイムアップ。
ファイルへの読み書きは時間が足りませんでした。
あとでプルリクしておこう。

### まとめ

ちょっぴり私的な事情で@ryonextとと変則的なペアプロになったのですが、コードを書くときにあたっての考え方とかをうまく話し合えたのとかがよかったのではないかなぁと思います。（多分）

あと、やっぱりお互いレビューの時間とかあったりしてもいいのかなぁとは思ったのですが、時間の関係上無理そうかなぁ。。

ちなみに今回のCosVONは以下の3つにあがってるぽいです

* https://github.com/yokohamarb/CoSVON
* https://github.com/cielavenir/cosvon
* https://github.com/ryonext/cosvon