2009年4月 2日

JavaScript

JavaScript の不思議な面白さ - 第五回

  • このエントリーをはてなブックマークに追加

第三回」「第四回」とプログラムの分離とそれによってもたらされる動作速度の変化の検証をおこなってきました。今回は速度を追及する為、多少の犠牲はいとわず速度優先でライブラリ化を進めることとしてみます。

今回からは、プログラミング技術の話にお付き合いください。
再度になりますが、ライブラリ化の目的が、

・ほかの開発者がライブラリを利用することで容易に開発できる
・ライブラリ開発者が独立してプログラムの改善を行える

といった開発効率の向上が目的であることを忘れないでください。
最高速を目指すのであれば「第二回」で示した解答例でよいのです。

前回のルールに沿った形でライブラリ化を行います。

解答例(ライブラリ化)

今回は柔軟な機能拡張の為にクラス化を行ってみます。
表記が異なるだけで基本は関数化と変わりありません。

<script type="text/javascript" src="mylibrary3.js"></script>
<form>
<script type="text/javascript">
new HTMLParts.input({
	id : "input",
	name : "q",
	description : "ここで検索!<img src='new.gif'>"
});
</script>
<input type="submit" value="検索"/>   
</form>

実はライブラリ化のメリットには二つ異なる視点が存在します。
一つは、ライブラリ化されたプログラムを利用する開発者、としての視点です。上記は非常に奇麗に分離されている一例で、利用者としては申し分ない形です。動作速度も速ければ利用者としてはこれ以上ない形でしょう。

この点でライブラリ化は開発効率向上に効果がありました。
そしてこれは「第二回」の答えにもなっています。

解答例(ライブラリ内部)

もう一つがライブラリ開発者としての視点です。
ライブラリ利用者に対して、ライブラリ開発者はライブラリ化によって機能強化やバグ修正などを独立して行うことが出来るという点で開発効率向上の効果を期待しています。

var HTMLParts = function(){}
HTMLParts.input = function(param){
	document.write("<div style=\"color:gray;position:absolute;z-index:2;font-size:9pt;padding:6px;\" id=\""+param.id+"desc\" onclick='document.getElementById(this.id.substring(0,this.id.length-4)).focus();'>"+param.description+"</div><input name=\""+param.name+"\" type='text' id=\""+param.id+"\" onkeydown='if(this.value==\"\"){ document.getElementById(this.id+\"desc\").style.display=\"none\";};' onfocus='if(this.className.indexOf(\"focused\")>=0){this.className=this.className.replace(\"focused\",\"\");return;}if(this.value==\"\"){ document.getElementById(this.id+\"desc\").style.display=\"none\";};' onblur='if(this.value==\"\" ){ document.getElementById(this.id+\"desc\").style.display=\"\";};' />");
}

そしてこちらが mylibrary3.js の中身です。
しかし、こちらはどうでしょう。出来上がったコードをよくよく見ると「第二回」解答例の HTML が解体したものの上にそのまま入っていることがわかります。お世辞にも開発効率向上などとはうたえそうにありません。

それどころか、いくらなんでもこの一行にすべてが詰まった恐ろしいコードをメンテナンスし続けていく自信はとてもなく、例え早いことがわかっていても遠慮願いたいところです。いくら良くても、この手法で完成させることができないのでは机上の空論になってしまうからです。

それこそ「第二回」解答例ですらプログラムの分離が声高に叫ばれる時代、これほどごっちゃになったプログラムがまかり通りそうにはありません。ですが今回はこの時点で完成品として配布を行うという前提では、一応の完成系とも見られるのでこれをライブラリ化後の解答例とします。

合理的に作れば利用者をいらだたせ、速度を追求すれば窮屈、とかく JavaScript の世は生きづらいわけですが、ほかのプログラミング言語に移住するわけにも行かないので、いま一度問題点を洗い出してみましょう。

コードの見やすさとは?

そもそもコードの見やすさ、管理しやすさとは何でしょうか。
さまざまな議論がある分野ですが現在問題になっているのは高度な内容ではありません。

悪い例

<input onkeydown='if(this.value==""){ document.getElementById(this.id+"desc").style.display="none";};' ...
document.write("<input  onkeydown='if(this.value==\"\"){ document.getElementById(this.id+\"desc\").style.display=\"none\";};'   ...

HTML 上に記述されていたり、プログラムが文字列として表現されている為に、改行できず、さまざまなプログラム機能が混ざっている為、コード全体が把握しにくい。

この状態になっているプログラムはたとえ一行にまとめられていても管理が困難になる。

良い例

function onkeydown(){
	if(this.value==""){
		document.getElementById(this.id+"desc").style.display="none";
	}
	...
}
HTMLParts = function(){}
HTMLParts.prototype.onkeydown = function(){
	if(this.value==""){
		document.getElementById(this.id+"desc").style.display="none";
	}
	...
}

適切な場所に改行とインデントが入れられ、プログラムが意味のあるブロックごとに分割、整理されている為に全体が把握しやすい。
この状態を維持してできれば、プログラムが膨大な量であっても管理しやすい。

ということです。

解答例として示したライブラリ内部は、このままでは確かに整理されているとはいえません。確かに見づらいのですが、改行が適切に入ってプログラムが見やすくなればそれでいい、とも考えられます。つまり下記のように考えを変えてみます。

 × HTML 内部にプログラムを入れたから読みづらい
 ○ 改行とインデントが適切に入っていないから読みづらい

つまり HTML が整然とプログラムを組み込めるような構造になっていれば何の問題もなく、そうでないので整然とプログラムを組み込めない部分を補完してやる必要があるいのです。この目的を達成する為に必要なのがフレームワークです。

prototype.js、YUI、JQuery など優秀なフレームワーク/ライブラリが世に多くありますが、今回は速度の計測まで行って異質なコーディングルールまで生まれましたので、これを元にフレームワークを自作してみようと思います。

次回「JavaScript フレームワークを作ろう」をお楽しみに。

(Yahoo!メール開発チーム 田淵純一)

(2009/4/9追記)
>>第六回へ

Yahoo! JAPANでは情報技術を駆使して人々や社会の課題を一緒に解決していける方を募集しています。詳しくは採用情報をご覧ください。

  • このエントリーをはてなブックマークに追加