iOSエンジニアリング

[iOSアーキテクチャ #5] iOS VIPERアーキテクチャ、大規模アプリが導入して離れた理由(RIBsまで)

iOSアーキテクチャの中で、VIPERほど評価が極端に分かれるパターンは珍しいでしょう。

読了 5 分
[iOSアーキテクチャ #5] iOS VIPERアーキテクチャ、大規模アプリが導入して離れた理由(RIBsまで)のカバー画像

iOSアーキテクチャの中で、VIPERほど評価が極端に分かれるパターンは珍しいでしょう。

一方では「大規模チーム協業の答え」と呼ばれ、他方では「ボイラープレート地獄」と呼ばれます。実際、複数の大規模サービスアプリが一時期VIPERやその派生を導入し、数年後にはより軽量な構成へ移行しました。

今回は、VIPERが何を解決しようとしたパターンなのか、そしてなぜその代償が大きかったのかをまとめます。


VIPERは5つの要素で構成される

VIPERは1つの画面を5つの役割に分割します。名前自体が5つの頭文字です。

  • View:画面表示を担当。ビューコントローラを含み、「描画だけ」を行います
  • Interactor:ビジネスロジック。データを取得し、ルールを適用します
  • Presenter:ViewとInteractorの仲介。データを画面表示用に加工します
  • Entity:純粋なデータモデル
  • Router(Wireframe):画面遷移を担当

MVC(Model-View-Controller)で1つのビューコントローラが担っていた仕事を4つに分け、画面遷移も別の要素であるRouterに切り出します。第1回で見たMassive View Controllerの責務それぞれに専用の場所を与えるわけです。

核心となるルールは、一方向に近い厳密な参照関係です。ViewはPresenterだけを知り、PresenterはInteractorとRouterを知り、InteractorはEntityだけを扱います。各境界をプロトコルで分けるため、どの要素もmockに差し替えられます。


何が良くなるのか?

この構成が力を発揮する場面は、確かにあります。

1つ目は、テストカバレッジを極限まで高められることです。すべての境界がプロトコルなので、Interactor、Presenter、Routerをそれぞれ単独でテストできます。

2つ目は、大規模チームでの分業が容易になることです。画面ごとの構成が同じなので、「誰が作った画面でもファイル構成は同じ」という予測可能性が生まれます。数十人が1つのコードベースを扱うとき、この均一性は実際に価値があります。

3つ目は、機能単位のモジュール化と相性が良いことです。1つの画面が自己完結した5要素になるため、機能ごとにモジュールを切り出しやすくなります。VIPERから着想を得たUberのRIBsは、この方向性を極限まで押し進めた例です。Viewではなくビジネスロジック単位でアプリをツリー構造に分割します。

ボタン1つの画面にも同じ5要素が強制されます
ボタン1つの画面にも同じ5要素が強制されます

なぜ皆離れていったのか?

問題はコストです。

ボイラープレートが圧倒的です。ボタン1つの画面でも、View、Interactor、Presenter、Entity、Routerと、それらの間のプロトコルまで含めると、6〜7個のファイルが生まれます。「ラベルのテキストを1つ変えるのに3つのファイルを通る」という嘆きが出るのも無理はありません。

単純な画面にも同じ重さが強制されます。静的な設定画面でも複雑なフィード画面でも、同じ5要素です。画面の複雑さと構成の重さが比例しません。

学習曲線とオンボーディングコストも軽くありません。データがView → Presenter → Interactor → Presenter → Viewと戻ってくる流れを初めて見る人には、追いかけるのに時間がかかります。

そして決定打となったのがSwiftUIの登場です。VIPERは「ビューコントローラから責務を切り離す」というUIKit時代の問題意識から生まれました。しかしSwiftUIではView自体が軽く、画面遷移の方法も異なるため、Routerのような要素が不自然になります。問題そのものが変わったのです。


では、VIPERは失敗したパターンなのか?

そう見るのは難しいでしょう。VIPERの遺産は現在の標準的な実践に溶け込んでいるからです。

  • 画面遷移を専用オブジェクトに切り出す → Coordinatorパターンとして定着
  • ビジネスロジックをプレゼンテーションから分離する → UseCase/Repository層として定着
  • 境界をプロトコルで分ける → 依存性注入とテストの実践として定着

VIPERの5要素をそのまま使うチームは減りましたが、その5要素が解決しようとした問題と解決策は生き残りました。今は必要な要素だけを選んで使う時代に近いでしょう。

全体としては廃れましたが、使える要素は標準的な実践として残っています
全体としては廃れましたが、使える要素は標準的な実践として残っています

まとめ

  • VIPERは1つの画面をView・Interactor・Presenter・Entity・Routerの5要素に分け、境界をプロトコルで定義するパターンです。
  • テストのしやすさと大規模チームでの均一性が強みですが、1画面に6〜7個のファイルが必要になるボイラープレートコストは大きな負担です。
  • SwiftUI時代になって問題意識そのものが変わり、原型のまま使うチームは減りました。
  • ただし、Router→Coordinator、Interactor→UseCaseのように、その遺産は標準的な実践として生き残っています。

次回は、その遺産の中で最も広く普及した形、クリーンアーキテクチャにおけるUseCaseとRepositoryがiOSで実際に果たす役割を扱います。

あわせて読みたい