Repositoryの後ろにネットワーク越しのシステムがあることの是非からRedux的世界へ

twitterで言ってたことを少し修正してまとめ。MVVM + Layered Architectureの文脈です。

最近、Repositoyとして抽象化しておけばそのデータがメモリ上にあるかそれともDB上にあるかネットワーク越しにあるか意識しなくていい、というのは嘘だと思ってる。パフォーマンスの観点除いても。


というのは、リポジトリが「非同期クエリ」を受け付け始めると、ReadStackの複雑性が跳ね上がるというのがあるからなんだけど、そもそもRepositoryへのクエリは必ず非同期であるというインターフェースにすればこれは問題にならないのかな


リポジトリを基本非同期に設計してもいいんだけど、そうすると同期的な表示を求めてくるUIプラットフォームと相性悪くなるんだよな


たとえばMVVMで考えると、モデルのイベントを購読して、イベント来たらクエリ投げてモデル以下にある状態を読み出してきて、自分のデータストアに書き戻すとデータバインドでViewが更新される、ってことすると思うんだけど、クエリが非同期だと、「イベント来たら非同期な操作投げる」ってなって、複雑さを増すと思うんだよ


そうなると、WebAPIは外部システムとみなして、WebAPIからデータ持ってくる操作は「外部システムからローカルのシステムにデータを取り込むコマンド」と考えてやったほうが全体的にシンプルになりやすい気がする


で、それやっていくと基本的に「状態の更新は常に同期操作」になって、なんとRedux的な世界観が近づいてくるんだよな。で、じゃあ非同期をどこで吸収するですかって話になったときに、middlewareっていう仕組み必要とするかアプリケーションサービスで吸収するかって話がある


わたしがRedux触ってみて良いと思ったのはsingle source of truthと、読み出しと書き込みが強制的に分離させられることと読み込みが常に同期的な操作であるって部分で、嫌だったのがmiddleware、ってのはこういうことです


Vuexのほうが好きな理由も同じです。ちゃんと非同期吸収ポイントが納得できる場所にある


あと、ReduxとかVuexはState更新したよってイベント購読管理しなくていいのが楽。けどそのトレードオフでStateの作り方をフレームワークから制約受ける。この制約を「良い制約」と思えるかどうかってのはあると思う。


これ単方向データフローを守ったMVVM前提で考えるからこういう結論になるんだなって思い至ってる


MVPならそもそも非同期であろうがなんだろうがそのタイミングでP呼び出すだけだもんな


ここで、ninjinkunさんと話した「MVVMは難しいパターンですよね」を思い出すのであった


あと単純に、Repositoryの後ろにネットワーク隠蔽しちゃうとAPIのレスポンス複数のVMから参照したいときとか、キャッシュをちゃんと制御したいときにも困る(リポジトリで透過的にキャッシュ?それ一時期web系ではやった"アンチパターン"だよね)


このへんのこと考えて設計した結果がBackLoggerのコードです。

github.com

今思うと、これ、RepositoryがいわゆるStateのポジションにいる、という考え方をしていると見て取れる。少なくともBackLoggerではこの考え方はかなりよく回ったと思っている。

追記:さまざまな反応

VuexとかReduxの制約が生きるシチュエーションについて

@shinpei0213: vuexとかreduxだとstateの作りに制約受けるの嫌なんだけど、InitialStateを外から与えてアプリをbootstrapしたいというようなことが起こる場合は良い制約だと思う

Repositoryってそういう責務かなあという話

@shinpei0213: そうですね。なので、記事では最後に「RepositoryをStateと見なすような感じ」という感じになっています。もしかしたらStateというのを生やして、RepositoryからStateに読み込む、みたいにすると用語の混乱がなくていいかなあと思ってるところです


@shinpei0213 ただ、同期で読み書きできる永続化層ならそれはStateとしてあつかっても不利益ないな(BackLoggerのSettingRepositoryの実装がそうなってる)というのもあり、「名付けをどちらに寄せるか」という問題かなと。


@shinpei0213 「このプロジェクトにおけるRepositoryの責務はこれです」が一貫しており、メンバーに共有するという制約付きですが


@shinpei0213 というかこの話実はイミュータブルドメインモデルと状態のライフサイクルの話と繋がっていて、かなり射程が深いので是非NDSで議論しましょう