2011-03-12

近況

無事です.

はいいとして, 先週 Shibuya.js で話してきました (スライド). 空気をよまず JS と無関係の話をしてしまいやや申しわけなかったけれども, WebKit の様々な幻想をぶちこわす開発の様子を知ってもらうことには個人的な使命感を感じておりつまりこれはちょっとした十字軍なのです.

JS のテストってなんでむずかしいの?

地震さわぎで自宅警備中の人も多いだろうから, お互いの気晴らしをかねてだらだら書きたい.

JavaScript のテストについてぐぐったりついったを読んだりしていると, JavaScript でテストを書くのは大変だとか難しくてやってないという話が多くて不思議におもった. 私は JavaScript を使ってウェブアプリを作る仕事をしたことがなく, いまいち難しさがピンとこない. 趣味でさわっている範囲だと普通に書ける. なぜ人は難しさを感じるのだろう. 誹謗中傷は承知のうえ印象を書いてみるので, 俺は違う理由だという人は教えてください.

印象: JavaScript 周辺では開発者テストの歴史が繰り返されている.

私はあるとき割とテストの書きにくいレガシー気味の仕事をしていたことがあって, その仕事中はどうテストを書くかにもっぱら頭をひねっていた. その仕事が済んだ少し後に レガシーコード改善ガイド を読んだとき いたく感動したのは, 自分が苦労してなんとなくやっていた(以上の)ことが, 綺麗に整理された形で示されたからだと思う.

ところが, その後スクラッチからコードを書く仕事や Python や Ruby なんかでウェブを作る 仕事をしたときは, レガシーコード対策について苦労することはなかった. 新しい環境には最初からテストの仕組みが備わっているし, 仕組みがない時もわざわざテストできないコードは書かない. そんな仕事をするうち, レガシーコード改善ガイドは過渡期のテクニック集にすぎず xUTP の方がより根深い問題に挑んでいると感じはじめた. 細かい違いはあれ, 世の中の人もおおおむねこの順番で学んだのではないかと思う.

JavaScript のテストに関する不平不満は, レガシーコード相手にテストをしない人達の言い訳によく似ている. レイアウトや副作用, ブラウザの互換性, イベントのエミュレーションといった最近の苦労話は, システムコールや 外部入出力, コンパイラやターゲット OS の互換性, フレームワークとの結合のような十年前の言い訳に呼応する. JavaScript のまわりだけ時代が xUTP 紀からレガシーコード紀に先祖返りした感じで面白い.

レガシーな JavaScript?

私の趣味 JavaScript がテストに苦労しないのは, 新しく書かれた非レガシーコードだから...つまり趣味だから, というだけの話に思える.

JavaScript にとってのレガシーコードとは, たとえばどんなものだろう. 出来合いの DOM を jQuery でちょろっと動かすようなやつ...というと語弊があるけれども, サーバ側で生成したページの DOM を動かしたり XHR で取得した HTML 片をページに差し込むようなコードは レガシーと呼ぶにふさわしいテスト難度を持っている気がする.

ブラウザの中で動くコードだけをテストしたくても, コードが HTTP ... JavaScript にとっての外部入出力 ... にべったりくっついていると, 単独でテストするのは難しい. 20 世紀でいうと継承元の MFC クラスが HWND を抱えて簡単にインスタンス化できないかんじ. テストしたい自分のコードが, 扱いにくい資源(ウィンドウ, アプリケーションサーバ)と密着している.

そのレガシーをどうテストすべきかは当事者に考えてもらうとして, 同じ文脈の "レガシーでないコード" とはどんなものだろう. たぶん JavaScrpt が HTML 全体を組み立てるスタイルだと思う.

レガシーでない JavaScript?

SproutCore, Sencha (Ext JS), Closure といった JavaScript ライブラリは JavaScript の中で GUI を組み立てる. 自分でも GUI 部品を書く. ページ自体を一つの GUI コントロール(コンテナ)にできる.

テストでは対象の GUI コントロールをインスタンス化しメソッドを呼べばいい. 私は Closure しか試していないけれど, こうしたテストは特に労なく書けた. GUI を組み立てるのに必要なデータは (View に対する) Model として分離し, 適当な fixture を与えればいい. サーバ用に書いていたテストがごっそりブラウザ側に来る感じ.

凝った GUI の必要ないアプリケーションなら 大仰なコンポーネントライブラリはいらない. テンプレートで一気に HTML を生成したい. このテンプレート路線でも, Model と View を分離し View の HTML をクライアント側で生成するとテストしやすい. 私は Backbone.js(+Underscore.js) という小さなライブラリを試しているけれど, 最低限必要なものは揃っているかんじ. テンプレートのテキストは CoffeScript のヒアドキュメントとして View のコードに埋め込むとだいぶすっきりする.

ただ Closure は大袈裟すぎ, Backbone.js は非力すぎる. jQuery には構造がない. かつて Rails をさわった時のようなぴたっと収まる座りのよさを, 私はまだ JavaScript から感じたことがない. JavaScript のテスト手法に決定打がないと感じるのは, こうしたレガシーでない(と私が思う) JavaScript 開発の足場に決定打がない症状なのかもしれない. いいのがあったら教えてください.

開発者テストの歴史に照らし, Rails のようなテスト支援を持つ足場がレガシーを駆逐しプログラマは末永く幸せに暮らしましたとさ... というハッピーエンドを趣味プログラマとしての私は夢みているけれど, 職業 JavaScript プログラマに必要なのはレガシー JavaScript と闘うテクニックなのだろうなあ. そういう話をそのうち誰かに書いてほしいです.