iOSアプリアーキテクチャ比較検討(Cocoa MVC,MVVM,MVP,CleanArchtecture)


今回は、アーキテクチャをまとめてみました。備忘録。


# アーキテクチャを取り入れる理由


アーキテクチャはアプリを綺麗に開発・継続的に運用していくための設計方法。

UI（プレゼンテーション）とそれ以外のUIに関連しない処理（ドメイン）にざっくり分けられる。
分けられると何が良いのか。

- 処理が理解しやすい
- 重複コードの排除
- 分業がしやすい
- テスタビリティの向上
など。

これによって、品質や開発スピードの向上につながる。
アーキテクチャによって特徴が異なるため、開発人数や環境、期間などによってどれが最適か検討する必要がある。



# 各アーキテクチャごとの概要

| アーキテクチャ | &nbsp;&nbsp;&nbsp;&nbsp;概要 | 役割 | メリット |	デメリット |
|:-----------|:------------|:-----------|:------------|:------------|
| Cocoa MVC| Appleが推奨しているアーキテクチャ。<br>CocoaMVCの大きな特徴は、ViewとModelが完全に独立しているところ。<br>ModelとViewが独立していることによって、再利用性が高まり、Controllerだけ作り直せば流用できる。 | **Model** <br> - データの処理<br> - ビジネスロジック<br> - Entityの保持<br>  **ViewController** <br> - UIの更新<br>ユーザーのアクション通知<br> - Modelの操作  | - 開発スピードが早い、シンプルな構成で学習コストが低い。<br> - 経験が浅くても保守しやすい。<br>- Modelのテストが可能になる。|ViewControllerの肥大化や重複コードにより可読性の低下。|
|MVP（PassiveView）|MVP の特徴はテスト容易性と作業分担のしやすさを実現させるところ。<br>フロー同期（対象データを更新してからUI更新する）のため<br>データフローが追いやすく書き易い。<br>protocol 化して疎結合にすることで、Presenter単体でのテストが行える。|**Model**<br>- データの処理<br>- データの更新<br>- ビジネスロジック<br>**View**<br>- タップイベントなどをPresenerへ通知<br>- UIの更新<br>**Presenter**<br>- Modelの操作<br>- Viewを更新<br>- Viewの状態を保持<br>- UI関連のロジック|<br>- MVVMやCleanArchTectureなどに比べるとシンプルな構成。<br>- View（viewController）の肥大化が抑えられ可読性が向上する。<br>- 画面ごとに書き方が統一しやすい。 UIのテストコードも書けるようになる|<br>- コード量が増える。<br>- MVCに比べると学習が必要。<br>-　自分はあまり実際の現場では見ない。（コストのかけ方的に中途半端？もしくはそこまでテストコードを重視していないから） |
|MVVM|MVVM の特徴はViewとViewModelをデータバインディングと呼ばれるしくみで関連付けることで、<br>ViewModelの状態を更新するだけで、<br>Viewの状態も更新され画面に反映される。<br>ネットを見ていると最近よく使われているパターンの一つ。<br> 双方向の場合もあれば、画面からの変更のみを管理する場合もある。|**Model**<br>- データの処理<br>- ビジネスロジック<br>**View**<br>- ユーザーのアクションをViewModelへ通知<br>- ViewModelの変更を元にUIの更新<br>**ViewModel**<br>- ViewとViewModelのバインディング<br>- Viewの状態を保持<br>- ViewとModelの仲介|<br>- 可読性の向上<br>- テストの容易性<br>- Viewへの更新通知、指示の部分のコードが不要|<br>- 小規模、少人数のプロジェクトではコストに対してリターンが少ない。。<br>- 学習コストが高い。<br>- ただ、自分の行ったFlutter案件や直近の大規模案件ではこのパターンを派生したり、一部用いたりしている印象。|
|Clean Architecture|サーバー通信や例外処理などもModelに切り分けられることが多いが、<br>より責務を細分化して定義することで<br>変更に強く可読性が高い。<br>Clean Architectureは依存関係に重きを置く設計であるため、<br>各層を単一方向につなげる。|**Entity**<br>- データ<br>- 使用する外部オブジェクトに依存しないロジック<br>**UseCase**<br>- ビジネスロジック<br>**Repository**<br>- データの処理<br>**View**<br>- UIの更新<br>- タップイベントなどをUseCaseへ通知<br>- データとViewのバインディング<br>- Viewの状態を保持|<br>- OSに非依存のロジックはAndroid,iOSで同じように書きやすい。<br>- 「何をどこに置く」という規約として機能し、コードの粒度を揃える|- 学習コストが高い。<br>- 責務を細分化するためファイル数が多くなる。<br>- UseCaseがUtilityのようになってしまうと良くない。　<br> -CleanArchitecture+MVVM（それぞれの使いたい部分を合わせたイメージの方が近い）のような形もあった。

参考：Apple Document Archve(MVC)[Apple Document Archve(MVC)](https://developer.apple.com/library/archive/documentation/General/Conceptual/DevPedia-CocoaCore/MVC.html)

　　　[iOSアプリ設計パターン入門（書籍）](https://peaks.cc/820C2478/iOS_architecture )

# 実際の検討結果

各アーキテクチャを比較検討した結果、2人のプロジェクトではMVCのまま実装するのが良いと考え進めた。
Flutter開発の場合は公式も推奨しているMVVMを利用した（20２０年当時）

理由は以下の通り。


## 開発人数とスキルセットの考慮
Flux,CleanArchtecureなどのレイヤーが細分化されたアーキテクチャパターンは、

「何をどこに置く」という規約として機能し、コードの粒度を揃える機能がある。

そのため開発人数が5人以上の規模かつ、アーキテクチャパターンの理解が浅いメンバーが多い場合に有用であるため

少人数(2人)の場合、MVC のようなある程度自由の効くアーキテクチャパターンが良いと感じた。

FlutterでMVVMを取り入れた際には、1ヶ月ほど自分が先行してアーキテクチャの理解とCommon的なクラスや機能をある程度作成し、参考にできるような１画面を作った。
2ヶ月ほどでメンバーの理解も高まり、進められるようになったが、自分の経験不足もあり後々複数人数でやってから直した方が良いところが出てきた。


## プロジェクトの期間と規模
MVVM,CleanArchtecureは、スタートアップで根本的な概念、仕様の見直しが発生するプロジェクトでは効果が出づらく

MVCやMVPのような最低限のパターンでの方が、今回のプロジェクトの場合レビュワーの負担の減少や開発スピードという点で良い。

Flutterの場合は大規模ではなく、小〜中規模だったが今後の保守作業も見据えることもあり、MVVMを取り入れた。


## プロジェクトの優先項目
テストの容易性なども必要になってくるとは思うが

開発、保守のしやすさなどからMVCで問題ないと感じる。



## アーキテクチャ変更によるリスク
現状一定の品質を担保しながら開発スピードを上げるためMVCを採用している。

変更のバックログを作成し期間を確保すれば問題ないが、今後開発人数が増えないことや上記の理由などから

リスクを取る必要のある恩恵がないと判断される。

## まとめ
現場のアーキテクチャはCocoa MVCを採用してますが、現在技術検証ということでMVPの反映とかやっているのでまた実際に実装した所感も書ければと思います。