【SAPUI5】SAPUI5のMVCをレストランに例えると

##はじめに
SAPUI5をしばらく触ってみて、MVCはレストランに似ていると感じました。
MVC、レストランと検索すると以下のようなページが出てきたので、そう感じるのは私だけではないようです。

[図解！どのサイトを見てもわからなかった人のためのMVC](https://qiita.com/a24dai/items/5fddbffdbb05b2ed2894)
[MVCフレームワークって？](https://qiita.com/morikuma709/items/3e7964482414666672c8)
[MVCとかWAFとかを最初に理解するにあたってイメージしたこと](https://qiita.com/s-age/items/fe4b321c5445341dfd6e)

これらのページでは、Model, View, Controllerは以下のものに例えられています。

- Model: コックさん
- View: ウェイター or お客さん or 料理
- Controller: ホールスタッフ

共通してるのは、Modelが処理ロジックであり、Controllerはデータをどこに届けるかを決める役割をしているという点です。

##SAPUIの場合
SAPUI5ではModelとはデータであり、処理ロジックはControllerが担います。よって、以下のイメージのほうが近いのではないかと考えます。
ここではデータ=料理とします。

- Model: メニュー・・・データの構造や内容を定義したもの
- View: お客さん・・・データを消費する
- Controller: コックさん・・・モデルをインスタンス化してビューに渡す

![image.png](https://qiita-image-store.s3.amazonaws.com/0/276021/a7c19442-d318-bfa0-d880-738dfc4181ba.png)

以下はシンプルなJSONモデルの例です。データの中身も見えていてそのまま使えそうですが、実は**モデルはインスタンス化しないと使うことができない**のです。（manifest.jsonを利用することによりインスタンス化を意識しないで済みますが）
そんなわけで、「Model=メニュー」のほうがSAPUI5ではしっくりくると思いました。

```json
{ 
	"product" : {
		"name" : "pumpkin",
		"price": 150
	}
}
```
##Model, View, Controllerのシンプルなアプリケーションを作ってみる
manifest.jsonファイルなどを使わない、シンプルなアプリケーションを作ってみます。

###ゴール
「本日の定食」を表示する画面を作ります。

###作成するファイル
- index.html
- Model
- View
- Controller

###フォルダ構成
フォルダ構成は以下のようになります。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/276021/bdee3685-c769-57ea-b9b8-5444eea8cfa2.png)


###index.html
まずはbootstrapの部分を作ります。（bootstrapについては[こちら](https://qiita.com/tami/items/b9dca653f1d076e19757)）

```html
<!DOCTYPE html>
<html>
	<head>
		<!-- bootstrap of SAP UI5 -->
		<script 
			id="sap-ui-bootstrap"
			src="https://sapui5.hana.ondemand.com/resources/sap-ui-core.js"
			data-sap-ui-libs="sap.m, sap.ui.layout"
			data-sap-ui-theme="sap_bluecrystal"
			data-sap-ui-xx-bindingSyntax="complex"
			data-sap-ui-resourceroots='{
				"restaurant": "./"
			}'>
		</script>
		<script>
			//ビューを生成する
		</script>
	</head>
	<body class="sapUiBody">
		<div id="content"></div>
		
	</body>
</html>
```

「ビューを生成する」のコメントのところに、"customer.view.xml"のビューをbodyに配置するという内容のコードを追加します。

```javascript
			var oFirstView = new sap.ui.view("idCustomer", {
				viewName: "restaurant.view.customer",
				type: sap.ui.core.mvc.ViewType.XML
			});
			oFirstView.placeAt("content");
```

###Model
本日の定食のモデル(menu.json)を作成します。簡単にするためにメニューは1つだけです。

```json
{
	"menu": 
		{ 
			"name": "焼き魚定食",
			"price": 850,
			"calories": 500
		}
}
```

###View
定食を待っているお客さんを表すビュー(customer.view.xml)を作成します。
Textコントロールにメニューの項目をバインドします。

```xml
<mvc:View 
	xmlns:core="sap.ui.core" 
	xmlns:mvc="sap.ui.core.mvc" 
	xmlns="sap.m"
	xmlns:f="sap.ui.layout.form"
	controllerName="restaurant.controller.customer">
	<App id="idApp">
		<Page title="本日の定食">
			<content>
				<f:SimpleForm>
					<f:content>
						<Label text="メニュー"></Label>
						<Text text="{/menu/name}"></Text>
						<Label text="価格"></Label>
						<Text text="{/menu/price}"></Text>
						<Label text="カロリー"></Label>
						<Text text="{/menu/calories}"></Text>						
					</f:content>
				</f:SimpleForm>				
			</content>
		</Page>
	</App>
</mvc:View>
```
###Controller
customer.controller.jsファイルを作成します。メニューの料理を作ってお客さんに渡します。

```javascript
sap.ui.define([
	"sap/ui/core/mvc/Controller",
	"sap/ui/model/json/JSONModel"
	], function(Controller, JSONModel){
		return Controller.extend("restaurant.controller.customer", {
			onInit: function(){
				//モデルをインスタンス化（メニューから料理を作る）
				var oModel = new JSONModel();
				oModel.loadData("model/menu.json");
				//モデルに名前を設定（名無しなのでデフォルトモデルになる）
				sap.ui.getCore().setModel(oModel);
			}
		});
});
```
まずは空のJSONモデルのインスタンスを作って、そこにデータを流し込みます。
setModelメソッドにより、このアプリケーションでモデルにアクセスできるようにします。

###結果
本日の定食がお客さんに届きました。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/276021/3862d568-86ed-1248-cfe7-5ab572aa5dc1.png)

##余談
ところで、「モデルを使うためにコントローラーって本当にいるの？」って思いませんか？
ビューでデータのパスを指定しているし、そのまま読み込めそうな感じがします。
そこで、コントローラの処理をコメントアウトしてみます。

```javascript
sap.ui.define([
	"sap/ui/core/mvc/Controller",
	"sap/ui/model/json/JSONModel"
	], function(Controller, JSONModel){
		return Controller.extend("restaurant.controller.customer", {
			onInit: function(){
/*				//モデルをインスタンス化（メニューから料理を作る）
				var oModel = new JSONModel();
				oModel.loadData("model/menu.json");
				//モデルに名前を設定（名無しなのでデフォルトモデルになる）
				sap.ui.getCore().setModel(oModel);*/
			}
		});
});
```

###結果
定食が消えてしまいました。やはり、モデルは料理（インスタンス化）しないと使えないことがわかりました。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/276021/6172ce6a-5f3b-7aa0-f5fc-3a40a7786071.png)

##まとめ

- 一般的なMVCと、SAPUI5のMVCではModelの役割が異なる
- SAPUI5ではデータを定義した「メニュー」（あるいはカタログ）のようなもの
- Modelは定義するだけでは使えず、インスタンス化する必要がある