2012年3月19日月曜日

シングルコンテキストでの設計方法(5)

Titanium Mobileを使ったアプリ開発において、シングルコンテキストで作る際の工夫の続き、第5回です。3つのレベルに分けてJavaScriptを作る、という話で進めてます。今回は3つめとなるレベル3の作り方を取り上げますね。

 

レベル3のJavaScriptに入れるのは、MVCモデルのVCに含まれる内容です。基本的には、アプリで使う画面ごとに分けて作ります。画面ごとに2文字以上の英字を割り当てて、それを先頭に入れたファイル名としてJavaScriptを別々に用意するルールでした。たとえば「pe_prod_edit.js」ように。どのJavaScriptも、次のような形になります。

// pe_prod_edit.js (レベル3)
(function() {
    // 名前空間を別にするために、peの入れ物を用意する
    bb.pe = {};

    // 画面に表示するためのUI部品
    bb.pe.win = bb.createWinF('prod_edit');
    bb.pe.win.addEventListener('open', openWinF);
    var lblTitle = bb.createLblF(bb.pe.win, '商品情報編集', 36, 'center', 70, 'auto', 20, null);
    var lblMsg = bb.createLblF(bb.pe.win, ' ', 18, 'left', 30, 500, 700, 200);
    var btnSave = bb.createBtnF(bb.pe.win, '保存', 24, 40, 200, 100, 32);
    btnSave.addEventListener('click', saveDataF);

    // データを内部的に保持するための変数(bb.pe.を付けなくても、varで動くはずですけど...)
    bb.pe.prodScrn = [];
    bb.pe.idxProd = null;
    bb.pe.userId = null;

    // イベントを実行したり、データを加工する関数
    function openWinF() { ... }
    function saveDataF() { ... }
})();

シングルコンテキストの作り方に沿って、これもJavaScript全体を即時関数で作ります。最初がpeの入れ物で、名前空間を別々にするために用います。ここで作る変数も関数もすべてpeに登録しますから、名前が重複しないようにと調べなくて大丈夫です。

次は、画面表示に使うUI部品です。レベル1のJavaScriptで用意した関数を使い、Titanium MobileのUI部品を加えていきます。最初に作るウィンドウだけはbb.pe空間に付けますが、それ以外のUI部品はvarの変数で作って、ウィンドウにaddするだけです。この例では、addまで含んだレベル1の関数を使い、UI部品を生成しています。ウィンドウだけbb.pe空間に付けますが、「bb.pe.win」と短い表記で済むため、ソースコードが長くなりません。他の画面のウィンドウでも「win」と短い名前に統一すれば、「bb.pv.win」や「bb.ce.win」となって、同じように短い名前で使えます。

続いて、このJavaScript内で使うデータ用変数のうち、値を継続して保持する必要がある変数だけ、bb.pe空間に付けます。これも前回と同じで、おまじない的に付けています。本来は、変数がどこかで必ず参照されていて、bb.pe空間に付けなくても動作するはずなのですが、、、、。前回と同様に苦肉の策なので、この部分だけは非推奨ということで。

保持して置く場所として、変数以外に画面表示も使えます。ユーザーが選んだ値は、画面上のUI部品に保持しています。その値を調べることで、変数に持つ必要はなくなります。また、UI部品が保持している値がそのまま使えないときでも、UI部品に新しいプロパティを加えて、そのプロパティに値を保持させる方法が使えます。どちらの方法でも、JavaScript内の変数を持たなくても、持ったと同じ効果が得られます。こういう方法も利用して構わないのではないでしょうか。

レベル3で作る関数は、他のJavaScriptから呼ばれるものは、めったにありません。他の画面と共有する関数はレベル1として作り、その関数へウィンドウやボタンの情報を渡して動かす形にします。そうすると、このJavaScript内で使う関数しか残らないのです。したがって、どれも普通の関数「function func_name() { ... }」の形で作ることになります。

 

外から呼ばれる関数がないので、ここで作った関数を使うJavaScriptの例もありません。当然ですね。逆に、ここの関数内では、レベル1やレベル2で作った関数を多用します。それらを使って、データの作成、加工、保存を実現します。また、新しく作成するデータは、画面に入力した値を取り込んで利用します。

画面上でのエラーチェック機能は、このJavaScriptに入れます。ただし、エラーを判定する処理だけは、レベル1またはレベル2に関数として用意します。その関数を呼び出してエラーかどうか判定し、判定結果を画面に表示します。エラー判定関数をレベル1に作るか、レベル2に作るかは、エラーチェック内容によって決まります。適用業務に関係するならレベル2に、関係しないならレベル1に作るのが基本です。特定の形式の文字列かどうかのチェックなら、適用業務に関係ないのでレベル1の関数となります。逆に適用業務上のエラーチェックは、該当するデータのレベル2JavaScriptに入れます。データごとに、関係するロジックがレベル2の該当箇所に集まるというわけです。

より良い構造で作るのであれば、レベル1のエラーチェック関数を、レベル3から直接呼ばない形が理想です。たとえ特定の形式の文字列かどうかのチェックであっても、チェック目的を表す名前でレベル2に関数を用意し、その中でレベル1のエラーチェック関数を呼ぶようにします。レベル1の関数名は、数値かどうかのチェックを意味する名前に、レベル2の関数名は、どのデータ項目をチェックするか表す名前になるでしょう。このように作れば、レベル2のJavaScriptの中に、エラーチェック内容がすべて集まる形に仕上げられます。

 

こんな感じで作り進みます。作業の順序としては、名前空間の入れ物を用意して、UI部品を作り、内部保持の変数を加えて、関数を書いていく感じですね。必要に応じて、UI部品の表示位置を調整したり、関数の修正や追加を行います。

以上で、3つのレベルの作り方を紹介し終わりました。ここまで書いてきて、レベルという表現(言葉)が適切だったのか、少し迷ってます。JavaScriptを3層構造に分けるという意味で、レベルかなと考えましたが、はたして良かったかどうか。適切な言葉って、意外に難しいですね。

シングルコンテキストでの作り方を調べたとき、将来的に「Ti.include」が使われなくなって、「require」を使う話がありました。最後に、「require」の話を別投稿で取り上げましょう。

0 件のコメント:

コメントを投稿