これから何回かに分けて、Redux に代表される JS の状態管理ライブラリをいくつか見ていきます。

早速本題に入りたいところですが、その前になぜいくつもライブラリを知っていた方がいいのか、当たり前のように思うことをあえて考えてみる必要があります。
なぜなら、状態管理ライブラリがたくさんあるために、次のような疑問が出てくるからです。

どれでも好きなものを使えば開発がうまくいくのか? 今までうまくいっていたライブラリを使い続ければ今後もうまくいくのか? 選ぶとしても、何を基準に選べば良いのか?
今回は少し立ち止ってこういった疑問について考えてみます。

ではそもそも状態管理とは、一体何のために、何をすることなのでしょうか?

状態管理が目指すもの – 読みやすさの基本定理

状態管理をする目的は様々ですが、最も大切なことはリーダブルコード(読まれて無い方は是非一読を!)の中で「読みやすさの基本定理」として掲げられた以下に集約されると僕は思います。

コードは他の人が最短時間で理解できるように書かなければいけない。

つまり、状態に関係する変数やロジックのソースコードを、最短時間で理解できるものとすること。これが状態管理の目的だと僕は思います。
ここでいう「最短時間で理解できる」とは、最短時間でコードに変更を加えたりバグを見つけたりできるという意味が込められています。

この目的を見失わないことが、状態管理において大切なことだと僕は思います。そうしないと、独りよがりな管理になることもあるからです。そのような管理はどんなに巧妙なことをしていても、理解できないならばアプリケーションの成長が止まってしまうかもしれません。

そもそも状態管理って何をすること?

では、状態管理 = 最短時間で理解できる状態周りのコードを目指す ためには何から始めればいいのでしょうか?

よく知られている Redux や他の Flux 的なライブラリを導入することでしょうか? GitHub のスター数が多くて開発も活発で日本語のドキュメントも充実したライブラリを導入することでしょうか?

僕が思うに上記は全て間違いです。まずはライブラリのことは全て忘れて、自分が開発するものをよく知ることです。

インタラクティブのない WEB サイトなのか、WEB アプリケーションなのか。また、そのアプリケーションは複雑なのか、また、複雑になっていくのかといったことをまず自問することです。

インタラクティブのない WEB サイトであれば、状態は複雑ではないかもしれません。そうであれば、特別に状態管理を考慮することは不要ですし、むしろ積極的に何かしない方が良い場合すらあります。

開発者はまずこの重要な判断を下さなければなりません。なぜなら、状態管理ライブラリだけでなく React や Vue すら使い方によっては「読みやすさの基本定理」を目指す際の足かせとなるからです。

ライブラリを一つ導入したり、コードに変数を一つ足すことは、開発者が認識するべきことや従うべき規則を増やします。たったこれだけのことでも、ソースコードの読みにくさは少しずつ(でも確実に)増していくものです。

つまり、ライブラリを導入すること自体が、コードを読みにくくすることです。

適切に選択されたライブラリは(また足された変数は)、自身が導入されることで発生する読みにくさを上まる利益をもたらしてくれます。それ以外は無用に支払うコストです。基本的には避けるべきものでしょう。

Redux の公式ページにおいても、ライブラリの導入がただのコストになり得るということが以下のように述べられています。

Redux は共有状態管理を扱うのに役立ちますが、他のツールと同様にトレードオフがあります。Redux はコードを書くための最短・最速の方法として設計されているわけではありません。

https://redux.js.org/faq/general#when-should-i-use-redux

また、上記の引用が示唆するのは、状態管理を真剣に考えるべき開発と、そうでもない開発があるということだと思います。

ここで状態管理は何をすることなのかという疑問に対して、こう答えることができるでしょう。

より複雑でない開発においては、より積極的に特別な状態管理をしない

管理する対象が存在しないのに管理しようとすることは、無駄な管理だということです。そのような管理は無い方が「読みやすさの基本定理」につながります。

より複雑な開発における状態管理

大規模な SPA を開発していると、ソースコードが複雑に変化することは避けられず、その複雑さに追従、もしくは先周りして堅牢に状態管理することも避けられなくなります。

ところで状態管理によって全ての状態の所在や流れを認識できれば理想的ですが、それは不可能です(僕が知る限りでは!)。
であれば、末端の処理からでもデータの取得や更新の経路を辿れることが大切でしょう。

そのために様々な状態管理ライブラリは、あるデータを参照、更新する際の規則を守ることを開発者に要求します。より厳しい規則に従うことは、状態の変化と取得の因果関係をより明確に定義することにつながります。そして、この因果関係の糸がより明確で堅牢であれば、状態が存在する場所や変化の経路をより確実に辿ることができるでしょう。

つまり、ここでは状態管理は何をすることなのかという疑問に対してこういうこともできると思います。

より複雑な開発においては、状態の変化と取得の因果関係をより明確に定義すること

さて、これでより複雑ではない開発と、より複雑な開発の 2 つにおいての状態管理を述べ、ライブラリ = 状態の変化と取得の因果関係の規則 の役割も簡単に述べてきました。
最後に、ライブラリを選択できるようになるために、もう一つ考えておくべきことがあります。

そもそも何故たくさんの 状態管理のライブラリ = 状態の変化と取得の因果関係の規則 があるのでしょうか?

たくさんの状態管理のライブラリが生まれる背景

僕の経験で想像できることは、アプリケーションの複雑さは 10 のアプリがあれば 10 通り異なるため、様々な複雑さの度合い応じた ライブラリ = 規則 が生み出されてきたのではないかということです。

これは開発をかなり破壊的に簡略化した例えですが、「レベル 5 の複雑さ」に対して「レベル 10 の規則」は足かせです。かといって、「レベル 1 の規則」では複雑さに対応できません。「レベル 5 の規則」がこの場合最も「読みやすさの基本定理」に繋がるということです。

そして、規則 = ライブラリ が適切に選択された時に最も「読みやすさの基本定理」に繋がるからこそ、選択することが重要だと思います。そして、選択するには選択肢を持つ必要があります。

そこで、その選択肢を増やすために、いくつかの状態管理ライブラリをこれから何回かに分けて見ていくことにします。

適切なライブラリの探索 – 各ライブラリが持つトレードオフ

比較的新しい状態管理ライブラリ XState の作者 David Khourshid(@DavidKPiano) は、状態管理ライブラリを探す時に役立ちそうな地図を提供してくれました

また、続けてツイートされた中でこうも言っています。

Direct manipulation is “easier” than indirect manipulation, but is less safe.

Single is “more convenient” than multi, but is more coupled.

These trade-offs might be acceptable for your use-cases, but they’re worth knowing.

https://twitter.com/DavidKPiano/status/1353714369239130119

つまり、状態管理ライブラリを大雑把ですが 2 つの視点でカテゴライズしています。

  • 1 つのストア(global, atomic store) vs 複数のストア(local, distributed)
  • 直接 State を変更 vs イベントで間接的に State を変更

そして、カテゴリにはそれぞれ以下のトレードオフがあり、許容できる場合でも知っておくことは価値があると言います。

  • 1つのストアはより便利。複数のストアは便利さを失うかわりにデータを疎結合にできる。
  • 直接更新は簡単。間接的な更新は簡単さを失うかわりにより安全。

このトレードオフは、「読みやすさの基本定理」を目指す際には重要に感じます。
すでに簡略化した例えで述べたように、あえて安全よりも簡単を選択すること、もしくは簡単よりも安全を選択することの両方が、アプリの複雑さによっては読みやすさに繋がるからです。

そこで次回から、以下にカテゴライズされるライブラリを実際に使ってみることで、そのトレードオフについて考えていきたいと思います。

  • Multi × Direct
  • Multi × Indirect
  • Single × Direct
  • Single × Indirect

次回は手始めに、最も有名であり Single × Indirect に属するライブラリの Redux を見ていきます。