2012年3月17日土曜日

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

Titanium Mobileを使い、iPad上で動く業務アプリを作りました。Titanium Mobileを使う最初のアプリだったので、どのような内部構造にするか事前に調べました。出てきたキーワードが、シングルコンテキストです。シングルコンテキストながら、個々のプログラムが影響を及ぼしにくく作るのが、今後の主流になりそうだと感じました。何人もの人が主張しているほど、人気の作り方のようです。正しい起源は知りませんが、tweetaniumというサンプルがもとになっているようでした。

詳しい内容は、もう何人もの方が書かれているので、ここで書く必要はないでしょう。「Titanium Mobile」と「シングルコンテキスト」で検索してみてください。たくさんのページが出てきますから、その中から何ページかを読めば理解できるでしょう。いちおう簡単に説明すると、次のようになります。「Ti.include」で読み込みながらシングルコンテキストで作るものの、特別なグローバル・オブジェクトを用意し、それに付加する形でウィンドウや関数を作ります。付加するプログラムは内容で分割し、それぞれ違う名前の場所に加えることで、別々の名前空間を実現します。また、ぞれぞれのプログラム全体を、即時関数として作るのも大きな特徴です。なかなか賢い方法ですね。

 

さて、ここからが本題です。私が作った業務アプリも、同じ構造を採用しました。ただし、「シングルコンテキスト+即時関数」という考え方だけでは、アプリ全体をすっきりした構造にするは不十分でした。さらなる工夫が必要で、その工夫を紹介します。

今回の業務アプリの内容から、特別なグローバル・オブジェクトを「bb」としました。この「bb」オブジェクトにウィンドウや関数を追加するわけですが、どのように分割するかが悩むところです。iPadアプリですから、画面に表示した内容にタッチしながら、作業を進めることになります。何種類かの画面があって、画面ごとに機能が分割されています。画面ごとに分割するのは、理解しやすくて作りやすい考え方でしょう。また、扱うデータごとに分割するという考え方もあります。商品データ、顧客データ、販売データなどによる分割です。加えて、アラートや確認ダイアログのように、システム全体で使うプログラム機能もあるでしょう。この3つを全部入れて、3レベルに分割したら良いと考えました。整理すると、レベル1がプログラム機能、レベル2が扱うデータに関わる処理、レベル3が画面に関係する機能です。

せっかく3レベルに分けたのですから、それらを「bb」に付加するときのルールも用意しました。レベル1では、そのまま追加する。レベル2では、1文字の英字で追加する。レベル3になると、2文字の英字で追加するという具合です。具体的な例を書くと、次のようになります。

// 特別なグローバル・オブジェクト
var bb = {};

// レベル1
(function() {
    bb.alertSp = function(msg) { ... }
})();

// レベル2
(function() {
    bb.c = {};
    bb.c.getName = function(id) { ... }
})();

// レベル3
(function() {
    bb.pe = {};
    bb.pe.strNameTable = [];
})();

加える文字は、0〜2文字と少なくしてあります。文字数が少ないことで、記述しやすくなるのを狙っているからです。参照される頻度は、レベル1とレベル2が圧倒的に多いため、この2つをより少ない文字数に割り当てたわけです。

レベル2と3の文字には、それぞれ意味を持たせたほうが理解しやすくなります。レベル2では、扱うデータごとに異なる文字を割り当てるのですから、データ名の先頭文字が適しています。商品情報ならproductsのpを、顧客の情報ならcustomerのcを、販売情報ならsalesのsをという具合に。レベル3も同様で、画面に対応させた機能を英字2文字に略した言葉が適しています。商品情報の編集画面なら、英語での一般的な表現と言うことでedit productsを略したepとしたくなるでしょう。しかし、お薦めなのは、逆順のpeです(理由は後述)。こうすると多くの場合、1文字目が作業対象を、2文字目が作業の種類を表すことになります。それが理解できると、たった2文字なのに、何をどうしている画面なのか予想できるようになります。もし2文字では足りないと感じる場合は、このレベルを3文字にする方法もありまし、2文字と3文字の混在でも構いません。好きずきで選んでください。

とは言うものの、pやsは競争率が高く、どうしても衝突しがちです。そんな場合は、もっとも重要なものをpやsに割り当てて、それ以外は別な英字に割り当てます。また、環境設定(pref)のように、すべてのアプリで使いそうな機能は、あまり使いそうもない英字(zなど)を割り当てて、アプリが変わっても同じ文字を割り当てられるように決めておきたいものです。

 

分割方法と割り当て文字が決まったら、それに従ってJavaScriptを作成します。当然、対応文字ごとにファイルも分割します。その際に大事なのが、ファイル名です。ファイル名の先頭に、割り当てた文字を入れるのです。たとえば、商品情報を扱うJavaScriptなら、ファイル名を「products.js」とするのではなく「p_products.js」とします。同様にレベル3でも、「prod_edit.js」ではなく「pe_prod_edit.js」というように。このように分かりやすい内容なら先頭に付ける意味はありませんが、「z_pref.js」や「ez_pref_edit.js」のような名前なら価値が大きいでしょう。

これら以外にも、ヘルプのような特別な画面もあります。このような画面でも、グローバル・オブジェクトに加える以上は何らかの2文字が必要です。作業名として意味のある1文字を無理して作り出そうとすると、無駄に悩んでしまいます。ここは気軽に、helpを単純に2文字に略した「hp_help.js」で構わないと思います。何事も柔軟にですね。

割り当て文字をファイル名に入れると、ファイル名の一覧表にも表示されます。その結果、割り当てた文字を否応なく記憶されられてしまいます。頑張って覚えるという感覚ではありません。何の努力もせず覚えてしまいますから、「bb.h」とか「bb.ez」とかが探す必要もなくなります。だからこそ、ファイル名に含めることが大事なのです。また、ファイル名を見ただけで、使っていない文字並びも簡単に分かります。新しい2文字を追加する際にも、今まで使った2文字を調べる必要はありません。

さて、2文字の場合、ep(edit_prod)ではなくpe(prod_edit)にした理由の話です。作業対象を前に置くと、ファイル一覧にファイル名が並んだとき、同じ対象を扱うJavaScriptが連続して並びます。ファイル一覧が自動的に整理された感じに見え、管理しやすくなります。というわけで、作業対象を前に置いた割り当て方法を強くお薦めします。

base.js
c_customer.js
ce_customer_edit.js
cv_customer_view.js
cvp_customer_view_prod.js
hp_help.js
p_products.js
pe_prod_edit.js
pv_prod_view.js
z_pref.js
ze_pref_edit.js

この中で先頭にある「base.js」が、レベル1のJavaScriptです。先頭に並んでほしかったので「base」という言葉を選びました。本当は「a」で始まる言葉を使いたかったのですが、思い浮かびませんでした。「base」ならば「b」で始まるファイル名の中でも一番先頭に来そうですし、言葉の意味としても適していそうなので、とりあえず良いかなと思いました。

ここまででも、予想したより長くなってしまいました。続きは、別な投稿として書きます。

 

追記:言葉の間違いを直すため数文字変更しただけなのに、投稿した日付も更新され後ろに移動しました。bloggerのバグなのか仕様なのか、困ったものです。この追記で、また新しい日付に変わるのでしょうか。投稿順に並ばなくなりましたが、直すのが大変なので、このままにしましょうかね。

0 件のコメント:

コメントを投稿