FluxアーキテクチャのTodoMVCとImmutableJSを試してみた

Fluxアーキテクチャにふれてみようということで、TodoMVCを試してみた。

Fluxアーキテクチャと特徴

Fluxのページにあるので最近よくみる図だけど、Fluxのアーキテクチャは以下のとおり

4つに大きく分かれていて、それぞれの特徴は

  1. ActionCreators

    • viewからのアクションを受けてDispatcherにPublish
    • 外部のAPIとの連携を受け持ちを行う
  2. Dispatcher

    • Viewからのアクションを受けてStoreに対してPublish
    • 処理の実行順序制御を行い、依存性を解決する役割もある
  3. Store

    • ビジネスロジックを受け持つ。
    • Dispatcherの通知をSubscribeして、アクションを実行する
    • データに変更があると、メッセージをPublishする
    • シングルトンオブジェクト
  4. Rect(View)

    • UIコンポーネント
    • ユーザーからの入力(イベント)を受け取り、Actionを呼び出す
    • Storeの発行する通知をSubscribeして、画面の再描画を行う
    • 描画は変更のある箇所のみ(VirtualDOM)

整理すると、

  • StoreはActionのイベントを監視
  • ComponentはStoreのイベントを監視
  • Componentはイベントを通じてActionのイベントをPublish

というサイクルの一連の処理の流れが単一方向で行われるオブザーバーパターン。
単一方向ということで複雑さが軽減でき、おおよその処理系統を推測できる。
アプリケーションが大きい場合は、運用にとってメリットとなりそう。

TodoMVC

TodoMVCのディレクトリ構成は以下の感じでした。

それぞれ役割ごとにディレクトリができている。
constantsはActionがPublishするメッセージが定義されているだけ。

イベントをPublish・Subscribeの箇所であるComponentとStore間はEventEmitterで、
ActionとStore間はFlux::Dispatcherを使っている。

EventEmitterとFlux::Dispatcherについては簡単には以下のようなもの。

写経したTodoMVCのコードをもとに見ていくと

チェックボックスをチェックすることでonChangeイベントでTodoActions.toggleCompleteが実行される。
Component上での変更はActionの該当するアクションにデータを渡す。

ActionはDispatcherにActionTypeをPublishする。

StoreではSubscribeしたActionTypeごとに適切な処理を行い、ChangeEventをPublishする。

Cpmponentはイベントを受け取りviewの再描画を行う。

ImmutableJSを使った

TodoMVCのStoreでデータはJavaScriptの単純なObjectだったが、今回はImmutableJSを使ってみた。

ImmutableJSを使用することにより、深い構造のObjectデータ操作が容易にできるほか、
パフォーマンス向上の為のPureRenderMixinなどを使っている場合に起こる予期せぬ状態を避けることができるようだ。

ReactのコンポーネントライフサイクルではStoreからのイベントを受けて、差分があるコンポーネントを再描画する。
その際に呼ばれるshouldComponentUpdateの値がtrueとならない限りそれ以降が実行されない為、再描画されない(renderが実行されない)。

簡単な例としてカウントアップをする場合、

shouldComponentUpdateがfalseを返すようにするとカウントアップされない。

PureRenderMixinはshouldcomponentupdateを利用して、変更前後のオブジェクトの値と参照をチェックし、変更がない場合はfalseを返す。
これにより変更がないとされ、無駄な再描画されないためパフォーマンスが向上する。

しかし、PureRenderMixinにも説明がにあるように、深い構造を持つObjectだと予期しないことになる。

また、自前でshouldComponentUpdateに差分チェック機能を実装することもできるが、深い構造のオブジェクトのチェックが頻繁に呼び出されるshouldComponentUpdateで行うのはパフォーマンス的にもよろしくない。

ImmutableJSを使うと、以下のように単純な比較でも予期した通りの結果を得られる

よってをPureRenderMixinでの予期せぬ結果を回避できるということのようだ。

ということで、
Fluxのアーキテクチャは単一方向性のオブザーバーパターンなので、これに従って、
BackboneやAngulerなどのフレームワークを組み合わせることである程度の規模でも煩雑さの少ない
アプリケーションができそう。

今回作成したTodoMVC kazu69/todomvc-with-flux-immutable

参考にしたページ

Advanced Performance
The React.js Way: Flux Architecture with Immutable.js
React – PureRenderMixinの検証

Comments