Nov 08, 2010

Jetpackへのモヤモヤを全部吐き出そう

僕はJetpackに対していろんな意味で期待していたはずなのに、自分がJetpackでバリバリ開発する姿はいまいち想像できないでいる。Jetpackの話が出始めた頃よりも、JetpackがrebootされてSDKとなってからの方がむしろ、「あれ、なんか僕ってJetpack使ってなさそうなんじゃね?」感が強くなっていっている気がする。Jetpackは僕を幸せにしてくれるのか? くれないのか? それが分からない。

Firefox Developers Conferenceでの発表について「Jetpackからよりディープな世界へのステップアップや、あるいはその逆に、これまでの手法でアドオンを開発していた人達がJetpackにステップアップするには? という風な話題」というオーダーをもらって、ようやっと重い腰を上げてJetpack SDK(とPython)をインストールしてみた。で、とりあえずJetpackの流儀というのを理解しなきゃと思って実際にアドオンを書いてみようとしていきなり挫折して、ドキュメントを読んでみようとしたけどどこから読めばいいのかすら分からなくて頭クラクラで、ヤケクソでJetpack SDKそのもののコードを読んでみたりして、という事をやりながらモヤモヤと考えてた。何故僕はこんなにも、Jetpackに乗り切れていないのか。

現実的にはJetpackを使った方がいい・使わざるを得ないという状況になってきている

Jetpack SDKのドキュメントをちょっと読んで雰囲気を眺めただけでも、僕の今までの知識はまるで役に立たないということはよく分かった。

アドオンを構成するコードは、大雑把に言うと

  1. 「タブの上でダブルクリックしたらタブを閉じる」とか「twitterで新しいツイートがあったらポップアップを表示する」とかの、ユーザ視点での便利さの向上に繋がる機能のためのロジック。Railsでいうなら、generateで生成されるRailsアプリケーション。
  2. 「タブの上で行われたマウスの操作を拾って任意の関数を実行する」とか「ポーリングやソケット通信を使ってサーバから必要な情報を取ってくる」とか「自動的に消えるパネルをデスクトップ上にフェードイン・フェードアウトで表示させる」とかの、前項のロジックを実際のアプリケーションで実現するための基盤。RailsでいうならRailsというフレームワークそのものにあたる部分。

の2つのレイヤに分けることができる。

これまでのアドオン開発においては、2の部分の開発コストが非常に大きかった。W3CのDOMであるとかCSSであるとかのWeb標準の知識がベースにあるとはいっても、XULやXPCOMというMozilla specificな技術を覚えなければならないし、覚えた上で、さらに工夫しないといけない。はっきり言って、アドオンのコードのほとんどは2のための物で、1のためのコードなんてのはほんの一部分だけだったりする。2の部分をどうやって解決するかというのが問題の大部分を占めていて、ほとんどの人はおそらくその段階で挫折してしまって、本題である1の部分に取りかかる事すらできないのだと思う。

僕は、そこ(2のレイヤ)に膨大な時間を注ぎ込んできた。そこに時間を取られるせいでFirefox本体の開発に貢献とかそんなとこまで頭が回らないよ、というくらいの勢いで。その結果蓄積された大量のバッドノウハウこそが、今の僕の武器であり価値なんだと思う。

でも、そういうバッドノウハウはすぐに陳腐化する。また、せっかく覚えたXULやXPCOMの知識も無駄になる時がある。特に、Gecko 2.0からはすべてのインターフェースが凍結されなくなるということは、これからはnsIPrefBranch::getBoolPref()のような頻出のインターフェースすら安心して使えなくなるという事で、かかるコストと得られる物が全然釣り合わないんじゃないのか。

という事を考えると、「だからこそJetpackなんだよ」という話は理解できる。Jetpack SDKは、2の部分をアドオン開発者の代わりにカバーするライブラリ集でもある。Gecko 2.0以降のインターフェースの不安定さをJetpack SDKが吸収して隠蔽してくれるから、開発者は2の部分のためにかける労力が要らなくなって、全力を1の部分の開発に注げるようになる。という寸法だ。1と2の両方に(特に2の部分に異常に多くの)力を注がなくてはいけないロートルの開発者と、1のことだけ考えて開発していればいい新しい開発者、どっちの方が生産性が高くてクリエイティブな結果を沢山生み出せるか。あるいは、どっちの方が労力が少なく済んで、長くメンテナンスし続けられるか。そういう話だ。

その謳い文句、本当なの?

しかし、ホントにそんなにうまくいくのかな?

今でも、過去にFUELという「アドオン開発者向けの、Firefox組み込みのライブラリ」が作られて、それが「XULやXPCOMといった小難しい物を隠蔽すること」を目指していたはずなのに、仕様が十分に錬られてないわ利用者(アドオン開発者)にとっての使いやすさという視点が欠けてるわ実装もあまりにやっつけ仕事でヘビーな利用には全然耐えられないわ(普通に使うとメモリリークしまくる)で、あっという間に「ああ、そんな物もあったっけ……でも使ってる人いるの?」な位置に落ちぶれてしまった。搭載当初は何も特別な準備をしなくても使えるように作られてたのに、Firefox 4からは「コイツの初期化に時間かかるから、初期状態で使えるようにわざわざしておく必要ないよね」と「一級市民のAPI」の地位を追われてしまった。という事実がある。あの頃「FUELで状況はよくなるはずだよ!」という風な事を言って、紹介を書いたりして安易に勧めていた人達は、自分も含めて戦犯として裁かれなきゃいかんね。

そういう前例を見ると、Jetpackも、今は威勢のいいことを言っていても、これから先Firefoxの仕様が変わった時に、「JetpackのライブラリのAPIを維持してFirefoxの仕様変更を頑張って吸収する」方向ではなく「JetpackのライブラリのAPIを変えてFirefoxの仕様変更に合わせる」方向に流れてしまうんじゃないのか、「XULやXPCOMといったコロコロ変わる厄介なAPIの上に、Jetpackというこれまたコロコロ変わる新しい厄介なAPIが加わっただけ」になってしまうんじゃないだろうか、と僕は思ってしまうんだ。それじゃあただの第2のFUELだ。

そこで頑張って自分で貢献するんだよ、って言われても、そもそも前述の2の所の開発で悩まされる事から解放されるためのJetpackのはずなのに……って思うわけですよ。

APIが窮屈

また、Jetpack SDKの提供するAPIをキモく感じてしまった、というのもある。APIで提供される機能がどうこう以前に、API越しでしかFirefoxに触れないっていうことがストレスになった。

例えばタブのコンテンツ領域になってるフレームの生に近いAPIには、今までだったらgBrowser.mTabContainer.childNodes[n].linkedBrowser.docShellでアクセスできた。べつにフツーにフツーのアドオンを作るだけだったらそんなとこ触る必要ないけど、いざというときにはそういう低レベルのAPIから裏口を叩けば何とかなるという、なんていうんだろ、安心感? みたいな? そういうのがあった。

しかしJetpackではこれが隠蔽される。APIで用意された範囲の機能にしかアクセスできない。ということは、やりたいことができそうに無かった時、今までよりもずっと手前の時点で諦めなきゃいけないんじゃないかって気がして、今すぐそれをやりたいかどうか以前に、もう、それができなくなるってだけで息苦しくて窮屈で「うああああ嫌だ嫌だ嫌だ」となってしまう。

まだJetpackがrebootされるよりも前の頃、生のXUL要素に触れるrawというプロパティがあった事について、僕はそれを激しく非難した。そんなのがあったら将来的なAPIの互換性を保てなくなってしまうじゃないか、と。その認識は今でも変わっていない。しかし自分がいざ当事者になってみて初めて、その窮屈さ不自由さを身に染みて実感した。(僕がChromeの拡張機能に手を出そうとしなかったのは、これを本能的に避けていたからなのかもしれない。)

Web標準から離れていく?

そもそも自分がMozillaに肩入れしてるのは何でだったのか。よく考えてみるまでもなく何度も言ってるけど、プロダクトそのものがW3CのWeb標準の技術に基づいているから、そしてそれらの技術にちゃんと対応してたから、というのが一番最初にあった理由なんだよね。

「W3CのDOM? XML? CSS3? そんなの全然Webで使えないじゃん、IEで使えない物に意味なんてないよ。」
「W3Cの仕様なんて、現実見てない頭でっかちの奴らが決めたものだろ? 名前がやたら長ったらしい(例:document.getElementById(id)はIEのDOM0だとdocument.all.idに相当)し、キモすぎる。」
「デファクトスタンダード(事実上の標準仕様)こそがすべてだよ。デジュールスタンダード(標準はこれです、という形で作られた標準仕様)なんかに意味はないよ。」
そんなWeb標準冬の時代に、CSS2のポジショニングにも疑似要素にも疑似クラスにもかなりのレベルで対応してて、W3Cの仕様書にある通りの書き方でちゃんとレンダリングしてくれるGeckoは、実に素晴らしいものだと本気で思ったし、ブラウザのUI自体すらもW3Cの仕様通りのWeb標準技術をベースにして作られてると知った時にはもう、泣いて喜ぶ勢いでしたよ。

「ああ、世間であんなに冷遇されてるWeb標準が、ここにはちゃんと息づいてる!!」それが僕のMozillaとの関わりの始まりだった。僕にとってMozillaは、Web標準の象徴だった。W3C信者だった僕にとっては、魅上照ばりに「あなたが神か」てなもんでした。

でも気がついたら、RDFを使う部分はどんどん減らされて、MNGサポートもドロップして代わりにAPNGなんてMozilla独自の画像形式になってしまって、SOAPサポートもドロップして(だったよね?確か。)……そんな感じで「世間ではまだ広く使われてないけどWeb標準の技術に対応してる、だからまだマイナーなWeb標準の技術でも実際に動くアプリケーションを僕でも作って実証できる、Web標準はちゃんと役に立つんだって事を証明できる」と思ってた余地がどんどん減っていって。その一方で、「次のスタンダードはWebKitだ!」と「標準」のお株を奪われて、新しいWeb標準への準拠度で後れを取って、性能面でも引き離されちゃって。

さらにはユーザの側からも開発者の側からも「XULなんてクソ重い無駄なもんなくしちまえ」みたいな声が出てきて。Jetpackって、XPCOMが廃止されてもXULが廃止されても拡張機能向けのAPIの互換性を保てるようにっていうことで出てきたんだったと記憶してるんですけど、ということは、Jetpackが最高にうまくいったらXULもなくなっちゃうって事ですか? CSS3で外観を変えたり、XPathでUI要素をゴソッと収集したり、そういうのがなくなっちゃうって事ですか? みたいな。

切ないね……

だいたいさあ、安定したAPIになる保証もないのにオレオレAPIをどんどん重ねてくっていうのが気にくわんのですよ!! document.allとかlayersとか混沌として色々分断されてた世の中が、せっかくWeb標準のおかげで見通し良くなってまとまってきたと思ったのに! prototype.jsとかDojoとかMochikitとかjQueryとかYUIとかExtJSとかオレオレな実装が乱立してきてさあ!! なんなの!! もう!!! Web標準だけあればいいじゃん!!!! そんでもってUI用の言語として開発されたXULでいいじゃん!!!! なんでHTMLで無理矢理UI作ろうとするんだよ!!!!! XMLっていう仕組みがあるんだから、それに則った上で用途に適した道具を選ぼうよ!!!!! そういう事を考えもしないで、見慣れてるからってだけでdivだのspanだのでオレオレUI作ってさあ!!!!!!!! なんなんだよそれ!!!!!!!!!

はあ……

しかし光明もある

そんな感じで考えれば考えるほどダウンな気持ちになってきたんだけど、さらに調査を進めていく中で、Jetpackの今のAPIの基礎になる部分はCommonJSの仕様に則る形で開発されているという事を知って、「おおっ!?」と思った。

僕がJetpackの前のAPIでとても「うへぇ」ってなってたのは、ライブラリの読み込み方の部分だった。Greasemonkey等で広く使われてたDocComment風の記法じゃない、jetpack.future.XXXとかのアクセス方法、あれがすごい気持ち悪かった。なんでここでまた無駄にオレオレルールを増やすかなあ!? と思って色々萎えた記憶がある。

でも今のJetpackでは、ライブラリを呼ぶ時はrequre('ライブラリ名')、ライブラリを作る時はexports.プロパティ名に値や関数をセットするというルールになっていた。これは、サーバサイドでJavaScriptを実行するnode.js等の環境でAPIを共通化しようということで議論が進められている、CommonJSのルールだ(そうだ)。これは、Webの開発者にとって親しみやすい物にしよう、独自拡張オレオレルールでなんでもやるんじゃなくて足並み合わせる所はきちんと合わせていこうという意図の顕れだと、僕には思えた。MNGとAPNGの件では見損なったけど、この件では見直した。

あと、Mozillaの中の構造とか全然知らない人にペアプログラミング形式で「ちょっとしたアドオンを作ってみましょうか」とJetpackベースでのやり方を指南(?)しようとして、ああやっぱりこのアプローチは間違ってないんだなということを実感した。

  • 使えるAPIの数が限られてるから、「どのやり方でやるべきか、どの方法を教えるべきか」で迷わないで、「この目的を達成するならこのAPIでやろう(っていうかそれ以外の方法がない)」とサクサク進める。
  • 実際に書くコードの量は少なくなるから、見通しが良くなる。
  • SDKにFirefoxのテスト実行モードがあるから、トライ&エラーで開発できる。「あれー、ダメだった。なんでだ? じゃあここをこうしてみるか」ですぐやり直せるし、「よし、まずはここまでできた。OK? じゃあ次のステップに進もう」という風にちょっとずつ教えられる。
  • 今回は使わなかったけど、自動テストのための仕組みもSDKに含まれてる。

初学者とかWebデベロッパーとか、Mozillaヲタじゃなくてもアドオンを作りやすくなってると思う。Pythonをインストールしなきゃならんとかコマンドラインでやらなきゃならんとかの点は、これからどうにでもなることだ。今まで取りこぼされていた人達をすくい上げる基礎になる物が、今のJetpackには確かに揃いつつあるのだと思う。今までの「動的に適用されるパッチ」でしかなかったアドオンの路線のままでは絶対になし得なかったことが、Jetpackでなら確かに可能になるのだと思う。

どう見ても老害です

しかしまあ、改めて考えると、僕がやっていた事も先人から見れば十分「なんだあの窮屈な世界は」てなもんなんだろうね。C++の生の実装に触ることなくその上に幾層にも積み上げられた物の上で僕はずっと遊んできたわけだけれども、その世界での制限には目を向けることもなく、全てを所与の物として受け入れてありがたがっていた。そんな僕が、GreasemonkeyやGoogle Chromeの拡張機能やJetpackに対して「なんだあの窮屈な世界は」なんて言うのはまったく笑い話でしかないのだろう。

下の層に目を向ければ、ハードウェア寄りのレイヤではそれこそ鬼のような非互換の嵐で、それを吸収するためのOSのレイヤがあって。上の層に目を向ければ、プラットフォームどころかデバイスの違いすら吸収するWebがあって。その中間層であるところのブラウザを作る段階で、プラットフォーム間の互換性がどうだのバージョン間の互換性がああだの言ってるのは、ちゃんちゃらおかしい。

そういう中途半端な所に(Web製作の世界から)逃げ延びて住み着いていた僕が、上の層から僕の居場所をなくそうと迫ってくるJetpackに恐怖を抱いて、拒絶反応を示していた。版図を広げようとしている若手の前で竹槍を振り回してた。ああ、実に老害だ……

それに、Web標準Web標準とわめいてみても、WebKitが中心になってしまった今のWebじゃあGeckoの方がはるかにオレオレ実装なはぐれ者だしおまけに10年以上前のコードを引きずってる骨董品だし、XULもXBLもXMLという仕組みの上に成り立っているとはいってもそれ自体はみんなの合意が得られた標準仕様じゃないわけだし。「神!私は仰せの通りに!」と崇めてるうちに、僕はWeb標準とMozillaのオレオレの見境が付かなくなってたのか……

まとめ

とりとめがないままにモヤモヤした物を吐き出してきたわけだけれども、それと平行してJetpackの内側を覗いてみたりして、光明も見えたりして、自分の勘違いも見えてきて、いくらかスッキリした気はする。

あと、最近は人生っていいものかもしれないなあと思うようになってきたので、老害と言われようともそれでも往生際悪く地味に追いすがっていこうと思ってます。オメガギーク!

エントリを編集します。

wikieditish message: Ready to edit this entry.











拡張機能