モバイルアプリアーキテクチャ勉強会

これは社内勉強会で利用した資料です。
そのため、語尾が雑だったり主観的な記述が多いですが、懐に眠らせておくよりは公開したほうが世のためになると考え、この記事を公開します。

---

# この勉強会の目的

過去のアーキテクチャからナウいアーキテクチャまで一通り学ぶことで、今後の開発やリファクタリングの指針としたい。

---

# アーキテクチャとは

MVC とか MVP とかの、ディレクトリ構成や各レイヤで何を担当するかなどの話です。
今回は特にモバイルアプリ、どちらかというと iOS よりの話です。

---

# アーキテクチャは必要か？

標準に従うんじゃダメなの？

---

## iOS

* コントローラは UIViewController を継承する
    * ViewController ...?
* 普通に書くと View と Controller がぐっちゃぐっちゃ
* FatViewController へ...

```swift
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 へ...

```java
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 という関係性
* テストがかけない...

だから設計談義が盛り上がる

:innocent: 

---

# アーキテクチャを導入する目的

* 保守性の高いコード
    * FatController にしない
    * テストのかきやすい構成へ
* 考える時間/レビュー時間を減らす
    * どの階層、ファイルで何をするか決めておく
* 規約と秩序！！！！！！！！！！！！

---

# 本題

アーキテクチャいろいろあります

---

# MVC

---

# 原初 MVC

データの流れが一方方向、 Observer!

![MVC\-Process \- Model View Controller \- Wikipedia](https://upload.wikimedia.org/wikipedia/commons/thumb/a/a0/MVC-Process.svg/500px-MVC-Process.svg.png)
> [Model View Controller \- Wikipedia](https://ja.wikipedia.org/wiki/Model_View_Controller)

---

# 原初 MVC 問題点

Model が View にデータを送るが、 View は Model に依存した画面しか表示ができずつらい。
[MVCモデルの問題点を解決するPMモデルとMVPモデル \- GeekなNooblog](http://geekna.hatenablog.jp/entry/20110823/p1)

---

# MVC2

---

# MVC2

![Ruby on Rails チュートリアル：実例を使って Rails を学ぼう](https://railstutorial.jp/chapters/images/figures/mvc_detailed.png)
> [Ruby on Rails チュートリアル：実例を使って Rails を学ぼう](https://railstutorial.jp/chapters/toy_app?version=5.0#sec-mvc_in_action)

---

# MVC2

* Controller は View と Model をつなぐ。
* View と Model は直接繋がらない！ Controller を挟む。
    * MVC と比べ View と Model の依存が解決された！
* Fat Model :innocent: 

---

## Cocoa MVC

Apple 様の提唱している MVC。

![8012a41c-a9f1-4826-91b1-12bad399fe01.png](https://qiita-image-store.s3.amazonaws.com/0/5678/6d0ec88c-ba03-5ca2-6b21-316a83e9896e.png)


> [Objective\-Cプログラミングの概念 \(TP40010810 1\.0\)](chrome-extension://mhjfbmdgcfjbbpaeojofohoefgiehjai/index.html)

---

## Cocoa MVC

Model と Controller は Observer な関係。
やはり Controller の負担が大きすぎて Fat になる。
MCV を文字って Massive View Controller とか言われる。

* サンプル
    * [ios\-architectures/ios\-architectures/MVC at master · tattn/ios\-architectures](https://github.com/tattn/ios-architectures/tree/master/ios-architectures/MVC)

---

# MVP

---

# MVP

* Model
    * View と Presenter 以外
* View
    * **ViewController も View に含む！！！！！** ここがポイント
* Presenter
    * View と Model を仲介する

つまり View は View に専念し、 
Presenter がコントローラの枠割を担う

---

## 2 つの MVP

MVP と言っても 2 つあります

ややこしい :angry:  :innocent: :rage: 

* MVP (Supervising Controller)
* MVP (Passive View)

---

## MVP (Supervising Controller)

---

## MVP (Supervising Controller)

![Supervising Controller](https://i-msdn.sec.s-msft.com/dynimg/IC258649.png)
> [Supervising Controller](https://msdn.microsoft.com/ja-jp/library/ff648921.aspx)

---

## MVP (Supervising Controller)

* 原初 MVC とにてる、 Model が更新されたら View が更新される。
    * View と Model はデータバインディングする
    * View と Model が依存関係になるため簡単に Model や View を 変えられないなど問題がある
        * View と Model に依存は持ちたくないのでこれは使いたくない

---

## MVP (Passive View)

---

## MVP (Passive View)

![mvp\-passive\-view\.jpg \(278×336\)](http://2.bp.blogspot.com/_m9VtXqkOxi8/Sty6687QJOI/AAAAAAAAAIc/DLlrbv1vwNg/w1200-h630-p-k-no-nu/mvp-passive-view.jpg)
> [Dot Net Facts: The MVP pattern](http://dotnetfacts.blogspot.jp/2009/10/mvp-pattern.html)

---

## 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 を使える
* サンプル
    * [iyadagha/iOS\-mvp\-sample](https://github.com/iyadagha/iOS-mvp-sample)

---

## MVP (Passive View) :+1:

* 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](https://ja.wikipedia.org/wiki/Model_View_ViewModel)

---

## MVVM

![MVVMPattern \- Model View ViewModel \- Wikipedia](https://upload.wikimedia.org/wikipedia/commons/8/87/MVVMPattern.png)
> [Model View ViewModel \- Wikipedia](https://ja.wikipedia.org/wiki/Model_View_ViewModel)

---

## MVVM

* データバインディングが必須
    * ユーザが文字を入力する
    * 入力された文字が自動で ViewModel に連携される (binding)
    * ViewModel が Model に変更依頼
    * Model でなんか処理する
        * **変更は通知で伝える**
    * ViewModel の値が変わると自動で View も変わる (binding)
* MVP でデータバインディングを使うと ViewModel になる感じ

---

## 変更は通知で伝える

> [MVVMのModelにまつわる誤解 \- the sea of fertility](http://ugaya40.hateblo.jp/entry/model-mistake)

* ViewModel は戻り値のない Model のメソッドを叩くだけ
    * 返り値は受け取らない
* ViewModel は Model の変更を Observe する
    * Model は変更を ViewModel に通知する

ひたすら Observable を使う感じ...

---

## ライブラリが必須

* RxSwift, RxJava などのライブラリが必要
* ひたすら依存度が高い、Rx が死んだらアプリも死ぬ (かも)
    * [恐怖！忍び寄るライブラリへのロックイン \- Qiita](http://qiita.com/takasek/items/9424bb795b54a33e43ec)
* 学習コストが高い
    * RxSwift やってるけどめっちゃむずい... :sob:

---

## MVVM は今までとパラダイムが全然違う

* RxSwift は Functional Reactive Programing
    * 今までの命令型とは全然違う
    * 関数型で宣言的に書いていく
    * ちょっと入れてみるか〜という感じではない

---

## しかしアツい

<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr"><a href="https://twitter.com/hashtag/DroidKaigi?src=hash">#DroidKaigi</a>  サイバーエージェントブースにお越しくださった皆様、二日間ありがとうございました🙏アンケートの最終結果はこちらです👇 ✨ <a href="https://t.co/UlhOd5uk6t">pic.twitter.com/UlhOd5uk6t</a></p>&mdash; CyberAgentDevelopers (@ca_developers) <a href="https://twitter.com/ca_developers/status/840114047034908672">2017年3月10日</a></blockquote>
<script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script>

---

## 向き不向きを見極めて使う

* 本当に MVVM が必要か考えて使うべき
    * ノリで使ってはならない！
* 向いているもの
    * ユーザアクションの多いものや Reactive なアプリケーション
        * 例えば LINE みたいなのとか、電卓とか
        * (ユーザアクションが少ないアプリなど存在しないのでは...?)
* 導入に当たって現状の課題を考える
    * 状態を変数で持つのが苦しいか？
    * データバインディングが欲しいか？
    * Observable が求められているか？
* 学習コストは高いぞ

---

## 良い資料

* [DataBindingで実現するMVVM Architecture // Speaker Deck](https://speakerdeck.com/star_zero/databindingteshi-xian-surumvvm-architecture)
* [MVVMのModelにまつわる誤解 \- the sea of fertility](http://ugaya40.hateblo.jp/entry/model-mistake)
* [健康的なMVVM 書いてますか？ ~MVVMアンチパターン集~ // Speaker Deck](https://speakerdeck.com/takasek/jian-kang-de-namvvm-shu-itemasuka-mvvmantipatanji)
* [devxoul/RxTodo: iOS Todo Application using Reactive Architecture](https://github.com/devxoul/RxTodo)

---

# VIPER

---

# VIPER

![iOS Project Architecture: Using VIPER \| Cheesecake Labs](https://s3.amazonaws.com/ckl-website-static/wp-content/uploads/2016/04/viper_architecture-2000x720.jpg)

![iOS Project Architecture: Using VIPER \| Cheesecake Labs](https://s3.amazonaws.com/ckl-website-static/wp-content/uploads/2016/04/Viper-Module.png)
> [iOS Project Architecture: Using VIPER \| Cheesecake Labs](https://www.ckl.io/blog/ios-project-architecture-using-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) を作るので、モック化しやすい
* ファイル数が多い
    * generator みたいなのがある: [rambler\-digital\-solutions/Generamba: This codegenerator is too brilliant to be real\!](https://github.com/rambler-digital-solutions/Generamba)
* 規律と秩序
    * Presenter, Interactor などどう実装するかメンバーで認識の齟齬が起きにくい
    * 抽象に依存した実装になるためモック化がしやすい

---

## VIPER or not

![\#8 VIPER to be or not to be? – swifting\.io](https://raw.githubusercontent.com/swiftingio/blog/%238-Viper/Images/ViperOrNot.jpg?utm_source=swifting.io&utm_medium=web&utm_campaign=blog%20post)

> [\#8 VIPER to be or not to be? – swifting\.io](https://swifting.io/blog/2016/03/07/8-viper-to-be-or-not-to-be/)

---

## 資料

* [Architecting iOS Apps with VIPER · objc\.io](https://www.objc.io/issues/13-architecture/viper/)
* [iOS Project Architecture: Using VIPER \| Cheesecake Labs](https://www.ckl.io/blog/ios-project-architecture-using-viper/)
* [iOS Project Architecture : Using VIPER \[和訳\] \- Qiita](http://qiita.com/YKEI_mrn/items/67735d8ebc9a83fffd29)
* [VIPER アーキテクチャによる iOS アプリの設計](https://www.slideshare.net/UsrNameu1/viper-arch)

---

# Clean Architecture

VIPER をもっと厳密にしたやつ、 Layerd Architecture などと呼ばれる

![クリーンアーキテクチャ\(The Clean Architecture翻訳\)](http://blog.tai2.net/images/CleanArchitecture.jpg)
> [クリーンアーキテクチャ\(The Clean Architecture翻訳\)](http://blog.tai2.net/the_clean_architecture.html)

---

## 構成

![まだMVC,MVP,MVVMで消耗してるの？ iOS Clean Architectureについて \- Qiita](https://qiita-image-store.s3.amazonaws.com/0/19097/e70a4605-e066-b0c2-5c6e-678c71d595ce.png)
> [まだMVC,MVP,MVVMで消耗してるの？ iOS Clean Architectureについて \- Qiita](http://qiita.com/koutalou/items/07a4f9cf51a2d13e4cdc)

---

## ファイル数やばい

![bannzai/Kuri: Automatically generates necessary code for iOS CleanArchitecture and imports it into Xcode project\.](https://cloud.githubusercontent.com/assets/10897361/21471548/01c91b3a-cafa-11e6-8f33-58c2c8b3c68e.png)
> [bannzai/Kuri: Automatically generates necessary code for iOS CleanArchitecture and imports it into Xcode project\.](https://github.com/bannzai/Kuri)

やばいので解説しない

---

## どういう時に使うか

> * 長期にわたる開発・メンテナンスが必要になるとき
> * 複雑な機能を有するアプリを開発するとき
> * テストを重視した開発のとき
> 
> 長期というのは、クリーンアーキテクチャを案件に導入してみたことのある人々の間でだいたい1年以上
> [Clean Architectureとその派生系による最適なiOSアーキテクチャ選定の考察 ｜ Developers\.IO](http://dev.classmethod.jp/smartphone/iphone/clean-architecture-and-derivative-systems-for-ios/)

(メンテ含めて1年超えないアプリなど存在しないのでは？)

開発メンバーが2,3人でやるには大げさなきがするので、やるとしてもこれから削って必要のなのを見極めた方が良さそう。


---

## 資料

* [まだMVC,MVP,MVVMで消耗してるの？ iOS Clean Architectureについて \- Qiita](http://qiita.com/koutalou/items/07a4f9cf51a2d13e4cdc)
* [まだiOS Clean Architecture で消耗してるの？ 爆速開発ツールを作ったのでご紹介 \- Qiita](http://qiita.com/bannzai/items/6e8add18b15af235a19f)
* [クリーンアーキテクチャ\(The Clean Architecture翻訳\)](http://blog.tai2.net/the_clean_architecture.html)

---

# Flux

データの流れが一方方向！

![flux](https://raw.githubusercontent.com/facebook/flux/master/docs/img/flux-diagram-white-background.png)
> [facebook/flux: Application Architecture for Building User Interfaces](https://github.com/facebook/flux)

---

# Flux

* 原初 MVC も一方方向でしたね
* ぐるぐる回るよ〜
* DOM の反映は差分検知で React がよろしくやってくれる
    * iOS にも Android にも React はない
        * ライブラリ入れるか〜？
* データの一方方向などの考え方はめっちゃいいと思うけど、ライフサイクルなどが標準と離れすぎてる気が
* Flux したいなら ReactNative 使えば？
* こんなクソ記事を書いていた時期もあった
    * [React \+ Redux \+ TypeScript でWebアプリを作った感想・勉強法と Angular との比較 \- Qiita](http://qiita.com/star__hoshi/items/34eb4ccafcfa100b5cad)

---

# DDD

> ドメイン駆動設計は特定のアーキテクチャに依存しているものではありません。
> [Y\.A\.M の 雑記帳: ドメイン駆動設計について DroidKaigi 2017 で登壇しました。](http://y-anz-m.blogspot.jp/2017/03/droidkaigi-2017_9.html)

なので解説しません。

---

# そのた

* MVVM-Coordinator
    * [画面遷移をVC外で管理するパターンの参考資料 \- Qiita](http://qiita.com/yoching/items/e24197a38cccbba880c1)
* [ヘキサゴナルアーキテクチャ\(Hexagonal architecture翻訳\)](http://blog.tai2.net/hexagonal_architexture.html)

多分他にもいっぱいある :feet: 

---

# まとめ (個人の意見)

* MVP は絶対に欲しい
* MVVM は検討した上で導入
* VIPER の DI の思想は良いので導入したい
    * Clean Architecture は重すぎるので VIPER より厳格に決めたいと思ってから入れたい
* まずは MVVM や VIPER がどれほどのものか **実際に何か作る** ことが必要と思う
* [あなたの開発、Hype\(誇大宣伝\) Driven Development になっていませんか？ \- Qiita](http://qiita.com/devneko/items/4f748253b2e2cd1192b1)

---

# わかりやすい資料

最初からこれよんだ方がわかりやすいのでは？

* [onmyway133/fantastic\-ios\-architecture: Better ways to structure apps](https://github.com/onmyway133/fantastic-ios-architecture)
* [10分で振り返るソフトウェアアーキテクチャの歴史2017 // Speaker Deck](https://speakerdeck.com/takasek/10fen-tezhen-rifan-rusohutoueaakitekutiyafalseli-shi-2017)
* [iOSアプリ設計大全集 2016 \- Qiita](http://qiita.com/tattn/items/d4b95af0b60c3849243a)
* [Webアプリケーション開発者から見た、MVCとMVP、そしてMVVMの違い \- Qiita](http://qiita.com/shinkuFencer/items/f2651073fb71416b6cd7)

---

# ほか参考

* [MVCモデルの問題点を解決するPMモデルとMVPモデル \- GeekなNooblog](http://geekna.hatenablog.jp/entry/20110823/p1)
* [Objective\-Cプログラミングの概念 \(TP40010810 1\.0\)](chrome-extension://mhjfbmdgcfjbbpaeojofohoefgiehjai/index.html)
* [onmyway133/fantastic\-ios\-architecture: Better ways to structure apps](https://github.com/onmyway133/fantastic-ios-architecture)

---

# 質問

---

## アーキテクチャを途中で変えたりはできるのか？

MVC -> MVP とかは Presenter 作るだけ、 VIPER も既存のを分割するので難しくない。
ただし、 MVVM -> MVP とかは作り直しのレベルになる。

---

## いまのあなたのアプリはどうなの？

MVC でできてる。正直ミスった。
しかも MVC の C と M のやりとりを callback でやっている。
半年前は勉強不足だった。

---

## Flux 良さそうじゃない？

Store を変えれば View が変わるの良さそう。
Web フロントエンドの人曰くガチの Flux はややこしいので必要な部分をかいつまんでやるのが良いとのこと。

React-Native やっていきたい。

---

## そもそもなぜ Apple は View と Controller を一緒にしているのか

storyboard と紐付くのが ViewController だから。
また、学習コストがとても低い。
入門書に Presenter などは出てこない。

---

## アーキテクチャが目的にならないようにしたいね

その通り。

---

画像など問題ありましたら消します。