【社内勉強会】MVC(Model View Controller)の基礎(2017/09/14)



# 0.はじめに

------------------
## 対象者
* Web開発者

### 前提知識

* [Servletの基礎 - 勉強会スライド](http://qiita.com/yuji38kwmt/items/0221c1d386f262db89e0)
* [JSPの基礎 - 勉強会スライド](https://qiita.com/yuji38kwmt/items/efca501cc02652ed03bd)

### 目的
* Webアプリケーションフレームワークで使われているMVCを知り、フレームワークの理解を深める


-------
## 参考図書

[Software Design (ソフトウェア デザイン) 2014年 04月号 ～なぜMVCモデルは誤解されるるのか～](https://www.amazon.co.jp/Software-Design-%E3%82%BD%E3%83%95%E3%83%88%E3%82%A6%E3%82%A7%E3%82%A2-%E3%83%87%E3%82%B6%E3%82%A4%E3%83%B3-2014%E5%B9%B4/dp/B00IPONHJO)

![image](https://qiita-image-store.s3.amazonaws.com/0/37903/b511e554-39ec-eb65-8c43-e555b7c2f827.png)


-------
## 目次

1. 前提知識
2. MVCの概要
3. JavaのWebアプリケーションでMVCを理解する

-------
# 1. 前提知識

--------
## ビジネスロジック

>そのシステムにおける、システム固有の処理を行う部分……的なニュアンスだけど具体的に何を指すかは結構あいまいで、みんな何となくのフィーリングで使っている用語。

※[ビジネスロジック (business logic)とは｜「分かりそう」で「分からない」でも「分かった」気になれるIT用語辞典](http://wa3.i-3-i.info/word13666.html) 引用

>どんなプログラミング言語の仕様を見ても、APIを見てもビジネスロジックという用語は出てこないし、学術論文にも現われない。基本的には、エンタープライズ系（業務支援系）ソフトウェアを開発する企業が内部的に、もしくは顧客への販売促進のために用いる用語である。

※ [ビジネスロジック - Wikipedia](https://ja.wikipedia.org/wiki/%E3%83%93%E3%82%B8%E3%83%8D%E3%82%B9%E3%83%AD%E3%82%B8%E3%83%83%E3%82%AF) 引用

--------
## JavaBeans

ある規則にしたがって作られるJavaのクラス。
以下、必要条件の一部。

* publicで引数なしのコンストラクタが必要
* メソッドの命名規則に従わなくてはならない(getter/setterメソッドが必要など)
* シリアライズ可能でなくてはならない


```java:Book.java
public class Book implements Serializable{
	private String title;
	public String getTitle() {
		return title;
	}
	public void setTitle(String title) {
		this.title = title;
	}
        //フィールドがもっとたくさんある
}
```

以下の処理などで使われる。

* データの保持
* データベースに対しての読み込み/書き込み

※  http://brbranch.jp/blog/201510/java/javabeans/ 参考

-------
# 1. MVCの概要



-------
## MVCとは？

>MVCは、ユーザーインタフェースをもつアプリケーションソフトウェアを実装するためのデザインパターンである。

※[Model View Controller - Wikipedia](https://ja.wikipedia.org/wiki/Model_View_Controller) 引用

デザインパターンとは？
>過去のソフトウェア設計者が発見し編み出した設計ノウハウを蓄積し、名前をつけ、再利用しやすいように特定の規約に従ってカタログ化したものである。

※[デザインパターン (ソフトウェア)- Wikipedia](https://ja.wikipedia.org/wiki/%E3%83%87%E3%82%B6%E3%82%A4%E3%83%B3%E3%83%91%E3%82%BF%E3%83%BC%E3%83%B3_(%E3%82%BD%E3%83%95%E3%83%88%E3%82%A6%E3%82%A7%E3%82%A2)) 引用

--------
## MVCの中身

* Model：ビジネスロジック（アプリケーションの中心となる機能）を処理するところ
* View：表示するところ
* Controller：ユーザからのイベントを受け付け、処理と処理結果の表示を制御するところ

※『Software Design 2014/04』P18 引用

![image](https://qiita-image-store.s3.amazonaws.com/0/37903/dcdfd8b6-a72f-c6fa-4daf-ba680abca1cd.png)
※ [Struts フレームワークおよび Model/View/Controller のデザイン・パターン](https://www.ibm.com/support/knowledgecenter/ja/SSRTLW_9.0.0/com.ibm.etools.struts.doc/topics/cstrdoc001.html) 引用

--------
### MVCをJavaアプリケーションで表現した場合

* Model：Javaアプリケーション
* View：JSP
* Controller：Servlet



-------
# 3.JavaのWebアプリケーションでMVCを理解する

-------
## 環境構築

* Java8
* Tomcat8
* プロジェクト名："SampleWeb"
* 作成する機能
   - 機械学習を使って、入力した文章から感情分析の結果を表示することを想定（実際にはランダム値を表示するだけ）
   - JavaScriptは使わない（1990年代後半を想定）

【注意】たぶんサンプルコードがよくない。。。  Modelがうまく表現できていない。。。

-------
## 簡単な自己完結型JSPファイル(MVCを使わない場合）


```html:form.html
<!-- 感情分析したい文章を入力するフォーム -->
<form action="/SampleWeb/result.jsp" method="POST">
	<input type="text" name="context">
	<input type="submit">
</form>
```    

```jsp:result.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"  %>
<%
request.setCharacterEncoding("UTF-8");
String context = request.getParameter("context");
System.out.println(context);
//機械学習で、文章から感情分析の結果を計算する
//本当は1000行くらいの処理
double value = Math.random();
%>

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
</head>
<body>
  入力した文章: <%=context %>
  <br>
  感情分析の結果: <%=value %>
</body>
</html>
```

-------
### 自己完結型JSPファイルの問題点

* HTMLとJavaが混在している
    - デザイナとプログラマで担当を分けにくい
    - ソースが見づらい（入力チェックなどの記述が煩雑になっていく）
* 1ファイル1000行以上で長い
    - メンテナンス性が悪い


※ [Struts、オープン・ソースMVC実装](https://www.ibm.com/developerworks/jp/java/library/j-struts/) 参照

-------
## MVCで実装

```java:Emotion.java
//Model
//機械学習で、文章から感情分析の結果を計算する
//本当は1000行くらいの処理
public class Emotion {
    public double calculate(String context) {
		return Math.random();
	}
}
```

```java:ResultServlet.java
//Controller
@WebServlet("/ResultServlet")
public class ResultServlet extends HttpServlet {
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		request.setCharacterEncoding("UTF-8");
		String context = request.getParameter("context");
		//感情分析の値を計算
		double emotionValue = (new Emotion()).calculate(context);
                //結果をrequestに設定
		request.setAttribute("emotionValue", emotionValue);
		//Foward(遷移)
		getServletContext().getRequestDispatcher("/result2.jsp").forward(request, response);
	}
}
```

```jsp:result2.jsp
<%-- View --%>
<%@ page language="java" contentType="text/html; charset=UTF-8"  %>
<%
String context = request.getParameter("context");
double value = (double)request.getAttribute("emotionValue");
%>

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
</head>
<body>
  入力した文章: <%=context %>
  <br>
  感情分析の結果: <%=value %>
</body>
</html>
```


--------
### MVCの流れ

1. ブラウザーがサーブレットにrequestを送信
2. サーブレットはデータベースに接続された Java Bean をインスタンス化する  (先の例ではデータベースを使っていない）
3. サーブレットが JSP ページと通信
4. JSP ページが Java Bean と通信
5. JSP ページがブラウザーに応答

![image](https://qiita-image-store.s3.amazonaws.com/0/37903/dcdfd8b6-a72f-c6fa-4daf-ba680abca1cd.png)

※ [Struts フレームワークおよび Model/View/Controller のデザイン・パターン](https://www.ibm.com/support/knowledgecenter/ja/SSRTLW_9.0.0/com.ibm.etools.struts.doc/topics/cstrdoc001.html) 引用

[注意]先ほどのサンプルコードでは、2, 4番の処理が説明できていない


--------
### MVCのメリット

* 機能ごとに分離されている
    - プログラマとデザイナで分業できる
    - メンテナンス性がよい
    
--------
### [補足] JavaScriptを考慮する場合
上記の例ではJavaScriptを考慮していないが、最近のWebアプリはJavaScriptは必須。
JavaScriptを使う場合は、MVCが2段構えになる。

![image](https://qiita-image-store.s3.amazonaws.com/0/37903/55fceaee-1b16-21e1-1d03-44ffebc009b4.png)

※ [雑把の UI アーキテクチャー史(MVCからMVVMへ)](http://yohshiy.blog.fc2.com/blog-entry-215.html) 引用

--------
# 付録


-------
## MVCの歴史

* 1970～1980年代、Smalltalk言語でのGUI開発の設計指針
* 1990年代後半、MVCのサーバサイド実装としてJSP Model 2が発表

Smalltal時代のMVCと、本記事で紹介したMVCは異なる。
本記事で紹介したMVCはMVC2と呼ばれる。

---------
## UIアーキテクチャーの考え方

>MVC 以降いろいろな UI アーキテクチャーが登場しますが、 共通している目的は アプリケーションのコア部分と UI 部分を分離する ということです。

※ http://yohshiy.blog.fc2.com/blog-entry-215.html 引用


* UIは変更されやすい
* UIの変更による影響を、アプリケーションの処理が受けないようにする




-------
## MVCの難しさ
* 設計の考え方であって、正解はない
* 使っている言語によって考え方が異なる
    - JavaScript界隈ではMVCは古いみたい（https://www.infoq.com/jp/articles/no-more-mvc-frameworks）
* MVC以外にもUIアーキテクチャがある（http://yohshiy.blog.fc2.com/blog-entry-215.html）
  - MVPP 
  - H-MVC
  - MVVM


  
--------
## MVCフレームワーク

主にController部分の共通的なしくみを提供するフレームワーク。

  
<img width="200" alt="MVCフレームワーク2.png" src="https://qiita-image-store.s3.amazonaws.com/0/37903/7fd88b0f-2531-2ab6-38b0-437b3c0a8040.png">
※『Software Design 2014/04 P26』引用

以下、代表的なMVCフレームワーク(Java)

* Struts1.x
* Struts2.x
* Spring MVC
* JSF




-------
## 参考サイト

* [StrutsのMVC](https://www.ibm.com/support/knowledgecenter/ja/SSRTLW_9.0.0/com.ibm.etools.struts.doc/topics/cstrdoc001.html)

* [Struts フレームワークおよび Model/View/Controller のデザイン・パターン](https://www.ibm.com/support/knowledgecenter/ja/SSRTLW_9.0.0/com.ibm.etools.struts.doc/topics/cstrdoc001.html) 

* [開発者が知っておくべき、6つのUIアーキテクチャ・パターン](http://www.atmarkit.co.jp/fdotnet/chushin/greatblogentry_10/greatblogentry_10_01.html)
* [雑把の UI アーキテクチャー史(MVCからMVVMへ)](http://yohshiy.blog.fc2.com/blog-entry-215.html)