unidirection data flow にしびれる、憧れる理由


# 短いまとめ

「ビューにしか影響を与えないアクションもモデルを通過する」のが、すごい。

# 中ぐらいのまとめ
1. Viewにしか影響を与えないアクションもModelを通過する
1. Controllerの責務から「アクションをModelとViewに振り分ける」がなくなる
1. アクションが（UIのイベントより）抽象的でないと実現できない
1. アクションを設計するのは難しい
1. アクションが設計できれば他のパターンでも上手くいく
1. アクションの設計を強要したのが、すごい

# 背景
UIアーキテクチャーパターンを振り返ります。

## MVC
[The Model-View-Controller (MVC) Its Past and Present](http://heim.ifi.uio.no/~trygver/2003/javazone-jaoo/MVC_pattern.pdf)に準拠します。

### 簡単な説明

- ドメインロジック
  - M:Model データモデル更新ロジック + データモデル
- プレゼンテーションロジック
  - V:View プレゼンテーションの更新
  - C:Controller ユーザの入力処理

### 素晴らしい点
- 分割方針がわかりやすい。誰にでも扱える。

### 解決できない問題

- 役割が明確なモジュール（Model）が小さい
  - 一般にビジネスロジックの量は少ない
  - アプリケーション全体の1/3を期待する？実際は1/10程度
- ビューの状態をControllerが持つ
  - Modelの役割はドメインロジック。ビューの状態はもちません
  - ビューの状態
      - 要素の選択状態
      - ボタンの有効無効制御
- 要素追加後に自動選択すると、ビューの更新をモデルの更新完了後まで待つ必要がある。[Supervising Controller](http://martinfowler.com/eaaDev/SupervisingPresenter.html)を導入できない

ModelとViewの役割は明確ですが、それ以外の役割は全てControllerが持ちます。
Controllerが巨大化します。

## MVP

[MVP: Model-View-Presenter
The Taligent Programming Model for C++ and Java](http://www.wildcrest.com/Potel/Portfolio/mvp.pdf)に準拠します。

### 簡単な説明

MVCのControllerを役割を細分化したパターン。

- ドメインロジック
  - M:Model データモデル
- プレゼンテーションロジック
  - S:Selection 選択状態
  - C:Command データモデル更新ロジック + 選択状態更新ロジック
  - P:Presenter ビューの状態 + ビューの状態更新ロジック + Commandの呼び出し
  - I:Interactor ユーザの入力処理
  - V:View プレゼンテーションの更新

選択状態やビューの状態をもつ専用のオブジェクトを導入します。

### 素晴らしい点

- Selectionを導入し、ビューがModelとSelectionを両方監視することで、Supervising Controllerが導入できる
- CommandをControllerから分離できる

### 解決できない問題

- 複数のビューを更新したい時はPresenterが頑張る
- 編集モードとreadonlyモードの切り替えはPresenterが頑張る
- モデル更新イベントとビュー更新イベントがどちらもPreseterを通る。Presenterはモデル更新とビュー更新の振り分けを行う

Presenterが巨大化します。

## プレゼンテーションモデル

[Presentation Model](http://www.martinfowler.com/eaaDev/PresentationModel.html)に準拠します。

### 簡単な説明

MVCのControllerを画面の要素で分割したパターン。
例えば、リストとリストの表示要素、それぞれにPresentationModelを作ります。

- ドメインロジック
  - M:Model データモデル更新ロジック + データモデル
- プレゼンテーションモデル
  - PM:PresentationModel ビューの状態 + Mを表示しやすいように変換。
  - V:View プレゼンテーションの更新

### 素晴らしい点

- 巨大化するControllerを分割できる
- PresentationModelは画面構成と対応するツリー構造になる。構成がわかりやすい

### 解決できない問題

- PM間のやりとりは親PMが管理
- PMとModelが1対1で対応していない場合、対応付けの解決は親PMが行う
- モデル更新イベントとビュー更新イベントがどちらもPMを通る。PMはモデル更新とビュー更新の振り分けを行う

上位のPresentationModelが巨大化します。


## 残っている課題

高度なアプリケーションを作ると
ユーザーの操作をModelとViewまたは他のPresentationModelに振り分ける処理が
プレゼンテーションロジックに集中します。

既存のMVC、MVP、プレゼンテーションモデルは、これを解決しません。

## 本題

unidirection data flow を見ます。

![flux-diagram](https://raw.githubusercontent.com/facebook/flux/master/docs/img/flux-diagram-white-background.png)


MVCな視点で見ると、以下になります。

- ドメインロジック
	- Store
- プレゼンテーションロジック
	- Action Creators : ユーザーの入力処理
	- React Views : プレゼンテーションの更新

構成要素は（Dispatcherを除くと）MVCとあまり変わりません。

### MVCとの違い

「ビューにしか影響を与えないアクションもモデルを通過する」

ビューにしか影響を与えないアクション例：

- 選択
	- 複数要素を選択して編集する際の、選択状態
- 非表示切り替え
	- TODOリストの完了項目を非表示にする
	- リストの明細を表示する
- Read Onlyモード切り替え

これらのアクションが一度はStoreを通る（けど何もしない）のがすごい。

### 「ビューにしか影響を与えないアクションもモデルを通過する」のすごさ

MVCが生まれてから四半世紀、いろいろ分割してみたけど


    ユーザーの操作をModelとView（他のPresentationModel）に振り分ける処理が
    プレゼンテーションロジックに集中する。

を回避する方法は発見されませんでした。

「ビューにしか影響を与えないアクションもモデルを通過する」とするだけで
モデル(Store)もビューも「自分の興味があるアクションにだけ、反応すれば良く」なりました:tada: 

### 問題点

- アクションがflowの途中で破壊された場合（バグ）、発生箇所を特定するのが面倒
- なんでもflowを一周するのが面倒
	- 「入力欄に文字が入っているときだけ、ボタンを押せる」インタラクションを作るのが面倒
- アクションの設計が難しい
	- ユーザー操作を上手く抽象化できれば、プレゼンテーションモデルだって、PM間の通信も上手く整理できる

### まとめ

「ユーザー操作を抽象化しない」逃げ道を塞ぎました

- :+1: 機能が増えても破綻しない設計
- :-1: 設計・実装コストが高い

unidirection data flowアーキテクチャーの最大の特徴はここだとと思います。
（少し知見がたまると、違う特徴が見えてくる可能性はあります。）

### fluxの補足
#### Dispatcherが必要な理由

- アクションの投げ先がシングルトンだと、ActionCreatorをViewのパーツごとに分けたときに投げ先を取得しやすい
- 一つのActionが複数のデータモデル・Viewを変更する時、Actionを分割する
	- 例えばカスケード削除。
- 分割したActionの順序を制御する
	- 例えばカスケード削除。データモデルは大抵どの順番で消しても大丈夫。Viewは削除順に制約があることがある

#### Constantsが必要な理由

- アクションの名前をAction Creator、Dispatcher、Storeで参照する。定数定義があると補完しやすい。