2009.11.12
Closure Library に興味津々
Closure Library (クロージャー・ライブラリ) は先日Google から出されたオープンソースのJavaScriptライブラリです。GmailやGoogle Docsなど様々なGoogleのAjaxサービスで使われてるそうです。もともとJavaScript自体は、異なるブラウザで挙動が違ったり、標準のモジュール化方法が提供されなかったりと、素で使うには厄介でした。そのために、これまで幾つものJavaScriptのライブラリ(prototype.js、jQuery、dojo、Ext JS、YUI、MooToolsなど)が登場してきました。今回のClosure LibraryはそれらライブラリにGoogleが本格的に対抗するものと捉えられます。
筆者はこれまでjQueryを好んで使っていました。一番メジャーであり、軽量かつ覚えるのも簡単で、プラグインも豊富にあるからです。ただ、とりわけ比較的大規模にJavaScriptで開発したいときに、モジュール化するのが比較的やりにくいと感じていました。簡素化のため、あえてそうしてるのだと思いますが、モジュールのインポート機能や自然なオブジェクト指向開発のためのツールが用意されていません。一方、これは、他のライブラリでは実現しているものもあります。しかし、メリットデメリットを考慮し、総合的な利便性でjQueryを選んでいました。Closure Libraryを見ると、その点でモジュール化が徹底されており、大規模開発向けな印象を受けます。そして改めて総合的に判断すると、今回はClosure Libraryに乗り換えるだけの魅力があるのではないかと感じています。
以下にClosure Libraryの主な特徴を独断と偏見で列挙したいと思います。
1.依存関係管理
Closure Libraryでの各コードファイルでは次のように、依存モジュール(ライブラリ)をインポートすることができます。
goog.provide('goog.math');
goog.require('goog.array');
goog.require('goog.math.Box');
goog.require('goog.math.Coordinate');
goog.require('goog.math.Range');
goog.require('goog.math.Rect');
goog.require('goog.math.Size');
ここでgoog.provide()関数はこのコードファイルでのパブリックなネームスペースもしくはクラスを宣言します。goog.requre()関数は他のモジュールをインポートし、このファイル内でそれらを利用できるようにします。
普通は、これら依存するコードファイルは複数のHTTPリクエストによってロードし展開します。しかし、この方法は速度的に問題があり、開発環境ではいいですが、本番環境には適していません。
そこで、calcdeps.pyというPythonのスクリプトファイルが用意されており、これを実行することによって、それら複数のコードファイルを一つのファイルにまとめ、かつ"圧縮"することができます。
2.継承
オブジェクトの継承は次のように行います。
function ParentClass(a, b) { }
ParentClass.prototype.foo = function(a) { }
function ChildClass(a, b, c) {
ParentClass.call(this, a, b);
}
goog.inherits(ChildClass, ParentClass);
var child = new ChildClass('a', 'b', 'see');
child.foo(); // works
ChildClassのコンストラクタ内のParentClass.call(this, a, b)は親クラスのコンストラクタを呼び出す部分です。そして、goog.inherits(ChildClass, ParentClass)でChildClassをParentClassの子クラスとして定義しています。
また、固有名のParentClassではなく共通の”superClass_”変数を利用して親クラスを呼び出すこともできるようです。
ChildClass.prototype.foo = function(a) {
ChildClass.superClass_.foo.call(this, a);
// other code
};
[追記] Closure Libraryの継承に関しては次のブログが詳しいです:”Inheritance Patterns in JavaScript“。より自然な継承の実現やClosure Compilerと親和性が高いこと、メモリへの配慮を行っていることが分かります。
3.イベント
イベント処理は次のように行います。
goog.events.listen(this.elHeader_, goog.events.EventType.CLICK,
this.onHeaderClick_, false, this);
1番目の引数はイベントを発動するDOMノード、
2番目の引数は捉えたいイベントタイプ、
3番目の引数はイベントが起こったときに呼ばれるリスナー関数です。
4番目の引数はcapturePhaseのみでイベントを捉えるかどうかを決め、リスナー関数内での”this”の中身を定めます。
5番目の引数は
第5引数でthisの中身を指定できるのはいいですね。
4.デバッグ
これは次のポップアップするデバッグウインドウのデモを見るのが早いかと思います:
http://closure-library.googlecode.com/svn/trunk/closure/goog/demos/debug.html
JavaScriptではFirefoxのプラグインツールであるFirebugを用いてデバッグするのが主流ですが、IE等ではまだまだデバッグツールが貧弱なので、このようなブラウザ非依存のリッチなデバッグツールがあると便利ですね。さらに、ログレベルを細かく設定できるので(参考)、特に大規模な開発で役に立つと期待されます。
4.データ管理
APIを見ると、ds.DataManagerというクラスがあり、データソースを統一的管理する仕組みが用意されているっぽいです。特に、データの変更を通知する仕組みが実装されており、これによってデータバインディングができるようになると思われます。個人的に、Flexの開発ではこのデータバインディングを重宝していて、これがJavaScriptで標準でできればと思っていました。
[追記] よくよく見るとFlexのデータバインディングとは少し違うようですね。ただこれを利用してデータバインディング的なことはできそうです。
5.基本ライブラリ
数学やコレクション関連の基本ライブラリはかなり充実していると感じました。例えば、個人的には、ds.SortedNodeListやstructs.Poolなどの機能を独自に実装した経験があり、こういうのがあったらと思っていました。
6.ユニットテスト
ユニットテストのライブラリも標準として備わっており、非常に充実しています(この辺のクラス)。大規模開発ではテスト駆動開発は必須になってくるので、ここはやはりしっかり押さえています。
6.ブラウザ機能
ユーザインターフェースを初めブラウザ独自の機能に関わるAPIも非常に豊富です。APIドキュメントのページの右にあるDemosタブからたくさんのデモを見ることができます。
基本的な設計思想としては、各ブラウザ機能をそれぞれ抽象化し、再構築している感じです。例えば、ui.CheckBoxはチェックボックス機能を独自に実装しています(Input要素は使わず、span要素と背景画像の切り替えで実装しています)。また、JavaScriptの基本関数であるsetTimeoutやsetInterval関数の機能もこのデモにあるようなクラスで抽象化し、改良しています。
また、例えば、クロスブラウザなキャンバスライブラリやマウスホイールのハンドリングなど、jQueryでは外部ライブラリが必要だったもので、Closure Libraryで実装されたものが要所要所であり、便利かなと思います。逆に、Closure Libraryでなくて、jQueryであるようなものは一応見当たらなかったです。
・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・・
とりあえず、以上です。全体としてJavaScriptがJAVAっぽくなった感じですが、同時に、徹底的に改良された印象を受けます。簡単な開発はjQuery、大規模な開発はClosure Libraryという流れになる気がするのですがどうでしょうか?
Trackback URL
Comment & Trackback
Comment feed
Comment