タオルケット体操

サツバツいんたーねっとでゲームとかガジェットのレビューとかをします

令和にはじめるReduxの学び方

Sponsored link

本当に効率が悪いReduxの学び方

  いまある"フレームワーク"の中でReduxほど覚えるのが簡単なものはありません。
しかし(僕を含め)多くの人が学習の最初に躓きと強い苦痛を覚えるようです。何故でしょうか。
私見ではありますが、これにはReduxがどういう性格をもったツールであるかということ、それによって現在マジョリティを占めるフレームワークとは異なる学習スタイルを求められることが影響していると考えております。

理由は追々述べていきますが、一番効率の悪いReduxの学習方法は「覚えよう」とすることです。
(異論はあるかもしれませんが)Railsなどのフルスタック系フレームワークを習得するときには実装例を写経するなどして暗記から学習していくスタイルはかなり有効だとおもいます。しかしReduxを同じように学習していくのは遠回りどころか、最悪で何一つ得られるものはなくただ壊れたアプリケーションが手元に残って終了します。

Reduxとはなんなのか

ざっくり分けてしまうと、皆がReduxと呼んでいるものには3つのパターンがあります。

  • GitHubリポジトリに上がっているライブラリのRedux
  • Reduxが提唱するアーキテクチャのRedux
  • 公式、野良ブログなどに存在している実装例としてのRedux

そして、使ったことない人が雰囲気で言及する存在。秘匿された13番目のRedux技ーーReduxファントム。

これらの総体が巷でReduxとして呼ばれています。笑い男みたいなものです。
また、これはFluxの時代からそうでしたが正しいReduxを実装するための確固たるライブラリは存在しません。
公式からは補助ツールと思想のみが提供されており、ユーザーはそこから自分だけのReduxを作り上げる必要があります。お前がみているサンプルコードはReduxじゃなくてただのPure Function。

なので僕はReduxはメタフレームワークだと呼ぶべきだと考えています。そのほうがかっこいいので。

Reduxを学ぶための最高にして唯一のリンク

https://redux.js.org

Reactもそうですが、Reduxについて公式ドキュメント以上に説明してくれているものはありません。ReduxのリポジトリはこのドキュメントのSEOとためにあると言ってもいいくらいです。読めば玄人。
読みましょう。読みましたか?じゃあもうこの記事を読まなくて結構です。これから書くことはそこに全部書いてあります。

1ページたりとも読まない、読みたくない人はRedux使わないほうがいいです。そういうスタンスで使うならVueやAngularのほうがフレームワークとして親切かつ良質です(たぶん)。

とはいえ分量が多いので少しづつ読んでいくのがいいとおもいます(エラソーに書いてる僕も全部読んで把握してるわけじゃもちろんないです。そもそも英語得意じゃないし)。
すでに長らくReduxを実務で使っている人も応用編やレシピの部分、それとスタイルガイドは時々更新されていたりするので読むことで多くの示唆が得られるはずです。 https://redux.js.org/style-guide/style-guide/

Redux利用者が陥りがちな典型的間違い

典型的アンチパターンを把握しておくことは逆引き的に正しい理解へとつながります。
ちなみにimmutableな書き方を知らない、というのはアンチパターン以前の問題なのでここでは言及しません。

0. Reactの理解すら曖昧なままにデファクトだからと入れてしまう

ちなみにReduxは半ばReactを使う際のデファクトスタンダードのような扱いを受けていますが、そういった心構えで導入を決めるのは間違いです。

You'll know when you need Flux. If you aren't sure if you need it, you don't need it.

Pete Hunt

I would like to amend this: don't use Redux until you have problems with vanilla React.

Dan Abramov

そういうことです。
いまだに「Reduxは書き方が冗長だから使わないぜ」みたいなことをわざわざ主張したがる人間がいますが、書き方の冗長さ程度の瑣末事が一番の問題に上がる規模のコードにReduxは不要でしょう。

1. アプリケーションの状態への考察がないまま書き始める

そこそこの数のReduxを使ったアプリの実装をみてきましたが、過半数以上がこのアンチパターンを踏んでいました。
また日本語、英語を問わず、多くのブログ記事が公式ドキュメントを無視してこの設計スタイルを推奨しています。特に英語圏ではReactが圧倒的に使われている影響もあってレベルの低い記事が物凄く多いです。

Reduxは、こちらも近年ブームになっているクリーンアーキテクチャと非常によく似た存在です。
DDDというクリーンアーキテクチャの基礎となるアプリケーション設計の一つの流派、その理解と実践を抜きにして「単なるMVC的なモジュールのレイヤー分けのフレームワーク」としてクリーンアーキテクチャを採用して爆死するプロジェクトが後をたちませんが、Reduxでも同じことが言えます。

「画面の状態管理」をしたいならバニラのReactで充分です。contextが非公開APIだった時代と違い、今ではProp drillingを避けるのも簡単です。
React Hooksが出たときに「これでReduxは必要なくなる!」という全く意味わからない*1記事がバズったりしてましたが、そもそもReduxは必須のツールではありません。使いたい人が使うものです。僕は使いますが。

とにかく、Reduxは基本的にアプリケーションの状態を管理するためのツールセットです。
なのでViewの状態やバックエンドのREST APIの形式に依存した設計にしてしまうとそのうまみが十分に生かせなくなるであろうことは想像に難くないとおもいます。サーバーサイドの人はRailsのModelがルーティング先の一つにつき一つ存在するような状態を想像してみるといいでしょう。

ちなみにオフィシャルでここに言及しているくだりは以下にあります。

https://redux.js.org/recipes/structuring-reducers/basic-reducer-structure#basic-state-shape

As an example, a shape of state.leftPane.todoList.todos would be a bad idea

とあります。
ちなみにreducerをREST APIに対応させているパターンも公式で言及はされていませんがよく見かけます。たぶんシェルスクリプトCRUDに対応させて自動生成させているんだとおもいますが、ちょっと書けば無意味であることがわかるとおもいます。

ちなみにドメインデータに沿って〜〜と簡単に書いてますが、実際にそのようにしたコードをある程度複雑になっているアプリケーションの実装に適用しようとするとnormalizeやselectorのキャッシュについて知る必要が出てくるでしょう。こういう、芋づる式に必要な知識が出てくる感じが苦手な人は多いとおもいますが気合で乗り切りましょう。

2. 言われるがままに流行っているMiddlewareを入れまくる

本当に必要なものを必要なだけ入れましょう。
middlewareはなんでもできてしまう層です。middlewareの中に一つフレームワークを作り上げることも可能です。例えば最初に選択肢に上がるであろうthunkですら、導入するとTypeScriptで型をつける際のややこしさが上がります。

特に、sagaとobservableについては本当にそれが必要かどうか胸に手を当てて、できれば最寄りの教会によってセーブしてから決断してください。

アンチパターンと大袈裟に書きましたが、基本的にはこの程度です。
ドキュメントを読めばわかりますがRedux自体は寛容なアーキテクチャ*2で、それぞれのユースケースに応じて様々な書き方をすることが推奨されています。

例えば「アプリケーションの状態*3」を主眼においてドメインという単位でStateを管理することを推奨していますが、UIの状態をReduxのStoreにおくことは別に禁止していません。

Reduxにある問題点(problemとissue)

当然、Reduxは完璧なフレームワークではありません。むしろ問題だらけです。
まず問題点を種類別に分けて整理します。

  1. 不便さ

    • ボイラープレートが多い
    • 他にも色々なライブラリを入れないといけない
    • フレームワークとしてのライフサイクルが存在しない
  2. 致命的なもの

    • immutabilityや副作用の禁止などのコア・コンセプトを機械的に検証する仕組みがない
    • 副作用(非同期)が取り扱われていない(解決方法は提示されているが、フレームワークのコンセプトに副作用をどう扱うかが存在しない)

こんなところでしょうか。
このうち、ボイラープレート云々については本質から程遠いものなので捨ておきます。Shorthand codingが好きならmobxとかそれ系のほうが幸せになるとおもいます。

また immutabilityや副作用の禁止などのコア・コンセプトを機械的に検証する仕組みがない という部分に関しても、使っている言語そのものに関わる問題でReduxについて言及する、という本稿のスコープから外れるのでここでは外します。どうしても我慢ならない人はElmやPureScriptを使いましょう。

そのほかの

  • フレームワークとしてのライフサイクル管理方法が存在しない
  • 副作用(非同期)が取り扱われていない(解決方法は提示されているが、フレームワークのコンセプトに副作用をどう扱うかが存在しない。またその解決方法もthunkは乱暴すぎるし、sagaやobservableはtoo much感が否めない)

ここ部分は普段書いてて割と困る部分です(よね?)。Redux-toolkitがリリースされましたが、あくまでReduxを補強するものでこの辺はノータッチです。
こうなっている理由ですが、前者はReduxがviewと疎結合なライブラリであること(React専用じゃないんですよ)で、後者はライブラリとして取り入れてシンプルさを損なうのが嫌なんじゃないかと推察しています。

じゃあどうやって解決したらいいか。
その辺は文章が長くなりすぎてるので次のエントリにまとめます。今回は観念的・抽象的な内容でしたが、次は具体的なことを語れるとよいですね(願望)。
たぶん、Elmと比較対象して語ります。

以上。

*1:意味がわかりません

*2:それ故に歯切れが悪くてイライラすることもある

*3:Domain dataと文書中で呼ばれている