読者です 読者をやめる 読者になる 読者になる

ゼロからReduxを学びボドゲのシミュレーターを作った

モダンなJSの開発環境とReact/Reduxを習得したくて、課題としてちょうどハマってたボドゲのシミュレーターを作った。

デモ

Dungeon of Mandom Simulator

ソース

github.com

ReactとFluxは一時期趣味で触ったことがあるくらいで、記事を遡ったら既に2年前の話だった。

norizabuton.hateblo.jp

技術選定

ビルドツール

babel/Webpackを使用。小規模なJSにbabelを使いたいだけであればbabelifyを通すだけで良さそうだが、今回はきちんと学ぶという名目なのでWebpackをちゃんと整備することにした。後々css-loaderを使ってCSS Modulesを試すこともできたのでこの選択は良かった。

AltJS

型が欲しいと思いTypeScriptかFlowで迷った。TypeScriptは現在ReactやAngularでもサポートされており、息が長そうで学ぶ価値は高そうという印象だが、既にbabel/Webpackでビルド環境を構築しており、ここからts-loaderを導入してTS用の環境を作るのが面倒だった(この時点で既にビルド環境構築に1週間ほど費やしている)ので、今回はbabel/Webpackに比較的乗せやすいFlowを選択した。

テスティングフレームワーク

node.jsでサーバーを立てた時にmochaでテストしていた経験はあったが、今回はReduxも推しているJestにし、assertはpower-assertを使ってみた。Jestはmochaと比較しても記法は対して変わらないので学習コストとしては大したことはなかった。デフォルトでMockになるので単体テストが容易という特徴があるらしいが、依存しているモジュールが少ないせいか今回はあまり恩恵を受けられなかった。

デザイン

同僚からantが綺麗で良いというオススメをもらったがmaterial-uiが使いたかった。使ってから気づいたがmaterial-uiにはBootstrapのGrid Systemは標準では存在してなさそうで、導入したければ恐らくサードパーティのものを使う必要がありそうだった。

エディタ

最近AtomからVS Codeに乗り換えたのでこれで書いている。Flowを入れてから気づいたが、VS Codeで型を定義すると.tsでないと使えないぞと怒られる。*1

f:id:Peranikov:20170318103654p:plain

これを回避するにはVS Codeの設定で "javascript.validate.enable": false とすれば良いのだがあまりに場当たりっぽい。

下記設定を試したところjsのコードハイライトが消えてしまったのですぐ戻した。

"files.associations": {
      "*.js": "flow"
    }

github.com

Issueの方でも正式な解決策は無さそうで今のところは警告を無視するしかなさそうな気がしている。つらい。

デプロイ

静的サイトなのでgh-pagesを使いGithub pagesにデプロイした。1コマンドでデプロイできめっちゃ便利である。

Redux所感

このくらいの規模のアプリケーションであれば正直Vue.jsを使ったほうが速く書けるし設計もさして重要ではなさそうである。各レイヤーの役割を覚えるまではコードが分散するので追っていくのが大変だが、慣れてくればどこを修正すれば良いのかがすぐわかるので後のメンテナビリティは上がりそうな気はした。

Modelレイヤー

Reduxを書き始めてすぐに気になった所は、どうやらロジックがreducerに集中してどんどんFatになっていく気がした。なので、下記記事を参考にimmutable.jsとModelレイヤーを導入した。*2

post.simplie.jp

モデルにロジックが集約していくのでテスタビリティも向上し、ロジックの見通しも良くなったと思われる。

それとは別に、Containerなどでコレクションのフィルタリングをしているのだが、モデルの構造を意識してフィルタリングしたくなく、もっと抽象的に扱うためにファーストクラスコレクションを導入したくなった。が、immutable.jsのコレクションは直接拡張することはどうやら難しそうで、公式でないextendable-immutableを用いれば実現できそうな気がしたが、なんとなく依存を増やしたくなく、PureなJSで色々試していたがあまりうまくいかなかった。良い例があったら知りたい。

Constantsの意味

ReduxではActionとReducerはActionTypeという文字列のキーを使ってロジックを紐付けるのだが、わざわざ定数を介する意味が見えず最初は直接文字列で書いていた。途中で気になって調べたところ、下記記事からメリットが複数あることがわかった。

stackoverflow.com

要約すると、

  • ActionTypeの一覧性が1つのファイルに集約するので、既存のアクションが把握しやすく名前の一貫性を保ちやすくなる
  • IDEを使っていれば補完が効くのでタイプミスを誘発しにくくなる
  • 変数名を介してアクセスするので、minifyの効果が向上する

ということで、ActionTypeのファイルを設けることにした。

デバッグ

イベントが発生後にStoreがどのように変化したかデバッグするために方法を探ったところ、redux-devtoolを見つけた。redux-devtoolはとても高機能で、Storeの状態を確認する以外にもActionのUndoやResetが可能らしいのだが、専用のComponentを導入する必要があったり、コードを多く変更する必要がある印象を受け、敷居の高さを感じ今回は見送った。それとは別にredux-loggerというものを見つけた。こちらはイベントの度にStoreの変更前と変更後をロギングしてくれ、比較的導入も楽で必要十分と感じたのでこちらを使用した。

テスト

公式を参考にaction/component/reducerのテストを書いてみたが、ロジックが大したことないのもあって、あまり必要性を感じなかった。Actionは外部APIを叩いたり非同期な処理が増えてくると有用性も高まるかもしれない。Componentsのテストも試しに書いてみたが、デザイン性に大きく関わる部分なのでどういう観点でテストを書けば良いのかがまだあまり掴めていない。Componentsにロジックが寄るのは恐らく設計としてあまりよろしくなさそうだし、UIについてはE2Eテストを別途設けたほうがむしろ有用ではないかという疑念が残っている。

さいごに

ダンジョンオブマンダムは良ゲーだったので買って遊ぶと良い。

ダンジョンオブマンダム

ダンジョンオブマンダム

*1:いかにもMSが作ったエディタっぽい挙動

*2:どんどんFacebookに染まっていくぞ〜