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


はじめに

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

図解!どのサイトを見てもわからなかった人のためのMVC
MVCフレームワークって?
MVCとかWAFとかを最初に理解するにあたってイメージしたこと

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

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

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

SAPUIの場合

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

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

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

{ 
    "product" : {
        "name" : "pumpkin",
        "price": 150
    }
}

Model, View, Controllerのシンプルなアプリケーションを作ってみる

manifest.jsonファイルなどを使わない、シンプルなアプリケーションを作ってみます。

ゴール

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

作成するファイル

  • index.html
  • Model
  • View
  • Controller

フォルダ構成

フォルダ構成は以下のようになります。

index.html

まずはbootstrapの部分を作ります。(bootstrapについてはこちら

<!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に配置するという内容のコードを追加します。

            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つだけです。

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

View

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

<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ファイルを作成します。メニューの料理を作ってお客さんに渡します。

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メソッドにより、このアプリケーションでモデルにアクセスできるようにします。

結果

本日の定食がお客さんに届きました。

余談

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

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);*/
            }
        });
});

結果

定食が消えてしまいました。やはり、モデルは料理(インスタンス化)しないと使えないことがわかりました。

まとめ

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