はじめに
iOS 開発の世界では、MVC や MVVM だけでは責務分離が不十分になりがちです。
そこで登場したのが VIPER アーキテクチャ。
VIPER は Clean Architecture をベースにした設計思想で、画面単位で役割を明確に分けることで 保守性・テスト容易性 を高めます。
VIPER の構成要素
VIPER は頭文字を取った以下5つの責務に分かれます。
1. View
- UI を表示し、ユーザー操作を Presenter に伝える
- 自分でロジックは持たない(受け身)
protocol SampleViewProtocol: AnyObject {
func showData(_ text: String)
}
class SampleViewController: UIViewController, SampleViewProtocol {
var presenter: SamplePresenterProtocol!
override func viewDidLoad() {
super.viewDidLoad()
presenter.viewDidLoad()
}
func showData(_ text: String) {
print("表示: \(text)")
}
}
2. Interactor
- ビジネスロジック担当(ユースケース)
- データ取得や処理を行い、結果を Presenter に返す
protocol SampleInteractorProtocol {
func fetchData()
}
class SampleInteractor: SampleInteractorProtocol {
weak var presenter: SamplePresenterProtocol?
func fetchData() {
let data = "データ取得完了"
presenter?.didFetchData(data)
}
}
3. Presenter
- View と Interactor の仲介役
- ユーザー操作を受け取り、必要な処理を Interactor に依頼
- 結果を State に変換して View に渡す
protocol SamplePresenterProtocol: AnyObject {
func viewDidLoad()
func didFetchData(_ data: String)
}
class SamplePresenter: SamplePresenterProtocol {
weak var view: SampleViewProtocol?
var interactor: SampleInteractorProtocol!
var router: SampleRouterProtocol!
func viewDidLoad() {
interactor.fetchData()
}
func didFetchData(_ data: String) {
view?.showData(data)
}
}
4. Entity
- ビジネスルールを表すモデル
- データそのもの(構造体やクラス)
- Interactor の中で使われる
struct User {
let id: Int
let name: String
}
5. Router
- 画面遷移やモジュールの組み立て(DI)を担当
- Presenter が次画面への遷移を依頼する
protocol SampleRouterProtocol {
static func createModule() -> UIViewController
}
class SampleRouter: SampleRouterProtocol {
static func createModule() -> UIViewController {
let view = SampleViewController()
let presenter = SamplePresenter()
let interactor = SampleInteractor()
let router = SampleRouter()
view.presenter = presenter
presenter.view = view
presenter.interactor = interactor
presenter.router = router
interactor.presenter = presenter
return view
}
}
データフローまとめ
View → Presenter → Interactor → Presenter → View
↓
Router(画面遷移)
↓
Entity(データ)
- View はユーザー入力を Presenter に渡す
- Presenter が Interactor を呼び出し、処理結果を受け取る
- Presenter が View に反映する
- Router が画面遷移を制御
VIPER のメリット
- 責務が明確で大規模開発に強い
- テストしやすい(Interactor, Presenter単体テストが容易)
- 各層の独立性が高く、再利用性も向上
VIPER のデメリット
- ファイル数が増える(1画面 = 5ファイル以上)
- 小規模アプリだとオーバーエンジニアリングになりやすい
- セットアップ(Router での依存注入)がやや複雑
VIPER と Clean Architecture の関係
- VIPER = Clean Architecture を iOS に落とし込んだ形
- UseCase = Interactor
- Controller = Router
- Entity = Domain Model
- Presenter = Application Layer
まとめ
- VIPER は View / Interactor / Presenter / Entity / Router の5つで構成される
- Clean Architecture の思想をモバイル開発に適用したもの
- 大規模開発やチーム開発に向くが、小規模にはやや重い