普段思ったことや、雑記。

Menu & Search

Reactの高度な状態管理にRedux+Sagaが定番となっていることについての疑問

2020年6月3日

久しぶりにReactを使用したいと思い、現代的な設計は何か調査し、色々と検討をしていたところふと思ってしまった疑問である。
私が最後にReactで開発をしていたのは、2017年末である。当時も、高度な状態管理の技術スタックの定番は、やはり現在と変わらずRedux + Sagaミドルウェアであった。

当時はSagaの適用箇所がさほどなかったこともあり、あまり気にかけていなかった。しかし、あらためてフラットな状態でこの技術スタックを見てみると、Reduxの「Sagaミドルウェア」に関し、なぜ流行っているのかよく理解できないと思ってしまったため、その疑問点をまとめてみた。

(1) Sagaパターンは、本来異なるプログラム間でトランザクションを整理するもので使うものではないのか?

Sagaパターンについて調査すると、いわゆるマイクロサービス化されて、アプリケーションごと異なる場合で、アプリケーションにトランザクションをもたらす必要がある際に適用するデザインだと思っている。アプリケーションにトランザクションの実装ともなると、実装コストや難易度が非常に高いものとなるであろう。

(2) クライアントサイドのSagaパターンのReact Reduxを除いた、他の実例が見当たらない

調べていて、クライアントサイドに適用されている実例が見つけられなかったため、Reactの界隈が若干特殊な傾向なのでは?という印象を抱いてしまった。

(3) 1つのアプリケーション内にSagaの設計を持ち込んで、ほら!これがSagaパターンだよ!と言われても、本来のSagaパターンの課題解決の想定とはかけ離れていそうであるために、困惑してしまう

端的にいうと、1つのアプリケーション内でSagaパターンを導入するには、多くの場合にファットすぎない?ということ。Sagaパターンの本来の想定されるであろう用途は疑問1の通りで、そもそもReact内の状態管理でいうと、アプリケーションをクライアントとみなすと、クライアントからストレージに接続しているのは唯一つであるわけで、クライアントが1つの場合になぜSagaパターンでなけばダメなのか、という点が理由として希薄に思える。

ReduxのSagaミドルウェアの主張として、存想像するに、UIからフックされるイベント(ReduxでいうAction)をクライアントと見立てており、またReduxのStoreをデータストアとして、ああデータストアに対して、非同期でたくさんイベントが飛んでくることが想定されますね、と雰囲気は分かるのだが…。
仮にそうだとしても、アプリケーション内における、非同期のデータフローの交通整理を行うデザインパターンで良いのでは?と思ってしまう。

(4) Sagaパターンが求めるトランザクションの解決は、クライアントサイドのアプリケーションの層において本当に必要な技術であるのか?

トランザクションにおける問題解決は、データストアに対する変更が競合した場合のロールバック処理が特にウェイトが大きいと思われる。トランザクションのような精緻な整合性の担保が、多くの場合にクライアントサイド内で完結して実装されている必要があるかが疑問であった。

今回でいうと、1つのアプリケーション内部に限った話であり、だとしたら、アプリケーション側で対処するのではなくて、トランザクションはアクセス先のデータストア側の提供する機能でなんとかならないのか?という話でもある気がする。

(5) Sagaという名称が何かと戦っている感があり、カッコ良いのが疑問

Webの辞書によると、Sagaの意味は、「壮大な歴史物語や冒険物語、ファンタジーなど」ということだ。略称か何かで、意図せずこういう命名になったにせよ、これはデザインパターンの名前にしてはカッコ良すぎるため、疑問を覚える他ない。

総評:Reactアプリケーション単体にSagaパターンの導入は腑に落ちなかった。トランザクションをアプリケーションに持ち込むような重厚な実装が必要でない限り、Observerパターンで良さそう

Sagaパターンは、デザインパターンの要件レベルで私には重すぎた…。では、Reduxの高度な状態管理にSagaパターンではない何を使うか?であるが、Observerパターンが良いのではないかと思っている。

1つのアプリケーション内において、状態管理にObserverパターンを適用する、はよくある話なのでReduxの取り回し向上のため、拡張的に適用するにも何ら違和感がない(というか、ReduxがReactと結合して状態を購読するあたり、Redux自体もObserverパターンを踏襲しているので理解もしやすい)。Observerパターンの実装をサポートするライブラリでは、有名なものではReactiveX(通称: Rx)は多くの開発言語で提供されている。一方で、Observerパターンを補助なしで書こうとした場合に、その仕組みが簡素であるので、実装時の難易度がさほど高くはないという点もポイントだ(Observerパターン自体の要件が軽量であるのが良い)。

今回論点となったReduxのSagaミドルウェアはもしかしたら魅力的なのかもしれないが(テストがしやすいなどの理由があるのかもしれないが)、デザインパターンの本質のみを突き詰めた場合に、自分が想定する多くのクライアント実装には要件として大き過ぎて、合わなそうであった。よって、Reactでの高度な状態管理にはObserverパターンのRxを使用することにしようと思う。

2020年9月14日追記:
そもそも、非同期処理をアプリケーションの唯一のデータソースの操作に組み込まないというルールのもとやれば、最近はこういったより複雑な非同期処理のライブラリがある程度までは不要になるのではないのかと思っている(これに気づいて一生懸命どれが良いのか調べていたわけだが、ある時気づいた)。この手の非同期処理をデータフロー中でサポートするライブラリは、データソースの構造が複雑であったりとか、私が認識していないさまざまな事情がある場合にsagaであったりが出てくるという認識である。

参考文献

Sagas
https://microservices.io/patterns/data/saga.html

sagaを使用したマイクロサービスのデータ一貫性https://www.infoq.com/jp/news/2018/03/data-consistency-microservices/

Read Me · Redux-Saga
https://redux-saga.js.org/

出版-購読型モデル – Wikipedia(Observerパターン)
https://ja.wikipedia.org/wiki/%E5%87%BA%E7%89%88-%E8%B3%BC%E8%AA%AD%E5%9E%8B%E3%83%A2%E3%83%87%E3%83%AB

Article Tags
mmiyauchi

プログラムを書きながらTranceを聴くのが良いですね。みなさんも聴いたほうがいいですよ、Trance。EDMよりハードトランスでしょ。

Related article

Redux(react-redux)における適切な配列要素の更新

2021年8月23日…

CloudFlareの『SSL/TLS 暗号化モード(HTTPS通信設定)』を使用したとき、『ERR SSL VERSION OR CIPHER MISMATCH』のエラーでChromeで発生し、接続できない場合の対処

英語の記事は見当たっ…

Dart(Flutter)についての所見

Dart(Flutter)についての所見

第一印象では、クロス…

Discussion about this post

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください

Type your search keyword, and press enter to search