モデルインターフェース
モジュールパス: /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() {}
}
export { MyModel1 };
class MyModel2 extends AlierModel {
func2Impl() {}
}
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 から関数の場所を指定します。省略した場合は local となります。 |
|
class |
AlierModel の派生クラスです。locale が local の場合のみ有効です。上位のタグで指定されていなければ必ず指定してください。 |
|
path |
✅ | 登録する関数を指定します。locale が local の場合は class から対象を参照するためのパスです。native の場合は関数名です。 |
使用例
class MyFuncModel1 extends AlierModel {
func1Impl() { return "function1" }
}
class MyFuncModel2 extends AlierModel {
func2Impl() { return "function2" }
}
class MyFuncModel3 extends AlierModel {
func3Impl() { return "function3" }
}
<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" />
<function name="func3" path="func3Impl" />
</unit>
</unit>
</interface>
</model>
let result1 = Alier.Model.unit1.func1();
let result2 = Alier.Model.unit1.unit2.func2();
let result3 = Alier.Model.unit1.unit2.func3();
console.log(result1); // "function1"
console.log(result2); // "function2"
console.log(result3); // "function3"
<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() メソッドを登録します。 |
使用可能なメソッド
-
MessagePorter
にlistener
を登録するメソッドです。 -
MessagePorter
からlistener
を削除するメソッドです。 -
MessagePorter
に登録されたlistener
にメッセージを送るメソッドです。このメソッドはpostEnable
属性が指定された時のみ使用出来ます。
使用例
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" class="MyEventModel1" path="event1Impl" postEnable="" />
<message-porter name="event2" 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 から登録するオブジェクトを参照するためのパスです。 |
使用可能なメソッド
-
バインドする対象のオブジェクトを登録するメソッドです。
使用例
class MyObservableObject extends AlierModel {
observableObjectImpl = new ObservableObject({ foo: 2 }, false);
}
<model>
<import path="observableObjectModel.js" />
<interface>
<observable-object name="MyObservableObject" 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 から登録するオブジェクトを参照するためのパスです。 |
使用可能なメソッド
-
バインドする対象の配列を登録するメソッドです。
使用例
class MyObservableArray extends AlierModel {
observableArrayImpl = new ObservableArray({ bar: 0 }, { twoWay: true, initCount: 3});
}
<model>
<import path="observableArrayModel.js" />
<interface>
<observable-array name="myObservableArray" 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 , remote から登録するオブジェクトのある場所を指定します。省略した場合は local となります。 |
|
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" 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" 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 を指定します。省略した場合は local となります。 |
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の構文定義を参照してください。