😸

クリーンアーキテクチャーと単方向データフロー

2021/09/04に公開

前回投稿に続いて、クリーンアーキテクチャーと単方向データフローの親和性に関する考察です。

一昨年、私はクリーンアーキテクチャーでAndroid/iOSアプリを開発し、ACCESSテックブック第1章を書きました。無料で読めますので、クリーンアーキテクチャーの概要はここでは短く済ませます。

概要

domainから他へインターフェースを提供し、「この通りに実装して結果をください」(to backend, data, sensor)、「Presenter型のオブジェクトを作ってくれれば結果を代入します」(to UI)とし、domainから他への依存を無くすのがクリーンアーキテクチャーの特徴です。

そのクリーンアーキテクチャーのデータの流れをわかりやすくするのが今回の話です。

補足

「クリーンアーキテクチャーを単方向データフロー化する」と書いてましたが、「元からView→UseCase→Presenterで単方向なのでは?」という意見がありました。確かにその通りです。この話は「データの流れをわかりやすくしたい」という内容なので、不適切な文章は修正しました。

Presenterを採用していると、ActionからViewに戻るまでのルートを自由に決めれるので、私の参画してる案件でもApplicationやAppDelegateなんかがPresenterを継承して、データの行き先がよくわからなくなってるロジックが多少ありました。

PresenterをStateに置き換え

まず、UIからdomainに渡すものをAction、domainからUIにはStateの更新を通知するようにしてみます。

AndroidアプリUnusedAppFinderで置き換えを実践してみました。commit

この図っぽくなりましたよね。

ところが、実はクリーンアーキテクチャーに反しています。Notify Updateのところで、UIがdomainに依存しているからです。

これはUI側からStateをSubscribeすることで回避可能で、矢印を依存関係で書くとデータの流れが分かりづらいので、UIまわりだけデータの流れで書いたというワケです。

さて、データの流れを意識するならViewModelも直さないとですね。

ViewModelからViewへは、依存こそありませんが、データは流れます。つまり、ViewとViewModelはデータの流れで言うと双方向の関係になっています。

これでは、ViewModelまわりのデータの流れが複雑で、テストもしにくいですね。

結局ViewModelは必要なのか

ViewModelを取ってしまうと、Viewに以下の責務が集中します。

  1. 画面の表示
  2. Stateの監視
  3. Stateから画面パーツ向けの型変換
  4. 画面の更新
  5. 画面遷移

これなら、2と3をViewModelとして分けてた方がまだ読みやすいでしょうし、テストのしにくさに至っては悪くなっています。

では、Viewからのイベント発火で直接interactorを呼び、ViewModelは上記2と3に専念させればどうでしょうか。

スッキリした気がします。

これもサンプルアプリでやってみました。commit
※LiveData→StateFlowの置き換えも含んだコミットなので若干わかりづらいかも…。

ちなみに最後の図のViewModelは、TCAではViewStore、UnioではViewStreamと呼ばれてたりします。ViewModelじゃない呼び名もアリかもしれないですね。

おわりに

大規模なプロジェクトには採用したことなく検討中なので、もしこうすればもっと良くなるとかコメントがあれば、ぜひ教えてください。

Discussion