LoginSignup
29

More than 5 years have passed since last update.

ReduxとMobXの選定観点

Last updated at Posted at 2017-12-29

この記事を書いた当時、MobXは余計な複雑さが隠蔽され、とても良く目に映りました。何よりReduxにはOOPが可能なモデルが無い、という当時のReduxに対する不満を解決してくれました。(今はReduxにもモデルを持ち込む手法を選んでいるので不満はありませんが)

直近、同僚に「Redux と MobX の選択はどうすれば?」と相談されたので、その日の返答内容をまとめてみました。

TODOサンプルだけでは測れない現実の課題

ライブラリのキャッチアップに、TODOや「+1」するカウンターで検証することはよくあると思います。ただし、これだけでは長期運用するプロダクトの検証には不十分です。 MobXは便利で簡単に始めることが出来るため、Storeを無作為に参照しあってエンバグしやすいコードが出来てしまいがちです。

Storeが数えるほどしかなく、機能も単純であれば原因を突き止めるのは容易です。しかしながら、現実は技術要件とビジネス要件が入り組みます。Store 同士のロジックが密結合してしまい、そこに依存するアプリケーションを組んでしまうと、技術負債の出来上がりです。

Storeが密結合してきた場合

Storeが密結合してきたら、Storeの結合点を外に逃すのが得策かと思います。複数の reaction を用意して、Storeとは切り離されたレイヤーで Observable な値に対してマッピングを行います。こうすることで、各々の Store は疎結合になり、ユニットテストも容易になります。

entry_point.js
const storeA = new StoreA()
const storeB = new StoreB()
const storeC = new StoreC()

reactions({ storeA, storeB, storeC })

reactions.js
export default function ({ storeA, storeB, storeC }) {
  reaction(
    () => storeA.value,
    value => { storeC.value = value * storeB.value }
  )
  reaction(
    () => storeB.value,
    value => { storeC.value = value * storeA.value }
  )
}

難点は、Store が増えるほどトランザクションが追い辛くなることです。リファクタ・スケールにおいては、簡単な部類ではないと思います。普段から出来ることといえば、他の Store が別の Store の状態を直接参照しないようにすることぐらいです。

MobXにする境界

1.異なるプラットフォームでドメインモデルを共有したい

React + MobX と紹介されることが多々ありますが、両者は疎結合で MobX をドメインモデルとすることが可能です。別の view で再利用可能で、データバインディングフレームワークと比べ、ドメインモデルが切り離されています。

そのため react-dom・ReactNative でドメインモデルを共有することもなども容易です。もしこの点に魅力がなければ、Reactに固執する必要もないかもしれません。

2.Storeの密結合が起こりえない

json を取ってきて SPA で記事を表示するだけ、というユースケースの場合は、Store の結合は問題にならないかと思います。非SPAの場合も同様で、MobX が最適解だと思います。

3.とにかく早く ReactComponent を書き上げたい

Redux もそうですが、React とは疎結合なため、状態管理は変更可能です。ReactComponent はそのままで、状態管理だけ差し替えることが出来ます。「Store結合が複雑な大型改修が必要になったら、Reduxに乗り換える」ぐらいの心意気があれば、最初は MobX の方がシンプルに目指しているものが作れるかと思います。

【こんな案件だったら自分はMobXを選ぶ】

  • エンドポイントによっては部分的にSPA
  • メディア媒体・シンプルな投稿機能サイト
  • 期間限定のプロモーションサイト
  • 個人のブログ

Reduxにする境界

1.異なるプラットフォームでドメインモデルを共有したい

こちらもまた、Reactとは疎結合なのでドメインを切り離すことが出来ます。普通の使い方をすると、Reduxはデータソースの保持のみでドメインモデル不在ですが、immutable.js を導入すればOOPが可能なドメインモデルを持ち込めます。Reducer の switch 文 やボイラープレートが辛いと感じる方は、こちらを参考にしてみてください。私自身の直近業務では、よく見る3種のボイラープレートは一切 git commit していません。(それ相当のものはもちろんcommitしています)

2.モデル同士の複雑な密結合が予想される

redux-saga は複雑だと敬遠されがちですが、非同期処理だけのものではありません。上記の様な MobXStore 密結合問題と同様に、redux-saga上でモデル間のマッピングが行えます。

一番の特徴は、そのトランザクションの組み替えが容易なこと。async/await と使い勝手が同じなので、学習コストが無駄になることが無いです。

ActionType名称を変更しても、Objectでマッピングされているため、悩み事は最小限で済みます。(redux-saga 以外に redux-observable でも可能です)

3.書き捨てではなく、長期的に保守していきたい

先に述べたとおり、リファクタに強いです。後々の保守工数を鑑みても、長期運用やスケーラビリティはこちらに分があります。

【こんな案件だったら自分はReduxを選ぶ】

  • 全エンドポイント SPA
  • 機能豊富な WebBrowser アプリ
  • 機能各種が密結合する ReactNative アプリ
  • 複数人でのフロントエンドコード長期保守

最後に

  • 作るもの・締め切りなどによって最適解は変わります。
  • ボイラープレートが辛い、という消去法で MobX にするのはやめましょう。
  • 少し工夫でボイラープレートは気にならなくなります。
  • Store や Model が純粋であることは尊いです。テストが書きづらく感じたら、赤信号です。
  • 両者のpros/cons を理解して最適解を選びましょう。
  • もしかしたら、React以外の選択もあるかもしれません。

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
29