読者です 読者をやめる 読者になる 読者になる

愛と勇気と缶ビール

ふしぎとぼくらはなにをしたらよいか

iPhone/Android向けのselector-based libraryを実装しての色々(3) - pluginとかtestとかdocumentとか

JavaScript

前回の続き。

plugin機構とか

Riddle.jsにはplugin機構があります、と書くとなんだかカッコよさげに聞こえるが、それは結局外部にエクスポートされているシンボルのうち2つ(rとr.fn)に関数を生やすとpluginっぽいことが出来ますよ、というだけの話にすぎない。r.fnは、セレクタで返ってくる結果セットが継承する元の雛形となっているオブジェクトで、jQuery.fnみたいなもんである。(今これを書いてて思ったけど、Property Descriptorsを使って外部pluginから既存APIの書き換えなどを防ぐ、というのはアリかもしれない。おそらく、そこまでしなくてもいい類のものだけど…)

coreを出来る限り小さく保ちたいという理由から、常に必要ではない要素 or 実験的な要素はpluginと付属させることにした。Zeptoと同じ方法を採用しているわけだが、Zeptoとの違いは、event binding周りのAPIをcoreに入れていること。selector-basedなライブラリ使いたいシーンで、eventのbind/unbindをしない場合とかあんのか?って思ったので。

アニメーションも、常に必要なものではないと思われるのでpluginの方に含めている。アニメーションについては色々考え中で、現在試験的に実装しているのは「CSS3のtransitionを設定し、それから単にcssのプロパティを変更する」という方法。

JSのライブラリでDOM要素に対するアニメーションをサポートする方法は、大きく分けると2つあると思っていて

  1. setTimeoutとeasing関数を組み合わせて頑張る方法
  2. CSS3のanimation周りの機能をラップする方法

1. は現在主流となっている多くのライブラリで実装されている(であろう)方式で、os0xさんがgihyoで連載されている記事のうちアニメーションに関するもの (http://gihyo.jp/dev/serial/01/crossbrowser-javascript/0017, http://gihyo.jp/dev/serial/01/crossbrowser-javascript/0018) をちゃんと読んで、ある程度実装能力があれば「とりあえず動くもの」は書けるように思われる。ただしこの場合、JavaScriptでハンドリングする部分が多いことに加えて、より柔軟&便利な機能を提供しようとすればするほどコード量が増加&複雑化することが予想できる。

2. はCSS3まわりが実装されているブラウザに環境を限定してしまうことになるが、JSのコード量が少なくなりまた簡潔に実装できる。ただ「CSSまかせ」であるが故に柔軟な機能(アニメーションを途中で止めるとか、巻き戻すとか)は実装しにくく、シンプルな単発のアニメーション向きのAPIしか提供できない可能性がある。

基本的に1.の方が機能が多く柔軟なアニメーションを実現できる公算が高いのだが、別に全ての場合に柔軟なアニメーションが必要なわけでもない、という考え方もある。例によってコードをできるだけ小さくまとめたいRiddle.jsでは2の方向でいこうかなー、と思っている(Zeptoはなぜかtransition + transformの組み合わせしか提供していない)。ただ、1.の真面目なアニメーションも自分自身で一度実装してみたいなあ、と思っているので別途書いてみるかもしれない。

testについて

testはQUnitを使っている。Jasmine使ってみようかなあ、とも思ったがシンタックスのオシャレさ以外に特に積極的な採用理由が見当たらず、特に学習コストをかける部分でもないので使い慣れているQUnitにした。

JavaScriptのテストフレームワークには究極、非同期な操作のテストを行う機能とある程度のマッチャ(例えばequal, deepEqual, throwみたいなもの)があれば十分だと思っている。JavaScriptに限った話ではないが、時に大量のマッチャが用意されているテストフレームワークを見かける。そんな大量のマッチャとか頭のメモリに載せておけないし一々使い分けるのが面倒だし、テストフレームワークの機能とかに変に詳しくなっても技術的な意味でそこまで嬉しくないので、僕の最近の好みはシンプルなテストフレームワークの方に傾いている。もっともこれはPerlを使っている影響かも知れないし、オシャレなテストフレームワーク全てを否定する気もないのだが…

要は自然言語風なオシャレなシンタックスとか、「実行できるドキュメントとしてのテスト」とかは飾りに過ぎないので、自分が必要としている機能と学習コストを見極めた上で選んだらいいんじゃないすかね、という話。その上の選択であれば、xUnit形式であるとかspec形式であるとかは大した問題ではない。

以前に僕は「JavaScriptのテストについて本気だしてなんとか」みたいな記事 (http://d.hatena.ne.jp/zentoo/20110123/1295796341) で「自動化!自動化!」「Headless! Headless!」みたいなことを書いていた関係もあって、「testが全部headlessで走るようにしようかなー」とも思ったが、やめた。理由は、headlessにブラウザ周りのtestをするソリューションには未だ決定版がなく、選定にかける時間もないし、そこまで自動化する必要も今のところないし、最終的にiPhone/Androidの実機で動かさないとダメだから。

テスティングフレームワークとは別に、テストを補助するためにSinon.jsとJSDeferredを使っている。これらはいくつかのtestを書くときにとても役に立った。Sinon.jsについては別途記事にするかもしれない。

documentについて

documentについてはこちらの記事 (http://efcl.info/2011/0226/res2291/) を参考に色々試したのだけど、決定版的なツールのなさが凄まじかった。みんなどうやってドキュメント生成してるんだろうか?

なんだかんだで一番枯れていそうなjsdoc-toolkit (http://code.google.com/p/jsdoc-toolkit/) を選んだのだが、デフォルトで出力されるhtmlがダサすぎる。テンプレートやcssを自分でいじればいいのかもしれないが、そんな部分を自分で頑張りたくはないので、デフォルトのデザインをもうちょっと何とか知れてほしいところ。

jsdocの文法ベースで、closure compilerのページに書いてあるガイド (http://code.google.com/intl/ja/closure/compiler/docs/js-for-compiler.html) に則ってドキュメントコメントを書いている。「こういうアノテーション書くとclosure compilerへのヒントになってよりよい最適化ができます」みたいなことが書いてあるけど、いくつか試した感じでは特にoptimizationが行われている形跡はなかった。コンパイルオプションによって違うのかもしれないけどね。

文句ばっかで恐縮だが、jsdocはjavadoc由来のせいかJavaScriptの一般的なコードにあまりそぐわないアノテーションが多い気がする。微妙にかゆい所に手が届かない、というか。でもそれだけのためにオレオレフォーマット作ってもなんなので、難しいところ。

終わりです

なんか色々ごちゃごちゃ書きましたが、Riddle.jsについては生暖かく見守って頂けると幸いです。