先週まで、Java SE 6のスクリプト対応について解説してきました。Javaからスクリプトへのアクセスが意外に簡単にできることが分かりました。
とはいっても、スクリプトをどこに活用すればいいかということは記述していません。そこで、今週はスクリプトの使いどころについて、議論していきましょう。
筆者が考える、スクリプト活用のポイントは次の3つです。
- 変化の頻度
- 構造と手続き
- 問題領域への特化
現代のビジネスでは変化はいたるところで発生します。ビジネスモデル、スケール、機能などさまざまな部分で変化は起っていきます。このような変化に対して迅速に対応を行なわなくては、ビジネスの機会を損失することもありえます。
筆者は、スクリプト言語を使うことで、変化への対応能力を向上させることができるのではないかと考えています。
次の構造と手続きを考えてみましょう。
Javaは手続きを表すことは得意です。一方、XMLは構造を表すのが得意です。Javaで構造を表すことも、もちろんできます。しかし、構造を手続き的に表すため、若干分かりにくくなってしまう部分があります。
たとえば、GUIを考えてみましょう。ある幅と高さを持ったフレームにラベルとボタンが貼られているとします。ラベルもボタンも幅と高さを持ち、ラベルとボタンの位置関係を表す必要もあります。ラベルに表示されている文字列、ボタンに表示されている文字列も表さなくてはいけません。
Javaではこのような構造を表すときに
- フレームを生成
- フレームにサイズを設定
- ラベルを設定
- ラベルの位置を設定
というように、1つ1つ手続きとして表す必要があります。ちょっとまどろっこしいですね。XMLはこのような構造的なデータを容易に記述することができます。
逆にXMLでは手続きを表すことが苦手です。ループや分岐を伴ったフローをXMLで表すことは可能ですが、冗長になり、可読性も低くなってしまいます。
スクリプト言語は言語によって特徴はありますが、ほとんどのスクリプト言語で構造と手続きの両方を容易に表すことができます。
最後の問題領域は、特定のドメインに特化した表現を行ないやすいかどうかということです。DSL (Domain Specific Language)という言葉はまさにこれを表しています。
スクリプトを活用できるのはこのポイントのいずれかが当てはまる場合が多いのではないかと筆者は感じています。
たとえば、Webアプリケーションのプレゼンテーション層にスクリプトを使用することを考えてみましょう。
Webアプリケーションという問題領域に特化したフレームワークであり、扱うのはHTMLという構造的な情報、そしてWebページの更新は頻繁に発生します。つまり、筆者が考えるスクリプト活用のポイントをすべて満たしているのです。
このポイントを鑑みて、スクリプトが適していると考えられる分野には次のようなものがあるのではないでしょうか。
- プレゼンテーション層
- ビルドツール、デプロイツール
- テスト
- コード生成、システム設定
- ワークフロー記述
図1 Roberto Chinnici氏 |
---|
プレゼンテーション層へのスクリプトの適用は、Grailsや、JRuby on Rails、Project Phobos、Sarugau JSなどすでに多くの例があります。ここではProject Phobosを紹介しましょう。
Project PhobosはjMakiなどと同様にGlassFishのサブプロジェクトとして開発されています。Project Phobosを開発しているのはJava EE 6のスペックリードでもあるRoberto Chinnici氏です(図1)。
Phobosはサーバ側でスクリプトを使用しているWebアプリケーションフレームワークです。現状はJavaScriptを使用していますが、その他の言語への展開も考えられているようです。
Phobosでは、MVCパターンを使用し、モデル、ビュー、コントローラに対応するJavaScriptファイルでアプリケーションを構成しています。
たとえば、サンプルとして提供されているCalculatorを見てみましょう。
PhobosはNetBeans 5.5のプラグインとして提供されています。詳しくはダウンロードページを参照していただくとして、NetBeansのアップデートセンターにAJAX Update Centerを追加し、Phobosに関連するモジュールをインストールします。
Calculatorは新規プロジェクトでScriptingカテゴリのSamplesの中にあります。
Calculatorを実行してみると、図2のように表示されます。Second Operandに数字を記入し、演算子を選択し、Computeボタンをクリックすると、Current Totalに結果が表示されます。
図2 Calculator |
---|
図3にプロジェクトの構成を示します。
図3 Calculatorプロジェクトの構成 |
---|
Application Directoryにサンプルのソースが配備されます。controllerにはcalculator.js、そしてviewの下にはcalculator.ejsがあります。前者がMVCのコントローラに相当し、後者がビューに相当します。
calculator.jsを以下に示します。なお、オリジナルの英語のコメントの代わりに、筆者が日本語のコメントを付け加えました。
// /calculatorというURLでコールされるように設定 library.common.define(controller, "calculator", function() { this.Calculator = function() { // calculator/show でコールされる関数 this.show = function() { var v = invocation.session.value; if (v == undefined) { v = 0; } var op = invocation.session.selectedOp; if (op == undefined) { op = "add"; } // これがMVCのモデル model = { value: String(v), selectedOp: op }; // ビューのレンダリング library.view.render("calculator.ejs"); }; // /calculator/compute でコールされる関数 this.compute = function() { library.httpserver.onMethod({ POST: function() { var value = Number(request.getParameter("value")); var operand = Number(request.getParameter("operand")); var operator = request.getParameter("operator") value = ({ add: function(x,y) { return x+y; }, subtract: function(x,y) { return x-y; }, multiply: function(x,y) { return x*y; }, divide: function(x,y) { return y == 0 ? 0 : x/y; }, }[operator])(value, operand); invocation.session.value = value; invocation.session.selectedOp = operator; // /calculator/show へのリダイレクト library.httpserver.sendFound(library.httpserver.makeUrl("/calculator/show")); }, any: function() { library.httpserver.sendNotFound(); } }); } }; });
2行目のlibrary.common.defineメソッドで、/calculatorというURLの場合にcalculator.jsがコールされることを定義しています。青字で示したshowメソッドとcomputeメソッドは、それぞれ/calculator/showおよび/calculator/computeの場合コールされます。
showメソッドではセッションからvalueとopを取り出し、赤字で示したようにそれをMVCのモデル要素であるmodelに保持させます。modelはマップとして実装されており、コロンの前がキー、後ろがバリューになります。
そして、最後にcalculator.ejsを呼び出し、ページをレンダリングします。