# Fluxアーキテクチャ覚え書き ## 参考資料 * [Flux Application Architecture | React](http://facebook.github.io/react/docs/flux-overview.html) * [javascript - In Flux architecture, how do you manage Store lifecycle? - Stack Overflow](http://stackoverflow.com/questions/23591325/in-flux-architecture-how-do-you-manage-store-lifecycle) * [Flux Chat Example](https://github.com/facebook/flux/tree/master/examples/flux-chat) ## アーキテクチャ本質 1. ドメインを分割する 2. ドメイン間のやり取りをメッセージパッシングのような疎結合な機構を用いて以下のように行う * ユーザーの入力がビューに対して発生したことをロジック側に伝える * ロジック処理の結果にデータが変更したことをビューに伝える 3. 各ドメイン間のメッセージの送信方向は、組み合わせによって常に一つに決定される ``` Views ---> (actions) ----> Dispatcher ---> (registered callback) ---> Stores -------+ Ʌ | | V +-- (Controller-Views "change" event handlers) ---- (Stores emit "change" events) --+ ``` ## 設計によって得られるメリット * メッセージパッシングの採用により、同時にビューが何個存在しようとも「データが更新された」というメッセージが発行されれば、そのメッセージを購読しているビューが勝手に更新される * 煩わしい管理をする必要が無い * ドメインの組み合わせに応じて、メッセージの流れる方向を制限することで、データフローが常に一つになる * 処理の予測が可能になる * メッセージパッシングによって引き起こされる、ドメイン間の依存性地獄の回避 * メッセージパッシングを使用しているので、ドメイン間の連携が強制的に非同期になる * モデルがいくつのスレッドに分割されていようと、どれだけ時間がかかろうと、設計として全く問題なくなる * StoreもDispatcherもシングルトンなサービスとして存在しているので(後述)、インスタンスの管理などの問題が軽減される ## 各ドメイン * 設計上、こうした方が良い、という点から、オブジェクトの生成が規定されることになる ### Dispatcher * Storeに向けてメッセージを発行する場合は必ずココを介する * シングルトンになる * facebook/Fluxでは、`waitFor()`という機能を提供することにより、Store間の処理順序の依存性を解決している * これが無い場合、Store間の依存性解決用の細かいメッセージを大量に定義する必要が出てくる * 無くても解決できるけど有った方が便利だわな ### Store * データ処理の領域を取り扱う。 * 内部的は完全に隠蔽されている * 独自にインスタンスを管理していようがシングルトンだろうが、ビューの状態も含めようが、それはロジックの問題である * 状態を持つのであれば、状態の生成と破棄のためのメッセージを追加すれば良い * 表向きにはシングルトンなオブジェクトがひとつ公開されており、それ経由でDispatcherからのメッセージ入力を受け取る * ファサードって言っていいんだっけ? ### View (Controller-View) * ユーザーからの入力とデータの出力(表示)を取り扱う * Storeから発生するメッセージを購読する * Storeからの入力に応じて(一意な)データの出力を行う * Facebookの流儀では、ここでReactを用いて描画コストの問題を解消する * 複数インスタンスを作ってよい * 過剰なコンポーネント化は、複雑な状態の保持や、予期せぬActionの呼び出しを発生させるので、開発の複雑性を増加させることに注意 ### Action * Dispatcherのメッセージ発行処理をラップして、より具体的な形(メソッド呼び出し)に変える * 無くても良い ## 通常のMVCではなぜ駄目だったか > We originally set out to deal correctly with derived data: for example, we wanted to show an unread count for message threads while another view showed a list of threads, with the unread ones highlighted. This was difficult to handle with MVC — marking a single thread as read would update the thread model, and then also need to update the unread count model. These dependencies and cascading updates often occur in a large MVC application, leading to a tangled weave of data flow and unpredictable results.