ReSwiftをためした所感
現在仕事で開発中のiOSアプリにReSwiftを導入できないか検討した。
結論としては今回は導入を見送ったが、良いと感じた部分が沢山あったので雑な作業メモを転記する。
ReSwift とは
Redux は複雑な状態を管理するために生まれたJS発祥の技術
そのRedux をSwiftに移植したものがReSwift
ReSwift/ReSwift: Unidirectional Data Flow in Swift - Inspired by Redux
こちらに大変わかりやすくまとまっている
ReSwiftでアプリの状態管理 / Reactive Swift Meetup // Speaker Deck
モチベーション
- アプリ全体で共有する状態の管理をうまくしたい
- グローバルなスコープのシングルトンにアプリの様々な箇所からアクセスするのは不健全な気がした
インストールから簡単に使うところまでの作業メモ
まずは以下のリポジトリをそのままアプリに移植し、それを拡張していった
ReSwift/CounterExample: Demo Application of Unidirectional Data Flow in Swift, Built with ReSwift
ReSwift を Cartfile に追加
$ carthage update --platform iOS --no-use-binaries
ReSwift の設定をプロジェクトに反映
AppState を作成
- アプリ全体の状態を持つ
- Action からしか変更できない
CounterReducer を作成した
- counterの状態を変更する Reducer
- AppState を返す状態を持たない関数
Actions を作成した
Action protocol を実装した struct として定義する
subscribe すると、最初に newState が呼ばれて現在の state が降ってくる
- 最初の state は 特に action をdispatchしていないので、ReSwiftinit 型になっている
- action を dispatch すると、その結果また newState が呼ばれて状態の更新が通知される
subscribe しないで dispatch することもできる
- 状態は変更できるが、newStateに通知されない
ネットワークエラーでアラートを出したいときはどうする?
- ErrorActionを発行して、subscribeしているViewControllerで新しいstateに応じてエラーを表示する
アプリアーキテクチャに関する考察
MVP(Clean Architecture) に適用する場合
Redux にすることで、今までdelegate とかクロージャでばらばらに受け取っていたコールバックを1つのメソッドで、1つの状態として扱えるようになる
引数とメソッド呼び出しについて
- データを fetch するaction で引数にデータを渡さなくても、クロージャのstate を通じて、欲しい状態を取れるようになる
- ようするにグローバル変数と変わらないのだが、状態の変更 をAction, Reducer を用いるよう制限することで、データの流れを把握しやすくする
Promise を使った非同期処理の連結
- AsyncActionCreator を使えば非同期処理の結果をActionとして発行できる
- 状態をクロージャ間で引数として渡すのではなく、それぞれのクロージャを別のメソッドに切り出す
- newStateが呼ばれるたびに状態をチェックして発火させる
- ReSwift の話題でよくstate machineが出てくる所以はまさにここっぽい
Reducer の分割について
How could i use multiple reducer in Reswift 4.0.0 · Issue #241 · ReSwift/ReSwift いいかんじ
ユニットテスト
まだ書いたことはないが、Action は基本的に状態を持たないのでテストは書きやすそう
デバッグのしやすさ
- クラッシュした時のStateをキャプチャできるので、再現してデバッグするのが簡単になるのではないか
- ReSwift Recorderという仕組みもある
やめた理由
- 今後自分以外の人も保守することを考えると、ReSwiftにロックインされるのはあまり良くない
- 今開発中のアプリは大量の状態を持っているわけではないので、現状の要件にはそこまでマッチしていない
- newState の取り回しが若干面倒な気がしている
- pros が cons を上回るなら導入も吝かではない
- もう少し練度が上がればスムーズに使っていけるのかもしれない