モデルインターフェース

モジュールパス: /alier_sys/SetupInterface.js

概要


モデルインタフェースを構築します。

モデルインターフェースについて

Alierではアプリケーションの構成について、ModelとViewの二つからなると考えています。Modelとはアプリが持つ本質的な機能を指します。データの保存や編集などの、アプリに必要なデータの管理を行います。Viewとは画面表示やユーザのインタラクションを受けとる機能です。Modelが持っているデータをユーザが閲覧できるように画面に表示します。

そのためModelとViewの間ではデータのやり取りが発生し、連携をとる必要があります。すると例えば、Modelの仕様変更に伴いViewの方も修正が必要になる、といった追加の作業が発生します。このような問題を解決するために、Alierではモデルインターフェースという機能を提供しています。

モデルインターフェースは、アプリケーション全体からModel機能にアクセスするための機能です。Modelのインターフェースと実装を分離することで、ViewはModelの実装を知ることなくModelを利用できます。

モデルインターフェースの定義はXMLで記述されます。このXMLで記述したインターフェース定義を setupModelInterface() 関数などに渡すことで、モデルインターフェースオブジェクトが作成されます。読み込まれたインターフェースは Alier.Model の下に割り当てられ、グローバルなオブジェクトとしてアプリ全体から利用可能になります。

モデルインターフェースの定義は以下のようにXMLで記述します。

<model>
  <import path="MyModel1.js" />
  <import path="MyModel2.js" />
  <interface>
    <unit name="unit1">
      <function name="func1" locale="local" class="MyModel1" path="func1Impl" />
      <unit name="unit2" class="MyModel2">
        <function name="func2" locale="local" path="func2Impl" />
      </unit>
    </unit>
  </interface>
</model>

このモデルインターフェース定義のXMLファイルを setupModelInterface() や setupModelInterfaceFromText() 関数に渡すとモデルインターフェースオブジェクトが作成されます。モデルインターフェースオブジェクトは、Alier.Model.<unit name>.<function name>() のように Alier.Model 下に XML の name 属性と同名のプロパティを持つオブジェクトとして構築されます。

//  setupModelInterface は AlierFramework.js によりグローバルに展開済みです。
//  インターフェースの構築
await setupModelInterface({ xml:"interface.xml" });

以下のモデルに対して、モデルインターフェースを用いてビューからモデルにアクセスできるようになります。

class MyModel1 extends AlierModel {
    func1Impl() {}
}
await Alier.export({ MyModel1 });
class MyModel2 extends AlierModel {
    func2Impl() {}
}
await Alier.export({ MyModel2 });
//  インターフェースを使用したModelの呼び出し
//  MyModel1 の func1Impl() をインタフェース経由で呼ぶ
Alier.Model.unit1.func1();
//  MyModel2 の func2Impl() をインタフェース経由で呼ぶ
Alier.Model.unit1.unit2.func2();

タグ一覧


モデルインターフェースの定義で使用可能なタグは以下の通りです。

タグ 説明
<model> XML のルート要素のタグです。
<import> インポートするモジュールを宣言するタグです。
<interface> インターフェース定義であることを示すタグです。
<unit> 関数などのインターフェースをまとめるためのタグです。
<function> 関数を表すタグです。
<arg> 関数の引数を定義するタグです。
<message-porter> メッセージポーターのタグです。
<observable-object> 監視可能なオブジェクトのタグです。
<observable-array> 監視可能な配列のタグです。
<restful-object> REST スタイルのオブジェクトのタグです。
<get> get()メソッドの引数を定義するタグです。
<post> post()メソッドの引数を定義するタグです。
<put> put()メソッドの引数を定義するタグです。
<delete> delete()メソッドの引数を定義するタグです。

<model>

XML のルート要素のタグです。

この中にインポートするモジュールのファイルとインターフェース定義を記述します。

このタグの下には以下のタグを置いてください。

タグ 個数制限
<import> なし
<interface> 1

使用可能な属性はありません。


<import>

インポートするモジュールを宣言するタグです。

インターフェースを構築する際に、 <interface> 以下のタグで class 属性に AlierModel の派生クラスの名称を指定する必要があります。指定したクラスをモジュールとして使用できるようにするため、このタグでインポートを行います。そのため、モジュールである AlierModel の派生クラスのファイルパスをこのタグの path 属性に指定してください。ファイルパスの指定方法はファイル名を指定する際のルールに則ってください。

このタグは <model> タグ直下に置いてください。このタグの下に置けるタグはありません。

また、このタグには以下の属性を指定してください。

属性 必須 説明
path ✅ モジュールのファイルパスを指定します。

<interface>

インターフェース定義であることを示すタグです。

このタグは <model> タグ直下に必ず1つだけ置いてください。また、このタグの下には以下のタグを配置できます。

タグ 個数制限
<unit> なし
<function> なし
<message-porter> なし
<observable-object> なし
<observable-array> なし
<restful-object> なし

また、このタグには以下の属性を指定してください。

属性 必須 説明
class インターフェース定義全体で AlierModel の派生クラスが一つしかない場合はここで class 属性を設定することもできます。

<unit>

関数などのインターフェースをまとめるためのタグです。

一つの集まりとして扱いたいインターフェースをこの下に置いて使用してください。

このタグは子要素に自身を入れて入れ子にして使用可能です。

このタグの下には以下のタグを配置できます。

タグ 個数制限
<unit> なし
<function> なし
<message-porter> なし
<observable-object> なし
<observable-array> なし
<restful-object> なし

また、このタグには以下の属性を指定してください。

属性 必須 説明
name ✅ グループの名称です。
class グループ内で AlierModel の派生クラスが1つしかない場合にそのモデルクラスを設定できます。

<function>

関数を表すタグです。

関数をインターフェースとして登録します。この関数には引数としてオブジェクトを1つ渡すことができます。この引数オブジェクトで受け入れるプロパティ名と型を子要素の <arg> タグで定義することができます。

このタグの下には以下のタグを配置できます。

タグ 個数制限
<arg> なし

また、このタグには以下の属性を指定してください。

属性 必須 説明
name ✅ 関数呼び出し時の名前です。
locale ✅ local, native から関数の場所を指定します。
class AlierModel の派生クラスです。locale が local の場合のみ有効です。上位のタグで指定されていなければ必ず指定してください。
path ✅ 登録する関数を指定します。locale が local の場合は class から対象を参照するためのパスです。native の場合は関数名です。

使用例

class MyFuncModel1 extends AlierModel {
    func1Impl() { return "function1" }
}
class MyFuncModel2 extends AlierModel {
    func2Impl() { return "function2" }
}
<model>
    <import path="funcModel.js" />
    <interface>
        <unit name="unit1">
            <function name="func1" locale="local" class="MyFuncModel1" path="func1Impl" />
            <unit name="unit2" class="MyFuncModel2">
                <function name="func2" locale="local" path="func2Impl" />
            </unit>    
        </unit>
    </interface>
</model>
let result1 = Alier.Model.unit1.func1();
let result2 = Alier.Model.unit1.unit2.func2();
console.log(result1);   // "function1"
console.log(result2);   // "function2"

<arg>

関数の引数を定義するタグです。

関数に渡す引数を定義します。モデルインターフェースの関数に渡す引数はオブジェクトを一つ渡す形式で統一されています。そのオブジェクトのプロパティと型を定義します。

このタグの子要素はありません。

また、このタグには以下の属性を指定してください。

属性 必須 説明
name ✅ 引数のプロパティ名です。
type ✅ 引数のプロパティの型です。

使用例

class MyFuncModel1 extends AlierModel {
    func1Impl(obj) {
        let text = obj.text;
    }
}
class MyFuncModel2 extends AlierModel {
    func2Impl(obj) {
        let num = obj.num;
        let bool = obj.bool;
    }
}
<model>
    <import path="funcModel.js" />
    <interface>
        <unit name="unit1">
            <function name="func1" locale="local" class="MyFuncModel1" path="func1Impl">
                <arg name="text" type="string" />
            </function>
            <unit name="unit2" class="MyFuncModel2">
                <function name="func2" locale="local" path="func2Impl">
                    <arg name="num" type="number" />
                    <arg name="bool" type="boolean" />
                </function>
            </unit>
        </unit>
    </interface>
</model>
Alier.Model.unit1.func1({ text:"some text" });
Alier.Model.unit1.unit2.func2({ num:0, bool:true });

<message-porter>

イベント通知機構を提供する MessagePorter のタグです。

MessagePorter をインターフェースに登録します。

このタグに子要素はありません。

また、このタグには以下の属性を指定してください。

属性 必須 説明
name ✅ メッセージポーター呼び出し時の名前です。
locale ✅ local を指定します。
class AlierModel の派生クラスです。locale が local の場合のみ有効です。上位のタグで指定されていなければ必ず指定してください。
path ✅ 登録する MessagePorter を指定します。locale が local の場合は class から対象を参照するためのパスです。
postEnable post() メソッドをモデルインターフェースに登録するか否かを指定します。この属性を定義していれば post() メソッドを登録します。

使用可能なメソッド

使用例

class MyEventModel1 extends AlierModel {
    event1Impl = new EventHandler();
}
class MyEventModel2 extends AlierModel {
    event2Impl = new EventHandler();
    event() {
        // eventメソッドが呼ばれるとコンソールログに"any-model-param"と表示される
        this.event2Impl.post(Alier.message("0", "any-event", "any-model-param"));    
    }
}
<model>
    <import path="eventModel.js" />
    <interface>
        <message-porter name="event1" locale="local" class="MyEventModel1" path="event1Impl" postEnable="" />
        <message-porter name="event2" locale="local" class="MyEventModel2" path="event2Impl" />
    </interface>
</model>
function listener(param) {
    console.log(param.param)
}
Alier.Model.event1.addListener(listener);
Alier.Model.event2.addListener(listener);

// コンソールログに"any-event"と表示される
Alier.Model.event1.post(Alier.message("0", "any-event", "any-param"));  

// postEnable属性を指定していないため無効
Alier.Model.event2.post(Alier.message("0", "any-event", "any-param"));  

<observable-object>

監視可能なオブジェクトである ObservableObject のタグです。

ObservableObject の Model と View で値の同期を行うインターフェースを登録します。ObservableObject には、同期の対象を登録する bindData というメソッドがあり、モデルインターフェースにはこのメソッドが登録されます。

このタグに子要素はありません。

また、このタグには以下の属性を指定してください。

属性 必須 説明
name ✅ 監視可能なオブジェクトの呼び出し時の名前です。
locale ✅ local のみ指定可能です。
class AlierModel の派生クラスです。上位のタグで指定されていなければ必ず指定してください。
path ✅ class から登録するオブジェクトを参照するためのパスです。

使用可能なメソッド

  • bindData()

    バインドする対象のオブジェクトを登録するメソッドです。

使用例

class MyObservableObject extends AlierModel {
    observableObjectImpl = new ObservableObject({ foo: 2 }, false);
}
<model>
    <import path="observableObjectModel.js" />
    <interface>
        <observable-object name="MyObservableObject" locale="local" class="MyObservableObject" path="observableObjectImpl" />
    </interface>
</model>
let target = { foo: 1 };
Alier.Model.MyObservableObject.bindData(target);
console.log(target.foo);  // 2

<observable-array>

監視可能な配列である ObservableArray のタグです。

ObservableArray の Model と View で値の同期を行うインターフェースを登録します。ObservableArray には、同期の対象を登録する bindData というメソッドがあり、モデルインターフェースにはこのメソッドが登録されます。

このタグに子要素はありません。

また、このタグには以下の属性を指定してください。

属性 必須 説明
name ✅ 監視可能な配列の呼び出し時の名前です。
locale ✅ local のみ指定可能です。
class `AlierModel の派生クラスです。上位のタグで指定されていなければ必ず指定してください。
path ✅ class から登録するオブジェクトを参照するためのパスです。

使用可能なメソッド

  • bindData()

    バインドする対象の配列を登録するメソッドです。

使用例

class MyObservableArray extends AlierModel {
    observableArrayImpl = new ObservableArray({ bar: 0 }, { twoWay: true, initCount: 3});
}
<model>
    <import path="observableArrayModel.js" />
    <interface>
        <observable-array name="myObservableArray" locale="local" class="MyObservableArray" path="observableArrayImpl" />
    </interface>
</model>
let targetList = [{ bar: 1 }, { bar: 2 }, { bar: 3 }]
Alier.Model.myObservableArray.bindData(targetList);

<restful-object>

REST スタイルのオブジェクトのタグです。

Model と View でデータのやり取りを行うインターフェースを登録します。このインターフェースは4つのメソッド get(), put(), post(), delete() を持ちます。

このタグの下には以下のタグを配置できます。

タグ 個数制限
<get> 0~1
<post> 0~1
<put> 0~1
<delete> 0~1

また、このタグには以下の属性を指定してください。

属性 必須 説明
name ✅ レストフルオブジェクトの呼び出し時の名前です。
locale ✅ local, native, remote から登録するオブジェクトのある場所を指定します。
class local の場合は AlierModel の派生クラスを指定します。上位タグで指定していなければ必ず指定してください。remote の場合は使用しません。
path local の場合は class からレストフルオブジェクトを参照するためのパスです。 native の場合は関数名です。remote の場合は使用しません。
uri remote の場合にサーバーのアドレスを指定します。
auth 認証オブジェクトの id を指定します。locale が remote の場合に使用します。

使用例

class MyRestfulModel1 extends AlierModel {
    restful1Impl = { get(){return 0} };
}
<model>
    <import path="restfulObjectModel.js" />
    <interface>
        <restful-object name="restful1" locale="local" class="MyRestfulModel1" path="restful1Impl" />
        <restful-object name="restful2" locale="remote" auth="any-id" uri="http://~~~/~~~/~~~" />
    </interface>
</model>
AgentRepository.registerAgent(new AuthAgent({ id: "any-id", protocols: new AnyProtocol() }));
let result1 = Alier.Model.restful1.get();
let result2 = Alier.Model.restful2.get();
console.log(result1);   // 0
console.log(result2);   // { foo:"bar" }

<get>

get() メソッドの引数を定義するタグです。

get() メソッドに渡す引数を定義します。モデルインターフェースの関数に渡す引数はオブジェクトを一つ渡す形式で統一されています。そのオブジェクトのプロパティと型を定義します。

このタグの子要素はありません。

また、このタグには以下の属性を指定してください。

属性 必須 説明
name ✅ 引数のプロパティ名です。
type ✅ 引数のプロパティの型です。

使用例

class MyRestfulModel1 extends AlierModel {
    id = "any-id";
    status = 1;
    restful1Impl = { get(obj){return obj.id == this.id ? this.status : 0} };
}
<model>
    <import path="restfulObjectModel.js" />
    <interface>
        <restful-object name="restful1" locale="local" class="MyRestfulModel1" path="restful1Impl">
            <get name="id" type="string" />
        </restful-object>
    </interface>
</model>
let result1 = Alier.Model.restful1.get({ id:"any-id" });

<post>

post() メソッドの引数を定義するタグです。

post() メソッドに渡す引数を定義します。モデルインターフェースの関数に渡す引数はオブジェクトを一つ渡す形式で統一されています。そのオブジェクトのプロパティと型を定義します。

このタグの子要素はありません。

また、このタグには以下の属性を指定してください。

属性 必須 説明
name ✅ 引数のプロパティ名です。
type ✅ 引数のプロパティの型です。

<put>

put() メソッドの引数を定義するタグです。

put() メソッドに渡す引数を定義します。モデルインターフェースの関数に渡す引数はオブジェクトを一つ渡す形式で統一されています。そのオブジェクトのプロパティと型を定義します。

このタグの子要素はありません。

また、このタグには以下の属性を指定してください。

属性 必須 説明
name ✅ 引数のプロパティ名です。
type ✅ 引数のプロパティの型です。

<delete>

delete() メソッドの引数を定義するタグです。

delete() メソッドに渡す引数を定義します。モデルインターフェースの関数に渡す引数はオブジェクトを一つ渡す形式で統一されています。そのオブジェクトのプロパティと型を定義します。

このタグの子要素はありません。

また、このタグには以下の属性を指定してください。

属性 必須 説明
name ✅ 引数のプロパティ名です。
type ✅ 引数のプロパティの型です。

属性

タグには以下の属性から適切なものを設定する必要があります。

属性 説明
name インターフェース名もしくは引数のプロパティ名の属性です。
locale インターフェースが接続する Model の所在を指定する属性です。値は local, native, remote のいずれかを取ります。Model を JavaScript で記述していれば local を指定します。Swift や Kotlin であれば native を指定します。サーバー上にある場合は remote を指定します。
class インターフェースを提供する Model のクラス名を指定する属性です。指定するクラスは AlierModel の派生クラスでなければなりません。class属性で指定した値は下位のタグに伝播していきます。<function> のような呼び出し可能なタグや <message-porter> のようなメソッドを持つタグで呼び出しを実行したとき、タグ自身に class 属性があればその値が使用されます。もしなければ、上位タグの class 属性を参照します。
path インターフェースとなる Model のプロパティを指定する属性です。locale が local の時は必ず指定してください。また、<import> タグの場合にはファイルパスを指定します。
uri データの送り先を指定する属性です。<restful-object> の locale が remote の時のみ使用します。
auth 認証オブジェクトの id を指定する属性です。<restful-object> の locale が remote の時のみ使用します。
type 引数の型を指定する属性です。

関数


setupModelInterface()

  • XML ファイルをパースし、モデルインターフェースを構築します。

setupModelInterfaceFromText()

  • XML 文字列をパースし、モデルインターフェースを構築します。

XML 構文定義


XMLの構文定義を参照してください。