目的
システムアーキテクチャである VIPER を理解すること
流れ
- システムアーキテクチャとは
- 欠点のあるアーキテクチャ Apple MVC
- VIPER とは
- アプリの作成(← コードあり)
- コードを踏まえてVIPERの説明
1.システムアーキテクチャとは
ここを参考にしてください
2. 代表的なシステムアーキテクチャ Apple MVC
iOSアプリ(プロフィール画面)を作成すると仮定し、Apple MVC を考えていく。
画面の描画は UIView が行う。
UIView の操作は UIViewController が行う。
この時、ドメイン( =Model ) の実装方法が明確に決められていない。
そのため、開発者によって ドメイン の実装方法がバラバラになり、関係性の認識が異なっていた。
影響範囲の分からないコードの量産に繋がる
これは、UIViewController に ドメイン が含まれがちになる。
この現象を 「Fat ViewController」「Massive ViewController」と呼ばれる。
→ 解決策として MVP や MVVM, VIPER といったシステムアーキテクチャが開発された
3. VIPER とは
クリーンアーキテクチャがもとになっている。
クリーンアーキテクチャをiOSアプリ用に再整理されたアーキテクチャ。
VIPERは、View
/Interactor
/Presenter
/Entity
/Router
の略語
VIPERの目的
依存性の分離, 要素単体で存在できるようにする
・要素同士が関心のない状態
・互いにプロトコルで繋がる
・実態は外部から差し込めるようにする
単一責任の原則
Single Responsibility Princible
「クラスの中身を変更する理由は複数存在しない(クラスに複数の機能を存在させない。そうすればクラスの中身を変更する理由は1つに絞られるはずだ。)」
1ビジネスロジック = 1クラス という原則
「データの取得」 「計算」 「結果を送信」 といったビジネスロジックは、それぞれ1クラスに収める
VIPER それぞれの責務(役割)

View
・UIを操作すること
・MVC上の VとC
・Presenterから教わったとおりに表示する事
Interactor
・ビジネスロジックを担当
・データのやりとり(CRUD, API)
・Entity の作成と破棄
・一つの役割に対して一つのファイル
※単一責任の原則 を強く意識する必要がある
Presenter
・UIKit を import しない
・View からの依頼を捌く
・Interactor への要求
・Router への指示
Interactorからデータ構造を受け取り、データ上にViewロジックを適用し、コンテンツの準備をし、最後にViewに何を表示するか教える
Entity
・データそのものの定義
・原則としてロジックを持たない
・ドメインに抽象化されたモデル
Entity を直接扱えるのは、Interactorのみ
Router
・画面遷移を担当
・画面遷移分ファイルを作成する
・Presentor からの指示で画面遷移を行う
・遷移先の画面を作成
・依存性注入を行う
・モジュール間のナビゲーションロジック
・モジュール間がどうなるべきか
デメリット
・ファイル数が多くなる
・学習コストが高い
4. アプリの作成(← コードあり)
コードはこちらに載ってます。
5. コードを踏まえてVIPERの説明
View
見た目に集中
・データの取得についての記述がない
・一覧から選択・ボタンを押す 等のプログラムを Presenter に任せることで、見た目にのみ集中できる
・命令に対してのみ「画面をどう見せるか」だけを考える。View がデータを取得し画面を操作することはない。
・if, for 文はなくなる傾向にある
・UIKitを使用して「背景色や文字」を変更する必要があるときは、if文を使っても良い
Interactor
1クラス1機能に集中
・単一責任の原則 に従って、1クラス1機能とする
(機能の例 : お気に入り記事の登録・APIからのデータ取得)
Presenter
仕様書のように振る舞う
・アプリの仕様書 をプログラムに落とし込むイメージ
・コード量が多くなりすぎないよう気をつける
・命名規則を意識する → コード量が多くなっても見通しの良いコードになる
・イベント内容と表示したいViewを合わせて書く → コードの見通しが良くなる
Router
画面遷移に集中
1クラス1グループ → ○
(1クラス1画面 → ×)
(グループの例 : アカウント登録系(メールアドレス/パスワード入力,ログイン...)・メニュー系・設定系)
Entity
・使用する変数を定義しておく
?Entity の構造体(struct)はそのままプリミティブ値で受け取る
?モデルクラスでは使いやすいように詳しい型で定義する
参考文献