Unidirectional Data Flow と Flux とかと Android
Android 界隈で Flux とか Redux とか The Elm Architecture (TEA) とかわーって飛びつく前に、これらが生まれた背景とか解決したかった課題とか Web の事情と Android の事情の違いとかをきちんと把握しないと無邪気に Android に Flux/Redux/TEA を取り入れてもあまり幸せな結果にならないのでは、それによってこれらのアーキテクチャパターンが効果を発揮するような場面があるにも拘らず過小な評価を受けてしまうことによって敬遠されてしまい、それはそれで掴めたはずの幸せを逃してしまうのではみたいなことをふわふわと考え始めたのでこれらに関わるメモをここに放り込んで何かを見出せたらいいですねとなっている 適当に思いついた大雑把なトピックを見出しにして適当に何か思いついたり書き表わせるようになったら書いていく感じ
概念図を素朴に実装することについて
よく使われる図 (View -> ActionCreator -(Action)-> Dispatcher -> Store -> View -> ... ) に出てくる各コンポーネントをそのままクラスに割り当ててる実装例について
端的にいうと Android アプリ設計パターン入門で紹介されてるようなやつ
コンポーネントの存在をクラスとして明示することで関係性がわかりやすくなってるので、どこが何でどういう役割を持たせるのか把握しやすいのだけど、ただちょっと問題点というか懸念点というかがいくつかあって
View から直接 ActionCreator クラスを介してデータを流すんだけど、状態は Store にあるので Action に状態を巻き込めない or 状態を持ってくるために Store にアクセスしてしまってそれはアリなのか? みたいになってしまう
ちょっと潔癖な考え方かもしれない
役者が多いのでちょっと圧倒されてしまうかもしれない
Google のガイドラインに寄せた設計を考える
TODO: Google の設計ガイドラインをきちんと読む
きちんとは読んでない上での推測と想像だと...
クラスとその依存関係的な部分は基本的にガイドラインのMVVMのときとそこまで変えなくて良いと思う
ViewModel にイベントに対して実行するメソッドを生やす
ViewModel が ActionCreator に依存していて、ActionCreator が UseCase とか Repository とかとやりとりして (する?) Action を生成して、Action を Store に dispatch する
Store は配布された Action を実行して state を更新する
この更新は (action, state) => state として実行されるので新しい状態 == 新しいインスタンスとなり、したがって state を LiveData に乗せておけば状態の更新を observe するための機構は簡単につくれる
ViewModel が Store なのではなくて、ViewModel が Store に依存している形で良さそう
Store は state を LiveData として公開させて、 ViewModel はそれを繋いでUIに公開すればいい
逆に LiveData は隠蔽しておいて、 observe(LifecycleOwner, Consumer) みたいな関数を ViewModel, Store に生やして方向を逆にするのもあり
こっちにすると Observable の実装を自由にできる感ある
Store == ViewModel 説
なさそう
MVVM/MVP 的なクラスの関係性と unidirectional data flow は対立関係にない
MVVM と MVP は対立する
Unidirectional data flow は Flux の中心的なコンセプトだけど Flux そのものではない
むしろ unidirectional data flow というコンセプトの上に Flux とか TEA とかがある
データの流れさえ一方通行にできればそれぞれのコンポーネントを用意する必要はないけど、型 (パターン) としてそういう役者を用意しておくことでコンセプトの共有をしやすくする的な、これはパターン化の発想でよくある話
Redux (or TEA) から得られる学び
(action, state) => state
状態の変更をテストできるような処理単位 (= 1つの関数) にすること
TODO: TEAちゃんと調べる
Android では Flux のありがたみを完全に享受できない?
View を atomic に変更できないところの話
React 的な diff-patch で View を更新する機構がないと結局 Store -> View のところは Store が持ってる状態の値をそれぞれ observable として露出させて View の各部がそれを observe するか、状態を表すオブジェクトをそのまま observe して View 側でそのプロパティを View の各部にパチパチ当てていくのをやっていくかみたいな、それはうれしいのか?
後者は react のコンポーネント定義とちょっと近い発想になるかも、かも? ほんとか? まあ obervable いっぱい生やすよりはしんどくなさそうだし、状態の更新によって View の何が変わるのか一箇所にまとまっててよさそうかもしれない
View が RecyclerView + DiffUtil (e.g. ListAdapter, Groupie, Epoxy) で構成されていれば state を1つのオブジェクトとして表現しても、adapter の update 関数まで state をそのまま運んでそこでバラバラと配るように実装すれば state の更新に対して adapter がいい感じに差分更新されるのでかなり近いことができるという印象 モデルクラスやアイテムクラスの等値設計をうまくやる必要があるが、だいたい Kotlin の data class でなんとかなりそう Flux, Redux あたりが登場した背景
Web の SPA の話
Flux, Redux あたりが Android でも嬉しくなるには
Navigation で Single Activity な設計にして、アプリ全体で共有する状態を Store として実装すれば SPA っぽくなってそれっぽくなるのではないか
これは Store というかアプリケーションの状態管理の設計の話で、プレゼンテーション層の構成とはあまり関係ないかも
Web front の領域で話題になってることをなんでもそのまま取り込んでいく必要はない (とおもう)
web document, GUI application とかがどうのって話
だれかが何かブログにしてた気がするので調べる
Android の方が web ブラウザよりリッチなGUIアプリケーションプラットフォーム (だった?)
できること・できないこととか背景的な部分とか抱えている課題とかが違う
それなのに同じアプローチが同じように適用できて同じような利益を得られるのかというと違うんじゃないかな
コンセプト (unidirectional data flow) とアプローチ (flux とか) を分けて考えた方がいい?
👀