日本ソフトウェア科学会第 32 回大会 (2015 年度) 講演論文集

部品化を指向したクライアントサイド Web アプリケーション開発の枠組の設計と実装
山本 竜太郎

岩崎 英哉

GUI アプリケーション開発において, UI を構成する要素を適切に部品に分割することは, 部品の再利用性を向上させ, アプリケーションの開発効率を向上させる上で重要である. 一方, クライアントサイド Web アプリケーション開発で用いられる HTML や CSS といった言語は, 名前空間や依存関係管理の機能を言語仕様として持っていない. そのため, 部品化を行っても, 異なる部品間で名前が衝突するという問題が生じ, 部品への分割の利点を十分に得ることが出来ないという問題点がある. この問題点を解決するために, 本研究では, HTML や CSS の文法をベースとして名前空間および依存関係管理の機能を追加した新たなアプリケーション開発の枠組を提案する. 提案する枠組を用いれば, 既存のコード資産に大きな変更を加えず, アプリケーションの部品化が可能となる.

成する要素を分割して開発する部品化と呼ばれる手

1 はじめに法が, 開発効率の向上に有用であることが知られてい

近年, GUI アプリケーションを構築する際に, Webる [3]. この手法を応用することで, クライアントサ技術を用いることが増えている. こうしたアプリケー

イド Web アプリケーションの開発効率の向上が期待

ションでは, HTML や CSS を用いてユーザインタできる. しかし, アプリケーション開発に用いられるフェース (UI) を設計し, JavaScript を用いて挙動をHTML や CSS, JavaScript といった言語は, 言語仕定義することで, Web ブラウザ上で GUI アプリケー様として部品化を行うのに十分な機能を持っていないションとしての機能を実現する. Web 技術を用いるという問題がある. 例えば, CSS は名前空間の概念をことで, Web ブラウザさえあればプラットフォームに持たないため, ある部品の CSS を異なる部品からも依存することなくアプリケーションを動作させること参照できてしまう.

ができ, 環境への依存性の低いアプリケーションを実

そこで本研究では, クライアントサイド Web アプ現できる. また, Web 技術はネットワークとの親和性リケーションの部品化を実現するアプリケーション開が高いため, アプリケーションにネットワークを利用発の枠組を提案し実装することを目指す. この枠組でした機能を容易に追加できるという利点もある. これは, 既存の開発言語である HTML や CSS, JavaScript

らのアプリケーションは, クライアントサーバモデルに対して必要最小限の変更を加え, アプリケーションのクライアント側で動作するアプリケーションであるの部品化を実現する. この枠組で取り入れられた変更ため, クライアントサイド Web アプリケーションとは非常に簡単なものであるため, 既存のコード資産に呼ばれる.

大きな変更を加えずに, アプリケーションを部品化でGUI アプリケーションの開発においては, UI を構きる.
本稿の構成は以下のとおりである. 2 章と 3 章では, 簡単なプログラム例を用いつつ, クライアントサ

Ryutaro Yamamoto, Hideya Iwasaki, 電 気 通 信 大学 情 報 理 工 学 研 究 科, Department of Information
and Computer Science, The University of ElectroCommunications.

イド Web アプリケーションの開発と, その際に生じうる問題について述べる. 次に 4 章で本研究で提案する枠組の概要について, 5 章で枠組を実現するための

/* HTML */<html><body onLoad="init()"><div><span id="count"></span><input type="button" onClick="countUp()">Count UP</input></div></body><html>

アプリケーション
部品A
部品AのHTML
部品AのCSS
部品AのJavaScript
部品B
部品BのHTML
部品BのCSS/* CSS */#count { color: #555555; }部品BのJavaScript
…

1
2
3
4
56
78
910111213
1415
16
17
18
1920
2122232425
26
2728/* JavaScript */var cnt;function init() {cnt = 0;
document.getElementById("count").innerHTML = cnt;}
function countUp() {cnt = cnt + 1;
document.getElementById("count").innerHTML = cnt;}

図2

クライアントサイド Web アプリケーションの部品化

CSS では, UI の見た目を定義する. 例では, countという ID のついたタグに対応する DOM について,文字色を#555555 に指定している.

JavaScript では, アプリケーションの挙動を定義する. JavaScript コードは, HTML タグで指定され

図1

簡単なクライアントサイド Web アプリケーションたイベントが発火した時に呼び出される. 例にある

input タグには onClick="countUp()"という属性がライブラリの設計と実装について説明する. 最後に 6付与されているので, この input タグで定義されたボ章で関連研究について述べ, 7 章で今後の課題と本稿タンがクリックされた際に, countUp 関数が呼び出さのまとめを述べる.

れる. JavaScript コード中では document オブジェク
トを介して DOM の要素を操作できる. init 関数及2 クライアントサイド Web アプリケーション

び countUp 関数では, これを用いて変数 cnt の値をク ラ イ ア ン ト サ イ ド Web ア プ リ ケ ー ション は,DOM に反映している.

HTML と CSS, JavaScript によって記述される.
図 1 に簡単なクライアントサイド Web アプリケー

3 部品化とその際に起きる問題点

ションの例を示す. このアプリケーションは初期状態

3. 1 GUI アプリケーションにおける部品化

では, count という ID が付与された DOM のテキス

GUI アプリケーションにおける部品化とは, アプリ

トが 0 となっている. そして, アプリケーションの利ケーションの UI を構成する要素を分割して開発する用者がボタンをクリックするたびに, そのテキストのことである. 部品化によって, アプリケーションの開内容が 1 ずつ増加する.

発において次のような利点が得られる.

HTML では, タグを用いてアプリケーションの UIの論理的構造を定義する. 例では, span タグを用いてカウントされた数の表示領域, input タグを用いてカウントアップを行うボタンを定義している. タグ• 一度開発した部品を再利用することで, 開発期間を短縮し, バグを減らすことが期待できる.

• 部品を複数の人間で分担して開発することで, 開発期間を短縮できる.には id および class 属性を付与でき, それを用いてクライアントサイド Web アプリケーションにおいCSS や JavaScript からタグに対応する DOM を指定て部品化を行うと, 図 2 のような構造となる. 各部品できる.

はそれぞれ HTML, CSS, JavaScript を独立して持っ123456789/* 部品 A の CSS a.css */#wrapper {background: a.jpg;}

部品A

部品Ba.css

c.css

b.css

b.css

/* 部品 B の CSS b.css */#wrapper {background: b.jpg;}(a) 正しい動作
部品A

図3

名前の衝突

部品B
a.css

c.css
参照

b.css

b.cssている.
(b) 間違った動作

部品化において実装される部品には, 予め定められたインタフェースによってのみ他の部品とやりとりで図4

依存関係の問題きるという性質が求められる [2]. これはオブジェクト指向プログラミングにおいてオブジェクトに求めらず, 全ての読みこまれた CSS がページ全体に適用される性質と類似している. この性質が仮に損なわれれれるため起きうる.

ば, 部品の利用者は部品の内部実装が変更される度に3. 2. 2 依存関係の問題

部品を利用しているコードを書き換えなければならな

図 4(a) に示すような部品が存在する状態を考える.

い. 一方, この性質が保たれていれば, インタフェー

ここで, 部品 A の b.css と部品 B の b.css は, 偶然スが変更されない限り, 部品の利用者は部品を利用し同じファイル名であるが内容は異なるものとする. こているコードを書き換えることなく, 新しい部品を利の状態で, 部品 A と部品 B を利用するアプリケーショ用できる.

ンを構成しても, 問題は発生しない.
しかし仮に図 4(b) のように, b.css を部品 B に含3. 2 CSS の問題め忘れたとする. 部品 B のみを利用するアプリケー

クライアントサイド Web アプリケーション開発にションであれば, b.css が見つからないというエラー

おいては, 3.1 節で述べた性質を保つことが難しい.

が発生するので, 問題にすぐ気づくことが出来る. しこの難しさは, クライアントサイド Web アプリケー

かし, 部品 A と部品 B を両方使うアプリケーションション開発に用いられる言語の仕様に起因している.の場合, 部品 B は部品 A の b.css を読み込んで動作

本稿では CSS の言語仕様に起因する問題を 2 つ説明してしまうため, ファイルが欠如しているという問題する.にすぐに気づくことが出来ない.

3. 2. 1 名前空間の問題
部品 A と部品 B がそれぞれ図 3 に示すような CSS

この問題は, 各部品が依存する CSS を管理する仕組が存在しないことに起因する問題である.

を持っているとする. この時, 開発者が部品 A と部
品 B を同時に利用するアプリケーションを開発する

4 提案する枠組の設計ことを考える. すると, 部品 A と部品 B 両方が部

4. 1 部品の開発

品 A の CSS と部品 B の CSS を参照できる状態とな提案する枠組における部品の開発手順を図 5 に示る. 部品 A の CSS と部品 B の CSS は, 同じセレクす. 部品の開発者は, HTML および CSS, JavaScript

タ#wrapper を持つので, 部品 A に対して部品 B のを用いて部品の定義を記述する. 続いて, 記述した

CSS が適用されたり, 部品 B に対して部品 A の CSSHTML および CSS, JavaScript コードを本研究で実が適用されたりする可能性が生まれる.

装する変換器に入力する. 変換器は記述を解釈し, ここの問題は, CSS が名前空間の概念を持っておられらを 1 つの JavaScript ファイルにまとめて出力すHTMLCSSJavaScript

変換器
JavaScriptコード

図5

部品の開発の流れる. この出力された JavaScript ファイルを部品として利用する. CSS の内容が JavaScript の中に埋め込まれるため, 各部品が依存する CSS の定義は自明であり, 3.2.2 節で述べた問題が生じることはない.

2 節で紹介した簡単なアプリケーションの例を元に,提案する枠組で部品を記述した例を図 6 に示す. 部品
は a.html, a.css, a.js の 3 つのファイルの記述で構成される.

CSS の記述は, これまでの CSS の記述と同等に行

12345678910111213141516171819202122232425
26/* a.html */<html><body><div><span class="count">{{ cnt }}</span><input type="button" onClick={{ countUp }}>Count UP</input></div></body><html>/* a.css */.count {color: #555555;}/* a.js *//* 最初に必ず実行される特別な関数 */function _init() {this.model.cnt = 0;}function countUp() {this.model.cnt = this.model.cnt + 1;}

える. ただし, a.css 内で定義された CSS は, a.htmlに適用範囲が制限される点が, 従来の CSS と異なる

図6

提案する枠組による部品の記述点である. これによって, 3.2.1 節で述べた問題が解決される.
クライアントサイド Web アプリケーションの実装
においては, JavaScript コードを実行しつつ, 必要に応じて DOM を動的に変更する仕組が必要である. 提案する枠組では, この仕組に対する既存のアプローチである Mustache.js [5] を参考に, HTML 上に拡張構文を記述できるようにしてこれを実現している.

HTML からは, {{}}という拡張構文を用いること
で, JavaScript 中で定義された変数や関数を参照で

1234567891011121314<html><body><div id="component-a"><script src="a.js"> /* 部品を読み込む */</div><div id="component-b"><script src="b.js"> /* 部品を読み込む */</div>/* 実行時ライブラリを読み込む */<script src="runtime.js"></body></html>きる. HTML から参照できる JavaScript の変数は,this.model オブジェクト中に定義されたものに限図7

部品を利用する例

定されている. これは JavaScript コードに登場するデータを DOM の構築に必要なものと, そうでない一時的なものに分け, プログラムの見通しを良くする役割を果たしている.

4. 2 部品の利用
上のように記述し生成した部品を利用する例を図 7に示す. ここで, a.js と b.js は先述の変換器で出力

JavaScript には, init という特別な関数を定義でされた JavaScript コードのファイルである. アプリ

きる. これは部品が読み込まれた時に自動的に実行さケーションの開発者は, HTML において部品を埋め込れる関数である.

みたい箇所に script タグを用いて部品の JavaScriptコードを読み込むことで, 部品を利用できる. a.jsと b.js はそれぞれ別の部品なので, a.js の定義をb.js から参照したり, その逆を行ったりすることは1 module {2\_css: {3/* CSS */4}
56....
7/* javascript functions */8....
910_render: function() {11return /* HTML */12}
13 }1234567891011/* 変換前 */abc {background: #555;}/* 変換後 */\_css: {abc: {
background: "#555",}}

図9
図8

変換器による CSS の変換変換器が中間生成する JavaScript コード

レクタで DOM を複雑に走査する必要はなくなるのできない.
例では, runtime.js というファイルも合わせて読で, CSS セレクタとして class 宣言しか使用できなくとも, アプリケーションの記述には支障はない.

み込んでいるが, これは部品の JavaScript コードをHTML は, render という特別な関数の返り値と解釈して動作させるための実行時ライブラリである.

して, 同様に JavaScript のオブジェクトの形に変換提案する枠組で開発された部品を利用するには, 実行して保持される.

時ライブラリを合わせて読み込む必要がある.

JavaScript コードの生成は, escodegen†1 というライブラリを用いて行う. このライブラリは, JavaScript

5 提案する枠組の実装の AST から実際の JavaScript コードを生成するラ提案する枠組を実現するために, 部品を記述したイブラリである.

HTML や CSS, JavaScript を単一の JavaScript コー

以上の手順で生成されたコードは, ECMAScript 6ドに変換する変換器と, その JavaScript コードを読み込んで実行し実際に部品として動作させる実行時に準拠したコードであるため, 古いブラウザでは動作させることが出来ない. そこで最後に, Traceur†2 とライブラリを実装する.

いうライブラリを用いて, ECMAScript 6 準拠のコードを現行のブラウザで実行できるものに変換し, これ

5. 1 変換器を最終的な出力とする.

変換器は, まず図 8 のような構成の JavaScript コードを生成する.

5. 2 実行時ライブラリ

コードの全体は, module ブロックで囲まれている.

変換器によって生成された部品ファイルは, 3.2 節

module は, ECMAScript 6 [6] より導入された言語仕で述べた問題を解決するために HTML および CSS,様である. このブロックの内部に変数と関数のみを宣JavaScript を全て一つのファイルにまとめているた

言することができ, それらは原則としてブロックの外め, そのままではブラウザで解釈して実行することが側から参照することが出来ない. これを用いることにできない. そのため, 部品ファイルを解釈して実行す

よって, 3.2.1 節で述べた問題点を解決することがでる実行時ライブラリが必要となる. 実行時ライブラリ

きる. この module の中に, 入力された HTML, CSS,は以下の動作をする.

JavaScript が全て含まれている. CSS は, JavaScript

1.

init 関数を実行する.のオブジェクトの形に変換して css という名前で保2.

render 関数の返り値を元に, DOM を生成し持する. 例えば, 図 9 のような変換が行われる. この変換の実装を簡潔にするために, CSS セレクタを class宣言に制限している. 部品化を十分に行えば, CSS セ†1 https://github.com/estools/escodegen†2 http://github.com/google/traceur-compiler

展開する.

3. model オブジェクトとイベントの監視を開始する.

なくアプリケーションを動作させることができる.

Cascading Tree Sheets (CTS) [1] は, CTS と呼ばれる CSS に似た文法を持つ新たな言語を導入し, 部

4. model オ ブ ジェク ト の 変 更 を 検 知 し た ら,品化を容易にしている. CSS に着目している点は本

render 関数の返り値を元に新たな DOM を生研究と類似しているが, 部品化の実現方法が本研究と成し, 古い DOM と置き換える.

は異なる.

5. イベントの発火を検知したら, 対応するイベントハンドラ関数を実行する.

7 おわりに本稿では, クライアントサイド Web アプリケーショ

6 関連研究ン開発で部品化を行う際の問題点を提起し, その問題クライアントサイド Web アプリケーションにお点を解決するための新たな枠組の提案を行った. こいて, アプリケーションの部品化をしやすくする仕の枠組では, 現行の開発言語に僅かな変更のみを加え組については, いくらかの例がある. Google Web

ることで部品化を容易にしているため, 既存のコード

Toolkit [4] は, Google が開発している Web アプリ

資産に大きな変更を加えることなく, 部品化が可能でケーションフレームワークである. このフレームワーある.

クは, UI を構成要素ごとに記述しそれを組み合わせる

現状は, 実行時ライブラリの実装を行っており, 手ことで Web アプリケーション開発を行う本研究と目で記述した簡単な変換後の JavaScript コードを解釈指す方向が同じであるが, アプリケーションを Java でして実行できるという段階である.

記述することを前提としており, Java の知識がないデ今後は, 実行時ライブラリが完全な JavaScript コー

ザイナなどが利用するにはハードルが高いという問題ドを解釈して実行できるように拡張するとともに, 変がある. 本研究の手法は, HTML や CSS, JavaScript換器の実装を進める. その上で, 簡単なアプリケーショなどの既に Web アプリケーション開発で広く利用さンを本枠組で実装し, 従来の記述と比較して, 記述性れている言語をベースとするため, 利用にあたってのや, 実行時性能について評価したいと考えている.

ハードルが低く抑えられている.

WebComponents [7] は, W3C が策定を進める Web
アプリケーションの UI の部品化のための仕様である. 既存の DOM や JavaScript に拡張を加え, 特定のDOM を外部から参照できないようにしたり, 特定のDOM に CSS の適用範囲を制限することが可能になっている. 例えば, DOM オブジェクトに対して外部から参照できない DOM を追加するメソッドが新たに実装されている. この仕組では, DOM と JavaScriptそのものに拡張を加えているため, WebComponentsを用いて記述されたアプリケーションを古いブラウザで直接動かすことが出来ないという問題がある. それに対して本研究の手法では, DOM や JavaScript に拡張を加えず, 既存のブラウザで利用できる機能のみを用いて部品化を実現するため, 古いブラウザでも問題

参 考 文 献[1] Benson, E. and Karger, D. R.: Cascading Tree
Sheets and Recombinant HTML: Better Encapsulation and Retargeting of Web Content, Proceedingsof the 22nd international conference on World Wide
Web (WWW ’13), 2013, pp. 107–118.
[2] Chaudron, M. and Crnkovic, I.: Componentbased software engineering, Software Engineering:
Principles and Practice, (2008), pp. 605–628.
[3] Goldberg, A. and Robson, D.: Smalltalk-80: The
Language and its Implementation, 1983.
[4] Google:
Google Web Toolkit, http://www.
gwtproject.org/.
[5] Lerner, R. M.: At the Forge: Mustache.js, Linux
Journal, Vol. 2011, No. 210(2011).
[6] Rauschmayer, D. A.: Exploring ES6: Upgrade to
the next version of JavaScript, 2015.
[7] W3C: WebComponents, http://www.w3.org/TR/components-intro/.