console.lealog();

@leader22のWeb系に関する勉強めもブログですのだ

これからMobXをはじめる人へ

さて、 #MobX に出会ってはや半年が経ちました。
相変わらずTwitterとか見てる限り、俺くらいしか使ってないのでは感を感じてたりはするんですけど・・。

2016年の海外では割と話題になってた(と個人的には)思ってて、2017年になれば国内でもぼちぼち取り上げられ始めるのでは・・?ということで。
そしてそのときになって「Redux vs MobX」とかいうしょーもない切り口ばっかり出てこないように、今のうちに釘を。

興味を持ってもらえた場合は、0からはじめるMobXシリーズもあるのであわせてどうぞ。

MobX カテゴリーの記事一覧 - console.lealog();

MobXについて

Introduction | MobX


詳しいことは過去に記事もいろいろ書いてるし、ドキュメントも充実してるので各位で調べてもらうとして。
ざーっくりいうと、

  • `Object.observe`のちゃんとしたやつ
  • Vue.jsのvm部分のつよいやつ

です。

ReactiveなObservableな値を用意して、それを変更したら関連するものも全部更新されて・・と、そういういわゆるState管理の層だけをやるライブラリです。
このObservableな値が変更されたタイミングで、しかる処理を自動的に呼んだりできます。(`autorun()`ってやつに自分で定義する)

コード見て判断するわ!という場合は、GitHub - mweststrate/mobx-todomvc: Trimmed down TodoMVC used for benchmarking とかがよいかな?
Perf目的のコードであんまり綺麗じゃないけど・・

先取りFAQ

Reactとセットなの?

違います。

`mobx-react`というバインディングがあって、Observableな値を更新すると勝手にコンポーネントの`render()`が走るみたいにできます。
しかも`shouldComponentUpdate()`のチューニングまでやってくれます。
あとは、いわゆる`Provider`も付いてきます。

さっきも書いたように`autorun()`で、値の更新時に走る処理をかけばいいので、jQueryでDOMを頑張って作るやつでも、Canvasに描くでもなんでもござれです。

噂のInfernoにもバインディングありますよ!w

Fluxライブラリなの?

違います。

なので今後「Redux vs MobX」ってのを見つけたら、「React vs Angular2」みたいな微妙な気分で見てください。

Reduxは死んだの?これからはMobXなの?

いやだから関係ないです!

Immutableなの?

これも違います。
MobXがMutableだからこその、この楽さとか便利さとかです。

作者さんはImmer Mutableと表したりもしてたけど。

The Quest For Immer Mutable State Management

Reduxとの比較もされてたりするのでご一読あれー。

Vue.jsでよくない?

正直、同じようなことはできると思います。
ただ値をReactiveに扱う点において、Vue.jsのvmにはないけどMobXにはある機能とかもあるので、そこは違いかなーと。
そもそも既存のReactコンポーネントがあるときに、Vueに移行しよう!とはならんと思うし。

Decoratorsはまだ時期尚早なのでは?

一理あります。
そして、Decorators使う方が圧倒的に書き味は良いです。

が、全ての機能がES5な環境でも使えるようになってるので問題はないです。

なぜMobXを使うのか

主に、

  • とりあえずReact使ってます・使いたい
  • アプリ作るならまぁFluxかなー

みたいな認識を持ってるそこの人!なんでですか?

  • Facebookが「MVCはスケールしない!」とかいってfacebook/fluxを出してきたから
  • なんかみんなFlux(実装を指して)だ!とか言ってるから

たぶんですけど、それくらいしか考えてない人も多いのではないかなーと。

そして、そんなFluxでやってみた結果、

  • ボイラープレート的なコードが冗長・・
  • どこで非同期処理書いたらいいの・・

みたいになってるんじゃないかなーと。
そしてそれがReduxつらい・・にもつながっていってるんじゃないかなーとも。

ReactのおかげでViewはStateを食わせるただの関数になった。
であればその状態を表すStateをどう管理して、どう更新していけばいいのかってとこに意識を注げばいいはず。

なのに、どのようにFluxするかみたいな話ばっかり出てくる。
そもそもReactでなんか作るのにFlux実装はマストではないはずで、別にMVCも死んでないし規模や要件に応じた設計を用いればいいだけでは・・?

まぁ何を指してFluxと呼ぶかみたいな話もあるけど・・

そこで、MobXという選択肢

なので最初に言っておくと、ただの選択肢であって正解ではないです。
ただ選択するからには何か理由があって。

Less boilerplate, more application code.

というわけでこれがMobXを選択する理由の第一です。
Flux実装によくあるActionオブジェクトはいらなくて、Stateの変更がそのままViewの更新につながります。楽ちん。

  • Storeを用意して
  • Viewに渡す
  • Storeの更新ハンドラだけよしなにViewから切り離せば

それなりの規模までは、ほんと楽に作れます。

ただその反面、こういう心構えも必要です。

MobX, it's been mentioned elsewhere but I can't help but sing its praises. Writing in MobX means that using controllers/ dispatchers/ actions/ supervisors or another form of managing dataflow returns to being an architectural concern you can pattern to your application's needs, rather than being something that's required by default for anything more than a Todo app.

これはどこぞのHacker Newsにあった言葉です。
いわゆるOpinionatedなものではないので、使い方はあなた次第ということ。

なのできちんと足回りを精査して、ちゃんとルールを作らないとすぐ破綻するよということ。
複数人でわちゃわちゃするプロジェクトならなおさら。

公式・コミュニティとしてもこうやってアプリ作ればいいよ!って言ってるものはまだなくて、みんな試行錯誤してる感じですね。

MobXの何がいいか

Anything that can be derived from the application state, should be derived. Automatically.

標語みたいなやつなんですけど。
本当に意識して扱うべき値の操作に集中すればよくて、それに付随する値・副作用は宣言的に書いておけば勝手にやってくれます。

class OrderLine {
    @observable price = 0;
    @observable amount = 1;

    constructor(price) {
        this.price = price;
    }

    // price | amount どちらか更新されると追従して更新される
    @computed get total() {
        return this.price * this.amount;
    }

    addAmount() {
        this.amount++;
    }
}

いわゆるFlux的なコードスタイルだと、ただのObjectなせいでこういう抽象化がやりにくいというか、全て関数にしないといけないというか。
それが良いところなのかもしれんけど、冗長というのもまた事実で・・。

住所を絞り込むプルダウンのフォームみたいなのをどう実装するかってのを想像してみてください。
あんなの、てっぺんのデータが変われば「自動的に」下層のデータも導き出されればいいと思いませんか?
それを手続き的に書くのではなく、コードスタイルとしても収まりよくできるのがMobXです。

個人の感想

個人としては、

  • Flux(facebook/fluxやReduxの流れを汲むコードスタイル)に対する疑念を抱き始める
    • ボイラープレート的なコードおおすぎ
    • Actionオブジェクトの存在意義がわからん
    • 別にタイムトラベルとかしない(そういう要件の仕事をすることがない
    • I/Oしっかりしてれば別にImmutableじゃなくてよくない・・?
  • EventEmitterだけあればいいと思うようになる
    • dispatcherだけcontextで埋めればいいのでは・・?
  • Stateオブジェクトと、Viewをつなぐものがあれば、それだけでよかった <- イマココ

そしてここまでくると、`setState()`を直接使ってもそれなりになんとか立ち回ることのできる術が身についてる。
でも`shouldComponentUpdate()`のチューニングはしたくないし、`setState()`も直で触るのは地味に面倒くさい。
もちろんEventEmitterだけあれば必要十分なんやけど、あと少しなんか助けてほしい。

そこをいい感じに拾ってくれたのがMobXって感じでした。

なので、

  • Post Reduxといえるし、いえない
  • Fluxが向く・向かないの要件を見極めた上での選択肢にはなる
  • 設計論がもうちょい成熟すれば流行るかも

まぁ個人的には、割と多くの人にとっての「顧客が本当に求めていたもの」さんのポジションも狙えるのではないかなーと思ってます。

最初は「Real World MobX」とかって、自分がどういう風に使ってるかを紹介するていで記事を書き始めたはずなのに、気付いたらこうなってた・・(˘ω˘ )