これは社内勉強会で利用した資料です。
そのため、語尾が雑だったり主観的な記述が多いですが、懐に眠らせておくよりは公開したほうが世のためになると考え、この記事を公開します。
この勉強会の目的
過去のアーキテクチャからナウいアーキテクチャまで一通り学ぶことで、今後の開発やリファクタリングの指針としたい。
アーキテクチャとは
MVC とか MVP とかの、ディレクトリ構成や各レイヤで何を担当するかなどの話です。
今回は特にモバイルアプリ、どちらかというと iOS よりの話です。
アーキテクチャは必要か?
標準に従うんじゃダメなの?
iOS
- コントローラは UIViewController を継承する
- ViewController ...?
- 普通に書くと View と Controller がぐっちゃぐっちゃ
- FatViewController へ...
import UIKit
class HogeViewController: UIViewController {
@IBOutlet weak var tableView: UITableView!
@IBOutlet weak var button: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
}
@IBAction func buttonTapped(_ sender: AnyObject) {
print("tap")
}
}
Android
- コントローラは Activity を継承する
- 普通に書くと Activity と View がぐっちゃぐっちゃ
- FatActivity へ...
public class MainActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.d(msg, "The onCreate() event");
}
}
つまり M-VC
- iOS も Android も View と Controller がまとめられてる
- M-VC なコードになる
- Model, ViewController という関係性
- テストがかけない...
だから設計談義が盛り上がる
アーキテクチャを導入する目的
- 保守性の高いコード
- FatController にしない
- テストのかきやすい構成へ
- 考える時間/レビュー時間を減らす
- どの階層、ファイルで何をするか決めておく
- 規約と秩序!!!!!!!!!!!!
本題
アーキテクチャいろいろあります
MVC
原初 MVC
データの流れが一方方向、 Observer!
原初 MVC 問題点
Model が View にデータを送るが、 View は Model に依存した画面しか表示ができずつらい。
MVCモデルの問題点を解決するPMモデルとMVPモデル - GeekなNooblog
MVC2
MVC2
MVC2
- Controller は View と Model をつなぐ。
- View と Model は直接繋がらない! Controller を挟む。
- MVC と比べ View と Model の依存が解決された!
- Fat Model
Cocoa MVC
Apple 様の提唱している MVC。
Cocoa MVC
Model と Controller は Observer な関係。
やはり Controller の負担が大きすぎて Fat になる。
MCV を文字って Massive View Controller とか言われる。
MVP
MVP
- Model
- View と Presenter 以外
- View
- ViewController も View に含む!!!!! ここがポイント
- Presenter
- View と Model を仲介する
つまり View は View に専念し、
Presenter がコントローラの枠割を担う
2 つの MVP
MVP と言っても 2 つあります
ややこしい
- MVP (Supervising Controller)
- MVP (Passive View)
MVP (Supervising Controller)
MVP (Supervising Controller)
MVP (Supervising Controller)
- 原初 MVC とにてる、 Model が更新されたら View が更新される。
- View と Model はデータバインディングする
- View と Model が依存関係になるため簡単に Model や View を 変えられないなど問題がある
- View と Model に依存は持ちたくないのでこれは使いたくない
MVP (Passive View)
MVP (Passive View)
MVP (Passive View)
- 処理の流れ(MVC2 とにてる)
- View のイベントを Presenter に渡す
- Presenter が Model に処理を依頼
- Model が処理して Presenter に返す
- Presenter が View に渡す
- View はそれを表示する
MVP (Passive View)
- View と Model が依存していない
- Presenter は View がどう描画されるか知らない
- Presenter に import UIKit を書いてはいけない!!
- だから概念的には iOS でも Mac アプリでも同じ Presenter を使える
- サンプル
MVP (Passive View)
- Passive View 良いと思います。
- 今後新規アプリを作る時は少なくとも MVP は欲しい
- わかりやすいので学習コストが少ない
- Presenter のテストがかける
- view のテストは...
- Presenter が大きくなりがちだけどそういうもんじゃね?
MVP 2つありますが、これ以降の MVP という単語は Passive View を指します。
MVVM
発祥は Microsoft
MVVMパターンは、2006年11月21日にリリースされた.NET Framework 3.0に実装されたWPFとSilverlightの両方をサポートするために考案された。
Model View ViewModel - Wikipedia
MVVM
MVVM
- データバインディングが必須
- ユーザが文字を入力する
- 入力された文字が自動で ViewModel に連携される (binding)
- ViewModel が Model に変更依頼
- Model でなんか処理する
- 変更は通知で伝える
- ViewModel の値が変わると自動で View も変わる (binding)
- MVP でデータバインディングを使うと ViewModel になる感じ
変更は通知で伝える
- ViewModel は戻り値のない Model のメソッドを叩くだけ
- 返り値は受け取らない
- ViewModel は Model の変更を Observe する
- Model は変更を ViewModel に通知する
ひたすら Observable を使う感じ...
ライブラリが必須
- RxSwift, RxJava などのライブラリが必要
- ひたすら依存度が高い、Rx が死んだらアプリも死ぬ (かも)
- 学習コストが高い
- RxSwift やってるけどめっちゃむずい...
MVVM は今までとパラダイムが全然違う
- RxSwift は Functional Reactive Programing
- 今までの命令型とは全然違う
- 関数型で宣言的に書いていく
- ちょっと入れてみるか〜という感じではない
しかしアツい
#DroidKaigi サイバーエージェントブースにお越しくださった皆様、二日間ありがとうございました🙏アンケートの最終結果はこちらです👇 ✨ pic.twitter.com/UlhOd5uk6t
— CyberAgentDevelopers (@ca_developers) 2017年3月10日
向き不向きを見極めて使う
- 本当に MVVM が必要か考えて使うべき
- ノリで使ってはならない!
- 向いているもの
- ユーザアクションの多いものや Reactive なアプリケーション
- 例えば LINE みたいなのとか、電卓とか
- (ユーザアクションが少ないアプリなど存在しないのでは...?)
- ユーザアクションの多いものや Reactive なアプリケーション
- 導入に当たって現状の課題を考える
- 状態を変数で持つのが苦しいか?
- データバインディングが欲しいか?
- Observable が求められているか?
- 学習コストは高いぞ
良い資料
- DataBindingで実現するMVVM Architecture // Speaker Deck
- MVVMのModelにまつわる誤解 - the sea of fertility
- 健康的なMVVM 書いてますか? ~MVVMアンチパターン集~ // Speaker Deck
- devxoul/RxTodo: iOS Todo Application using Reactive Architecture
VIPER
VIPER
VIPER 用語
- View(UIVIewVontroller)
- ボタンをしたのを Presenter に伝える
- Presenter
- Interactor, Router, View などの橋渡し
- Router
- Dependency Injection と画面遷移
- Interactor
- API の実行やデータの fetch など
- DataManager
- VIPER の文字の中には出てこない、あってもなくても良い
- Interactor が直接データを触らないようにする
- Entity
- データオブジェクト、データ型定義みたいなやつ
これらを 1 つのモジュール(画面)として管理
VIPER のキモは Router
- モジュールは全て interface をきり interface に従い実装する
- それぞれのモジュールは実装に依存せず interface に依存する
- 抽象に依存した実装になる
- Router がモジュールに対し依存性を注入する
- テストがかける!!!!!!!!!!
メリデメ
- すべて Protocol (Interface) を作るので、モック化しやすい
- ファイル数が多い
- 規律と秩序
- Presenter, Interactor などどう実装するかメンバーで認識の齟齬が起きにくい
- 抽象に依存した実装になるためモック化がしやすい
VIPER or not
資料
- Architecting iOS Apps with VIPER · objc.io
- iOS Project Architecture: Using VIPER | Cheesecake Labs
- iOS Project Architecture : Using VIPER [和訳] - Qiita
- VIPER アーキテクチャによる iOS アプリの設計
Clean Architecture
VIPER をもっと厳密にしたやつ、 Layerd Architecture などと呼ばれる
構成
ファイル数やばい
やばいので解説しない
どういう時に使うか
- 長期にわたる開発・メンテナンスが必要になるとき
- 複雑な機能を有するアプリを開発するとき
- テストを重視した開発のとき
長期というのは、クリーンアーキテクチャを案件に導入してみたことのある人々の間でだいたい1年以上
Clean Architectureとその派生系による最適なiOSアーキテクチャ選定の考察 | Developers.IO
(メンテ含めて1年超えないアプリなど存在しないのでは?)
開発メンバーが2,3人でやるには大げさなきがするので、やるとしてもこれから削って必要のなのを見極めた方が良さそう。
資料
- まだMVC,MVP,MVVMで消耗してるの? iOS Clean Architectureについて - Qiita
- まだiOS Clean Architecture で消耗してるの? 爆速開発ツールを作ったのでご紹介 - Qiita
- クリーンアーキテクチャ(The Clean Architecture翻訳)
Flux
データの流れが一方方向!
facebook/flux: Application Architecture for Building User Interfaces
Flux
- 原初 MVC も一方方向でしたね
- ぐるぐる回るよ〜
- DOM の反映は差分検知で React がよろしくやってくれる
- iOS にも Android にも React はない
- ライブラリ入れるか〜?
- iOS にも Android にも React はない
- データの一方方向などの考え方はめっちゃいいと思うけど、ライフサイクルなどが標準と離れすぎてる気が
- Flux したいなら ReactNative 使えば?
- こんなクソ記事を書いていた時期もあった
DDD
ドメイン駆動設計は特定のアーキテクチャに依存しているものではありません。
Y.A.M の 雑記帳: ドメイン駆動設計について DroidKaigi 2017 で登壇しました。
なので解説しません。
そのた
- MVVM-Coordinator
- ヘキサゴナルアーキテクチャ(Hexagonal architecture翻訳)
多分他にもいっぱいある
まとめ (個人の意見)
- MVP は絶対に欲しい
- MVVM は検討した上で導入
- VIPER の DI の思想は良いので導入したい
- Clean Architecture は重すぎるので VIPER より厳格に決めたいと思ってから入れたい
- まずは MVVM や VIPER がどれほどのものか 実際に何か作る ことが必要と思う
- あなたの開発、Hype(誇大宣伝) Driven Development になっていませんか? - Qiita
わかりやすい資料
最初からこれよんだ方がわかりやすいのでは?
- onmyway133/fantastic-ios-architecture: Better ways to structure apps
- 10分で振り返るソフトウェアアーキテクチャの歴史2017 // Speaker Deck
- iOSアプリ設計大全集 2016 - Qiita
- Webアプリケーション開発者から見た、MVCとMVP、そしてMVVMの違い - Qiita
ほか参考
- MVCモデルの問題点を解決するPMモデルとMVPモデル - GeekなNooblog
- Objective-Cプログラミングの概念 (TP40010810 1.0)
- onmyway133/fantastic-ios-architecture: Better ways to structure apps
質問
アーキテクチャを途中で変えたりはできるのか?
MVC -> MVP とかは Presenter 作るだけ、 VIPER も既存のを分割するので難しくない。
ただし、 MVVM -> MVP とかは作り直しのレベルになる。
いまのあなたのアプリはどうなの?
MVC でできてる。正直ミスった。
しかも MVC の C と M のやりとりを callback でやっている。
半年前は勉強不足だった。
Flux 良さそうじゃない?
Store を変えれば View が変わるの良さそう。
Web フロントエンドの人曰くガチの Flux はややこしいので必要な部分をかいつまんでやるのが良いとのこと。
React-Native やっていきたい。
そもそもなぜ Apple は View と Controller を一緒にしているのか
storyboard と紐付くのが ViewController だから。
また、学習コストがとても低い。
入門書に Presenter などは出てこない。
アーキテクチャが目的にならないようにしたいね
その通り。
画像など問題ありましたら消します。