Webのフロントエンドで仕事をしているみなさんに質問があります。あなたにとってWebのプログラミングは、HTMLというマークアップを読み書きすることですか。それともDOM(Document Object Model)というツリー構造の操作でしょうか。今回は、この2つの関係を考えてみたいと思います。
マークアップ主義とテンプレートエンジン
HTMLを書くのは簡単です。テキストにいくつかタグを付け足せば最低限のHTMLはすぐにできあがります。プログラミングの必要なDOM操作と比べると、このわかりやすさはHTMLの大きな利点です。
Web開発がマークアップの読み書きだと答えた人の多くは、おそらくRuby 用のERBやJava のJSP(JavaServer Pages)、Python向けのJinjaなど、サーバサイドで動くテンプレートエンジンを使っていることでしょう。テンプレートエンジンはHTMLのわかりやすさに簡潔さを加えてくれます。共通部分をモジュール化して冗長さを減らせるからです。
テンプレートエンジンなどHTML中心のフロントエンド開発を、本稿ではマークアップ主義と呼ぶことにします。わかりやすさと簡潔さを兼ね備えたマークアップ主義はWeb開発の一大勢力です。テンプレートエンジンはその中心でマークアップ主義者のメンタルモデルを支えています。
マークアップ主義には弱点もあります。たとえば対話的な機能(interactivity)は苦手です。イベントハンドラを使い操作に応じて表示内容を変更する。HTML単体にそんな対話性はありません。CSSで事足りるケースもありますが、たいていはJavaScriptを使ったDOM操作に踏み込む必要があります。
マークアップ主義の世界は一方通行です。HTMLという入力から出力である画面表示へ、処理はまっすぐ進んでいきます。HTMLから画面にまっすぐに進む一方通行。この制限によってマークアップ主義はわかりやすさを手に入れました。テンプレートエンジンがあっても一方通行に変わりはありません。しかしJavaScriptによる対話性はそれを壊してしまいます。
jQuery
jQueryは対話性を求めるマークアップ主義者を助けるヒーローです。jQueryならHTMLのわかりやすさを保ちながらページに対話性を持ち込めるからです。検索を宣言的に行うCSSセレクタ、フレームワークの中にfor文を隠す自動ループ、セレクタを拡張するかのようなメソッドチェイン。jQueryのスタイルは、どれもJavaScriptが持つ手続き型プログラミングの性格を隠してくれます。隠し切れない部分もなんとかプラグインに押し出して蓋をするのが流儀。jQueryは、対話的な機能をマークアップ主義の一方通行モデルで解釈しなおす試みなのです。
ツリー主義とGUIツールキット
マークアップ主義の対極にあるのがDOM中心のアプローチです。本稿ではこれをツリー主義と呼ぶことにします。HTMLのテキストを作るマークアップ主義に対し、ツリー主義ではJavaScriptのAPIでDOMツリーを作ります。いわゆる「Webサイト」がマークアップ主義を好むのに対し、たとえばGmailのように対話性を重視した「アプリケーション」サービスはツリー主義に進む傾向があります。
ツリー主義の強みは密度が高く反応が速いユーザインタフェースの開発です。ユーザの操作に応じ、JavaScriptで即座にページを書き換えるのです。ページ遷移も少なく、同一画面に機能を盛り込みます。こうした高い対話性を追い求めるツリー主義では、ページの書き換えというDOMの操作そのものに軸足を置きます。こうなると一方通行のマークアップ主義に立つ瀬はありません。
マークアップ主義者がテンプレートエンジンを使うように、多くのツリー主義者は「GUIツールキット」と呼ばれるJavaScriptのライブラリを使います。Mac OSのCocoaやJavaのSwing、あるいは.NETのFormsなどを模したGUI構築用のライブラリです。歴史あるネイティブアプリケーションの世界から対話的プログラミングのパターンを持ち込んだわけです。Ext JS、SproutCore、Closure LibraryなどがJavaScript版GUIツールキットとして知られています(リスト1)。
テンプレートエンジンはHTML片をモジュール化しました。GUIツールキットはDOMツリーの断片をモジュール化します。たとえばDOMでカレンダーコントロールを作るには数十のDOMノードが必要でしょう。ツールキットの流儀ではそれを単一のウィジェットとしてオブジェクトにまとめます。カレンダーコントロールならCalendarウィジェットを定義するわけです。
多くのウィジェットは入れ子になっています。そして入れ子構造をツリーで表現します(図1)。多くのツリー主義者はDOMツリーの代わりにGUIツールキットのウィジェットツリーを相手にコードを書きます。マークアップ主義者がHTMLを越え、テンプレートの語彙で考えるのと同じです。
ウィジェットはGUIの外見だけでなく、振る舞いもカプセル化します。これがテンプレートとの違いです。テンプレートでもカレンダーの外見を作ることはできます。しかしテンプレートから生成されたHTMLに振る舞いを付け加えるのは外見の再利用ほど簡単ではありません。HTMLとCSSに閉じないからです。
DOMとJavaScriptを一級市民として扱うウィジェットは、それらを無理なく扱えます。開発者はAPIでウィジェットを組み立てるだけ。ウィジェットを使った振る舞いのカプセル化は、高密度な画面を作り込む助けになります。
とはいえAPIでDOMを組み立てるのはマークアップでHTMLを書き出すより面倒なのも事実。画面全体を一望できないコード中心の世界はどうしても見通しが悪いのです。そのほかの要因も相まって、多くのWeb開発者はマークアップ主義にとどまりました。ツリー主義を選んだのは高度に対話的なアプリケーションを作ろうと意気込む開発者だけでした。
GUIツールキットとマークアップ
一部のGUIツールキットは、それでもできるだけ複雑さを減らそうと取り組みを続けました。中でもWeb の中心から少し離れたRIA(Rich Internet Application)向けのツールキットには大きな進歩がありました。一里塚はウィジェットツリーをマークアップで書くアプローチです。XMLでウィジェットツリーの階層構造を記述しておくと、その指示に従ってフレームワークがツリーを構築してくれます。Microsoft Silverlight用のXAMLやAdobe Flex用のMXMLなどが、代表的なウィジェット構築用マークアップです(リスト2)。
HTMLと違い、こうしたマークアップにはあとから語彙を追加できます。開発者がCalendarクラスを実装し、それをタグに割り当てられるイメージです。
マークアップ主義の視点で見ると、このカスタムタグはテンプレートのモジュールに似ています。ただしこのカスタムタグには振る舞いを持てる強みがあります。他方のツリー主義者にとって、この新しいマークアップはウィジェットツリー構築言語です。ウィジェットの入れ子を組み立てる面倒をマークアップに追い出してくれます。
解釈はさておき、これら現代的なGUIツールキットはツリー主義にマークアップを持ち込みました。おかげで開発者はコードを次のような扱いやすい単位に分割できます。
- ① ウィジェット単位で外見と振る舞いを作り込むこと
- ② ウィジェットへの操作に応じたロジックを書くこと
- ③ ウィジェットをマークアップしてロジックをつなぎ合わせ、画面全体を作ること
従来は②と③が混じり合い、ページ全体の構造を見えにくくしていました。それがマークアップによって分離されました。
ところで、これらウィジェットマークアップの一方の祖先はサーバサイドにいます。.NETスタックの標準であるASP.NETやSun Microsystemsが推し進めていたJavaのJSF(JavaServer Faces)は、サーバサイドにウィジェットツリーを持っています。これらツリー主義者のサーバサイド技術がクライアントサイドに引き継がれ、形を変えて返り咲いたのです。
クライアントサイドテンプレート
マークアップ主義を飲み込むツリー主義。ウィジェットマークアップの指し示す先にはそんなWeb開発の未来が見えます。しかし、これにはWebブラウザの進化が不可欠です。一方でマークアップ主義者たちは別の未来を模索しています。そんな兆しの一つがクライアントサイドテンプレートです。
クライアントサイドテンプレートはブラウザ上で動くJavaScript 製のテンプレートエンジンです。Mustache、jQuery Template、Soyなど多くの実装があり、スマートフォン向けのWebを中心に受け入れられつつあります(リスト3)。
対話性についてマークアップ主義が持つ弱点のうち、クライアントサイドテンプレートは反応速度の問題を解決します。ブラウザ上でHTMLを構築すればサーバとの通信にかかる時間を隠すことができるからです。通信量も小さくなります。
Backbone.js[1]のようなクライアントサイドMVC(Model-View-Controller)フレームワークとクライアントサイドテンプレートを組み合わせれば、コードの多くをサーバ側からブラウザ側に移せます。そしてツリー主義への宗旨替えはいりません。テンプレートとMVCの親しみやすいスタイルのまま弱点を補えるのがこのアプローチの利点です。
テンプレートとウィジェットツリー
クライアントサイドテンプレートだけではマークアップ主義の弱点を補いきれません。ツリー主義者の聖杯たるウィジェットが振る舞いをモジュール化したのに対し、対抗馬のテンプレートモジュールにはそれがないからです。
しかし昔とは状況が違います。今やテンプレートエンジンはブラウザの上にいます。その利点を活かし、クライアントサイドテンプレートに振る舞いのモジュール化を持ち込もうとする試みが始まりました。Ember.jsやBatman.jsといった一部のクライアントサイドMVCフレームワークがその舞台です。
一例としてEmber.jsのサンプルコードを眺めてみましょう(リスト4)。一見ただのMustacheテンプレートですが、{{view}}というマークアップに秘密があります。{{view}}マークアップはEmber.jsのViewオブジェクトを構築します。ViewはEmber.jsにおけるウィジェットです。振る舞いを備えています。この例ではApp.myTextというクラスのViewオブジェクトがテンプレートエンジンによってインスタンス化されます。つまりこのテンプレートエンジンはHTMLだけでなく、独自のマークアップで指定されたJavaScriptのViewオブジェクトも構築するのです。そしてできあがったHTMLのDOMとViewオブジェクトを結び付け、振る舞いを与えます(図2)。
こうしてテンプレートはウィジェット構築言語に生まれ変わりました。ウィジェットにマークアップを持ち込んだGUIツールキットとは逆に、マークアップ主義にツリー主義の成果を取り込もうとしているのです。生まれたばかりの荒削りなフレームワークたちですが、新しい地平を切り開こうとする意欲を感じます。
混じり合う水と油
CGIを祖先に持つマークアップ主義の血と、デスクトップから続くツリー主義の血は、紆余曲折を経て混ざり合いつつあります。距離をおき、時には反目しあうコミュニティ同士でも、行方を決める両家のプログラマたちは相手のことをよく見ている。その抜け目のなさは少し微笑ましく、同時にとても頼もしく感じます。ソフトウェアテクノロジの坩堝(るつぼ)たるWebの本領を垣間見る一幕でした。