【Swift】イメージで理解するMVPとMVC

# はじめに
最近の大谷選手の活躍には目が離せませんね。彼こそまさにMVPですね。ということで今日はMVPとMVC(Cocoa MVC)アーキテクチャの違いについてイメージで理解できるようにまとめていきます。
まだまだ、技術的にひよっこもひよっこなので間違っていることもあるかと思いますが、参考になれば嬉しいです。



# 記事を読んでわかること
- MVPとMVCの違い
- MVCと比較した時のMVPのいいところ

# 想定読者
以下の条件に当てはまる人が読むといいのではないかと思っております。
もちろんそれ以外の人もぜひ。
- MVCは何となく知ってるぞ！
- MVPって聞いたことあるけどなんだかよくわからない！
- MVCとMVPの違いがよくわからない！


# MVCとMVPのイメージ
何かを理解する時にイメージをするというのはとても大事だと僕は思っています。
そこで、まず初めにMVCとMVPをイメージにすることでなんとなくの違いを理解していこうと思います。
今回は飲食店を用いてイメージしていきます。

## 飲食店でイメージするMVC
僕の中でMVCはこんなイメージです。

### お店の形式
- フードコート方式

### 登場人物
- ご飯を食べたい人(あなた)
- ご飯を作る人(お店)

### フードコートでご飯を食べるまでの流れ
- `あなた`が食べたい料理のある`お店`に自分で行って注文をします
- 提供された料理を`自分`で席に運んで食べます
- もし、希望の商品が売り切れなどになっていた場合は、`自分`で次の`お店`を選んで再度料理を注文します

これが僕の中でのMVCのイメージです。
つぎにMVPのイメージを紹介します。

## 飲食店でイメージするMVP
僕の中でMVPはこんなイメージです。

### お店の形式
- お店はレストラン

### 登場人物
- ご飯を食べたい人(あなた)
- 注文を聞き、料理を運んでくれる人（ホールスタッフ）
- 料理を作る人(シェフ)

### レストランでご飯を食べるまでの流れ
- `あなた`は食べたい料理を`ホールスタッフ`に注文します
- `ホールスタッフ`は`シェフ`に調理を依頼します
- `ホールスタッフ`が`あなた`に料理を運んできてくれるので、それを食べます
- もし食材がなくなっていると`シェフ`から伝えられた際は`ホールスタッフ`が`あなた`に教えてくれます

## MVCとMVPのイメージの違い
さて、ざっくりご飯を食べるときの状況はイメージできたでしょうか？
この2つにはおおきな違いがあります。それは、

:::note info
**あなたの担う役割の広さ**
:::
MVCではMVPよりもあなたがやらなければいけないことがかなり多いですね。
そして、この担う役割の違いこそがまさにMVCとMVPの違いだと思っています。

## ちなみにViewControllerに全てを詰め込むコードのイメージ
自炊です。全部自分でやります。


# イメージとコード上での振る舞い
さて、ここまででMVCとMVPの僕の中のイメージを紹介してきました
ここからはイメージと実際のコード上での振る舞いとを結び付けていこうと思います

## イメージ上の登場人物はコード上での誰？
### お店、シェフ
- イメージ上のお店、シェフは非常にわかりやすく、コード上ではModelクラスに当たります。MVC、MVPのそれぞれの`M`です
- Modelクラスはサーバーとの通信を行なったり、計算の処理を行なったり`見た目`の部分とは関係ないロジックを担います
- もう少し掘り下げると、Modelは画面の表示に関することは知りません。例えば、計算して返した結果を、TableViewで表示しているのか、CollectionViewで表示しているのか、アラートを表示したのかとか。つまり、`UIKitをimportしません`

## イメージ上のホールスタッフ
- ホールスタッフは`MVP`にしかいません
- コード上では`Presenter`にあたります。MVPの`P`です
- その役割は`M(Model)`と`View(V)`の仲介役です
- Viewのイベント発生を受けてModelに処理を頼みます。頼んだ処理のModelからの反応をView側がわかりやすい形で伝えます。
- Presenterも`UIKitをimoportしません`
- 
### Presenterの処理の例
- ボタンをタップしたら通信を行うという処理があったとします
- ボタンをタップされるとPresenterは「タップされた」というイベントを受け取ります
- それを受けてModelクラスに通信の依頼をします
- Modelクラスから通信の結果を受け取ります
- 受け取った結果をもとに、何を表示してほしいかをViewに伝えます
  - 成功だったら結果を表示、失敗だったらエラーを表示みたいな
  - 何を表示してほしいかを伝えるだけで、どう表示するかは指示しません(Labelなのかアラートなのかとか)

## イメージ上のあなた
イメージ上のあなたはMVCとMVPで大きく異なります。
ここが非常に大事なポイントだと思っています。

### **MVP**
- MVPにおいて`あなた`は`ViewController`です
- MVPにおける`V`にあたります
- `ViewController`がやることはPresenterにどんな処理が起きたかを伝えることと、Presenterから指示された内容を表示することです
- つまり、「ボタンがタップされた」「viewDidLoadが呼ばれた」などのイベントをPresenterに伝え、Presenterから「エラーを表示してくれ！」と言われたらエラーを表示し、「ユーザー情報を表示してくれ！」と言われたらそれも表示します。
- 「もし〇〇だったら△△して」みたいなことは基本しないはずです


### **MVC**
- 飲食店でご飯を食べる人(あなた)はコード上では`ViewController`になります。
- MVCにおける`VC`にあたります。
- フードコートであなたが自分でお店に行って注文したり、料理を運んだり、もし売り切れていたら別のお店に行ったり、ということをMVCでは`ViewController`が行います。
- `ViewController`にはサーバーへのリクエスト処理の呼び出し、通信が成功した時にどんな処理を行うか、複数の通信が失敗した時にはどんな処理を行うか、その全てが書かれます。
- MVCにおいて、`ViewController`はMVPに比べ広い範囲の処理をカバーします。
- それゆえ、処理が肥大化しがちです。

ここで説明したように、MVP、MVCではViewControllerが担う処理の広さが全く異なります。
`MVCにおけるViewControllerの処理を一部Presenterに切り取った`のがMVPという感じで捉えていいかもしれません。

# MVPを使うことのメリット
ここまでのイメージ等がうまく伝わっていれば、MVPを使うことのメリットは感じていただけるのではないでしょうか。
僕が思うMVPを使うことのメリットは大きく2つです
## 僕が思うメリット
### ViewControllerが担う責任の範囲を狭くできる
  - やるべきことが明確になるので、処理が膨らみにくくなり何がどこにあるのかがわかりやすくなる。
### Presenterが仕様書替わりになる
  - 今回の説明で仕様書がわりになると言われてもイメージしづらいかもしれませんが、どんなイベントが起きているのか、どんな処理をModelに依頼しているのかを一覧で見て処理全体の流れが追いやすくなります
※また別の機会に実際にサンプルを作って説明してみようと思います

# おわりに
いかがだったでしょう？
うまく伝わっていたら嬉しいのですが、イメージを言語化するというのは非常に難しかったです。
少しでも「あーなんかそうな感じね」と思っていただけたら嬉しいです。
次は実際にサンプルを使ってMVPの処理の流れを紹介できたらいいなと思います。
ではでは。