はじめに
先日、同僚と「自動販売機の CLI アプリ」とお互いに作って発表し合うということを行いました。題材はこちらを使わせていただきました。
この題材をステップ 0 からステップ 7 まで各々が個人作業で作ってみて、最後にコードレビューをし合うというものです。
題材をご覧いただくとわかる通り自動販売機というのは意外に仕様が複雑で、ちゃんと設計しないとステップが進んでいくごとに大きな書き直しを迫られてしまうという自分の設計力がもろにアウトプットの質に関わってくるという少しハードな題材でした。
結構大変な思いをして書いたので、せっかくなら公表しようと思い記事を書くことにしました。
因みに TDD Boot Camp から題材を拝借していますが、TDD で書いたわけではないです。
作ったもの
私が作ったものは以下の github に上げています。
どうせなら普段の業務ではあまり実践できていないことを思い切ってやってみようと思って書きました。
以下に今回意識したことを書いてみようと思います。
設計思想
主に以下の 2 つを意識して書きました。
- メタプログラミング
- MVP
メタプログラミング
自動販売機なので「お釣りの管理」をしなければならず、どの硬貨をいくつ所持しているかをちゃんと管理する必要があります。
また硬貨の種類が増えたり、今はお札は 1,000 円札しか対応していないが 1 万円札にも対応させたりするなどの仕様変更が考えられたので、硬貨の種類を管理している箇所を一箇所変えれば必要なメソッドが勝手に生えてくるようなメタプログラミングで書くようにしました。
CashBox
モデルにそのロジックを書いています。
https://github.com/kakihara0512/vendind_machine/blob/master/models/cash_box.rb
メタプログラミングについては、以下の書籍で学んだことを意識して書いてみました。
MVP
もう一つ意識したこととして、プレゼンター層を取り入れて MVP で書くことにしました。
これは例えば何かデータの更新を行うとき、ビジネスロジックが書かれた Model のメソッドを呼び出すことになりますが、直接 Model のメソッドを View から呼び出すのではなく Presenter 層を通して呼び出すようにしています。
またターミナル上に表示させる文言などは、なるべく View にベタ書きをせずに Presenter 層に書くことで View が荒れるのを防ぎました。
反省点
上記のようなことを意識して書いたのですが、以下の 2 点が反省でした。
eval
をやたら多用している点
初めてメタプログラミングで書いたため、どう書くのがベストプラクティスなのかが分からず、やたらと eval
を多用して可読性が低く、コードインジェクションのリスクを一定孕んだコードになってしまいました。
もらった FB として、define_method
を使って書けばもうちょっとマシになったかもというものがあり、確かにその通りだなと思いました。
main.rb
のロジックはまだ Presenter 層に寄せることができた
main.rb
のロジックはもう少し Presenter 層に寄せることができたなと思いました。
今の main.rb
はまだロジックが多く書かれていてこのファイル自体のテストが必要なくらいですが、テストが書けない程の複雑性を持ってしまっているので、この辺はもう少しなんとかなったかなと思いました。
終わりに
「はじめに」でも書いた通りハードな課題でしたが、設計の勉強になってとても良かったです。
この記事を読んだ方も是非チャレンジしてもらえたらと思いました。