こんにちは、ふーが(@fugakkbn)です。
最近ダイエットのためにジョギングと食事制限を始めました。2週間ほどで 1.5kg 体重が減ったので、この調子で目標の 55kg まで続けたいなあ。
さて、僕は「りんどく.rb」という Ruby 関連書籍で輪読会をしよう!というコミュニティを運営しているのですが、そこでおもしろい取り組みをしたので紹介します。
なにをやったのか
伊藤淳一さん著、「プロを目指す人のための Ruby 入門」通称「チェリー本」のサンプルコードに機能追加をしてみました。
りんどく.rb ではこのチェリー本の輪読会をしていまして、Chapter.7 はクラスに関する章で例題として「改札機プログラム」を作ります。
ちょうど改札機プログラムを終えたタイミングで伊藤さんがりんどく.rb に来てくださり、「改札機プログラムで Suica を使えるようなプログラムを組んでみたら、クラスの理解が深まっておもしろいんじゃない?」とご提案いただきました。
当時参加してくださっていた皆さんも「ぜひやりたい」という声が多く、みんなでわいわい議論しながら設計〜テスト〜実装をやってみることになりました。
今日の #りんどくrb に #チェリー本 著者の伊藤さん( @jnchito )が来てくださり(ありがとうございます!)、7章の例題やシーケンス図をわかりやすくご説明いただきました🎉
— ふーが (@fugakkbn) 2022年5月27日
発展編として演習のご提案もいただき、さらにレビューまでしていただけるとのことでさらにおもしろくなりそう😄なイベント↓ https://t.co/YuFqhih0qk
なぜやったのか
僕を含め参加者の皆さんからのお声をまとめると、以下の理由から「やってみたい」と表明してくれた方が多かったです。
- クラスの理解が深まりそう
- 議論しながら設計していくのが楽しそう
- テストのシナリオを自分で考えたことがないのでやってみたい
個人的には議論しながら設計するのがチーム開発っぽくて楽しそうだな、と思いました。
実際この予感は当たっていて、自分にはない観点や考え方を知る良い機会になりました。
機能追加の流れ
では、どういった流れで機能追加していったのかを、具体的な内容も交えて紹介します。
設計
まず最初に設計をするための情報をまとめることから始めました。
Suica ってなんだろう?
ここでは「Suica ってなんだろう?」という哲学的な問いから始めることにしました。
どんなモデルを作る?
出た情報をもとに、「どんなモデルを作る?」を議論した結果が以下です。
議論の結果、Suica モデルを追加するのがよさそう、という結論になりました。
Suica モデルはどんなふるまいをする?
ではこの Suica モデルはどんなふるまいをするのでしょうか?
あわせて、「ふるまいをメソッドで表現したら?」というのも考えました。
シーケンス図
さらに、ここまでの議論でまとまった設計をシーケンス図に落とし込んでいきました。
ストーリー出し
ここまでで Suica モデルの概念やふるまいが固まってきました。
次は「どういう使われ方をするのか」を考えるストーリー出しをしていきます。
以降のテスト・実装はここで出たストーリーをもとに進めていくので、漏れがないよう一生懸命捻り出しました。
テスト・実装
ここまで決まればあとは実装あるのみ!
TDD に慣れるため、まずはストーリーをもとにテストコードを書いてから実装、実装ができたらリファクタリング、という順序で進めていきました。
GitHub に実装用のリポジトリを作って fork してもらい、その日の修正をプルリクエストにしてもらいレビュー、マージ、という OSS 的な進め方ができたのもよかったです。
完成品はこちらです。
チェリー本の改札機プログラムとの差分はこちら。
学んだこと
約1ヶ月半取り組んでみて、輪読会とは違った気づきや学びがたくさんありました。
特に印象に残っていることを書きます。
設計の考え方・難しさ
普段のお仕事でも感じていることですが、設計に唯一の正解はない、というのが難しいところだなと改めて思いました。
ベストプラティスやアンチパターンを理解しつつ、実装がしやすく、利用時に扱いやすい設計を考える力が必要だと実感しました。
また、現実世界でのふるまいとプログラムとしてのふるまいのバランスも難しかったです。
基本的に現実のふるまいを踏襲したプログラムの方がいい、という考えがありましたが、あまりに近づけすぎるとプログラムとしての実現が難しくなることもあり、そのバランス感覚は一朝一夕で身に付くものではないですね。
ストーリー出しの観点
モデルやメソッドのふるまいを検証するのに必要十分なストーリーを出すことで実装がスムーズに進むことを肌で感じることができました。
ストーリーがあるおかげで「どんなテストを書けば何を検証できるか」が視覚化されて実装に迷いがなくなったと思います。
また、伊藤さんからは「具体的な数値を使う場合には境界値をテストするようにした方がいい」というアドバイスもいただきました。
これまで適当な値(テストがパスする・しないしか考慮していない値)を使ってしまっていたので、大切な観点を教えていただきました。
TDD の流儀
Red → Green → Refactoring のサイクルを回しながら実装を進めていく、というのを頭では理解していても実践することができていませんでした。
今回はこの流儀に従って進めたおかげで、「こんな感じでやっていくんだ」というのを肌で感じられました。
また、終盤にはシナリオは足りていないが実装は済んでいる、というケースもあり、シナリオをもとにテストを書いたら1発で通ってしまうということがありました。
そこで伊藤さんから「そういう時はわざと Red になるようなテストで1度 Red にして、そのあとに正しいテストで Green になることを確認すると良い。意図しない形で Green になっていないことを確認するのが大事」と教えていただきました。
あわせて「テストが1発で通ることに不安感を覚えるのは良いこと」とも言っていただき、TDD の流れが多少なりとも身についたのかな、と嬉しく思いました。
おわりに
伊藤さんからご提案いただいてノリで始めた特別回でしたが、当初想像していた以上に多くの、そして大きな学びがあり、本当にやってみてよかったです。
設計やストーリー出しなど参加者で議論することも多かったため、今まで以上に参加者の皆さんの考え方などを知れたのもうれしかったです。
機会を作ってまた同様のことをしてみたいと思います。
みんなでわいわい議論したい、設計を学んでみたい(教えてやろうも大歓迎です!)、という方はぜひ一緒にわいわいしましょう!
最後になりますが、1ヶ月半という長期間にわたり朝の貴重な時間にお付き合いいただいた伊藤さんに改めて感謝いたします。
本当にたくさんのことを教えていただき濃密な1ヶ月半でした。伊藤さん、本当にありがとうございました!!
宣伝コーナー
りんどく.rb たのしくやっています
紹介したような感じでりんどく.rb ではゆるくわいわいと楽しんでいます。
「Ruby にもっと詳しくなりたい」「チェリー本をもっと深く理解したい」「わからないところを聞く場が欲しい」という方のご参加をお待ちしております。
プロを目指す人のための Ruby 入門 第2版 〜通称:チェリー本
りんどく.rb で輪読している書籍です。