読者です 読者をやめる 読者になる 読者になる

#iosdc 2016 A-4 Reactive State Machine

twitter.com

ここ1, 2年のSwiftの登場とFunctional Reactive Programming (FRP)の普及によって、iOSアプリ開発の現場では劇的なパラダイムシフトが起きています。しかし一方で、副作用を伴うアプリの状態管理に苦労する点が未だ多くあり、バグの温床となっています。このプレゼンでは、状態管理の基礎理論であるオートマトン(ステートマシン)を基に、Reduxなどのフレームワークとの対比も交えながら、FRPでの効率的な設計手法について探ります。

iosdc.jp

speakerdeck.com

Reactive State Machine

f:id:niwatako:20160820130053j:plain

f:id:niwatako:20160820130055j:plain

f:id:niwatako:20160820130111j:plain

f:id:niwatako:20160820130112j:plain

どのライブラリもデータフローを構築します。

f:id:niwatako:20160820130151j:plain

f:id:niwatako:20160820130153j:plain

f:id:niwatako:20160820130158j:plain

状態を保存、管理する。

f:id:niwatako:20160820130237j:plain

EventEmmitterで定期的に監視する。FRPになるとObservableやシグナルになって、同じことが出来ます。

取得は?

f:id:niwatako:20160820130348j:plain

.rawValueでは、単発的にしか取得できない。イベントの機能は備わっていないので監視はKVOを使わないと難しい。それがReactiveになるとKVOの部分が置き換わって監視できるようになる。

f:id:niwatako:20160820130450j:plain

f:id:niwatako:20160820130451j:plain

これらを使ってMVVMパターンにそってデータバインディングを定義していく

f:id:niwatako:20160820130518j:plain

f:id:niwatako:20160820130526j:plain

いや、今日は30分です

f:id:niwatako:20160820130552j:plain

f:id:niwatako:20160820130602j:plain

f:id:niwatako:20160820130608j:plain

Viewの数だけViewModelが。。。

これらが相互に関係しあって複雑なデータフローを構築するとします

f:id:niwatako:20160820130621j:plain

f:id:niwatako:20160820130643j:plain

これをコードレビューしてくれと言われたらどうしますか?

f:id:niwatako:20160820130657j:plain

最終的にLGTMというでしょうか

f:id:niwatako:20160820130710j:plain

f:id:niwatako:20160820130719j:plain

どこかのシステム統合の話予納ですね

FRPでこれらが解決するわけではない。データフローは別の問題だから。

f:id:niwatako:20160820130741j:plain

だれかが間違って汚いものを流すこともある。

f:id:niwatako:20160820130802j:plain

f:id:niwatako:20160820130821j:plain

別の川を作ってつなげてしまう、下水管が繋がってしまうこともある。

f:id:niwatako:20160820130832j:plain

付け外しできる川

f:id:niwatako:20160820130908j:plain

f:id:niwatako:20160820130913j:plain

データフローも状態だった...!

f:id:niwatako:20160820130920j:plain

f:id:niwatako:20160820130930j:plain

f:id:niwatako:20160820130936j:plain

f:id:niwatako:20160820130952j:plain

f:id:niwatako:20160820131004j:plain

ではどこから手を付けたら良いのでしょうか。WEBの世界には既に手がかりがあります。

f:id:niwatako:20160820131035j:plain

f:id:niwatako:20160820131044j:plain

ReactはUIViewやUIViewControllerのようなものだと思えば良い。ただそれらをイミュータブルなものとして捉えます。

状態の変更はバーチャルDOMを使って必要最小限の部分だけ再レンダリングされる。

データフローを作る麺ではReactiveだがReactiveプログラミングとは違うものです。

f:id:niwatako:20160820131200j:plain

Reactは一番上の親に状態を集約する。

イベントが発生すると、発生地点の子から親まで伝播して、必要箇所を再レンダリングする。

f:id:niwatako:20160820131217j:plain

このボトムアップのデータのリレーは辛い。

f:id:niwatako:20160820131301j:plain

どうやって改善するのか

Reactは他のフレームワークと一緒に使うことが多い。それがRedux。

f:id:niwatako:20160820131329j:plain

シングルトンとして扱う状態コンテナを作成

f:id:niwatako:20160820131333j:plain

テストがしやすくなる。

子から親へのデータフローが、子から直接Storeに送ることで、いちいち親にでんぱする必要がなくなる。

f:id:niwatako:20160820131418j:plain

React.js + Redux で状態が究極にシングルトンにまとまり、状態がイミュータブルなファンクショナブルな形になる。

f:id:niwatako:20160820131502j:plain

f:id:niwatako:20160820131506j:plain

実際は密結合にしたほうが処理がしやすいこともある。そういう時はかえって複雑な実装をしなければいけなくなってしまう。

ミドルウェアが他のミドルウェアに思わぬ悪影響をおよぼすことがある。

非同期が弱い。

f:id:niwatako:20160820131554j:plain

複数のミドルウェアが非同期連鎖反応した時、フローが予測しにくい。非同期処理連鎖はFRPに任せたほうが見通しが良い。

f:id:niwatako:20160820131635j:plain

f:id:niwatako:20160820131636j:plain

現在の状態を引数に新しい状態を返す

f:id:niwatako:20160820131654j:plain

テーマが深いので一つだけ紹介する

f:id:niwatako:20160820131701j:plain

Reduxはミーリ・マシンと一緒

f:id:niwatako:20160820131722j:plain

新しい状態を生み出す以外にも出力を伴う

f:id:niwatako:20160820131742j:plain

これら6つが揃ってミーリ・マシンと呼ぶことが出来る。

f:id:niwatako:20160820131822j:plain

f:id:niwatako:20160820131823j:plain

f:id:niwatako:20160820131830j:plain

ミーリ・マシンとFRPを組み合わせたらもっと面白い実装が出来るのではないか

f:id:niwatako:20160820131855j:plain

f:id:niwatako:20160820131857j:plain

出来上がったものはこちら。

f:id:niwatako:20160820131939j:plain

github.com

f:id:niwatako:20160820132005j:plain

f:id:niwatako:20160820132028j:plain

f:id:niwatako:20160820132115j:plain

非常に読みにくいのでもう少し綺麗にかけないかということでこういう書き方もサポート

f:id:niwatako:20160820132221j:plain

f:id:niwatako:20160820132246j:plain

f:id:niwatako:20160820132416j:plain

f:id:niwatako:20160820132418j:plain

f:id:niwatako:20160820132419j:plain

f:id:niwatako:20160820132421j:plain

f:id:niwatako:20160820132422j:plain

排他制御も完璧で非同期でも大丈夫です。

f:id:niwatako:20160820132450j:plain

この設計の面白い点はElmという言語の設計に似ていることです。HaskellライクにかけるJS。

f:id:niwatako:20160820132529j:plain

ReactがありReduxがありReduxはミーリ・マシンと透過でFRPと組み合わせると上手く書けるようになる、そしてそれはElmにちかい

f:id:niwatako:20160820132627j:plain

f:id:niwatako:20160820132628j:plain

Elm0.17ではFRPを捨てるという斜め上の展開になっている。

この分野は今後も面白いと思うので引き続きチェックしていきたい。

f:id:niwatako:20160820132744j:plain

Q&A

補足:ReactiveAutomatonとRxAutomatonの私のリポジトリにスターを下さい!!!知らなくてもそっと目をつぶって押して下さい🙇

github.com

github.com

感想

twitter.com

twitter.com

twitter.com

twitter.com

twitter.com

twitter.com

twitter.com

qiita.com

まとめ