相変わらずうまいなあ。
ユーザーは狭く見る - レジデント初期研修用資料Chrome の速さだとか、Gmail の軽さみたいな感覚を、もうすこしきれいに言語化できると、幸せになれる人が多いと思うんだけれど。
というわけで、それを言語化する試み。日本語だけじゃなくてJavaScriptとかも混じっちゃったけど。
何かをお願いしたあと、たぶんたいていの上司は、その人が視界から消えるまでの時間でもって、その人の「使える度」を判断する。
実は我々はすべて自分のパソコンの上司どころか王様で、そしてパソコンは部下どころか奴隷である。そして、その奴隷をいかに「使えるようにする」かがプログラマーの仕事。
「まじめなグズ」は、まじめだから、上司がいる目の前で、問題の検討を行って、分からないことは、目の前の上司に尋ねる。やりかたは正しいんだけれど、「まじめなグズ」は、上司の視野からいつまでも立ち去らないから、ウスノロ扱いされてしまう。
というわけで、簡単な仕事をあなたのブラウザーにやってもらうことにしよう。「ボタンを押したらボタンの表示を"Running..."にして、さらに一秒たったら"Done."にして、そしてその一秒後に元の名前である"Run"に戻す」という簡単なお仕事だ。
まずは「まじめなグズ」「まじめなグズ」は上司の目の前で仕事をしてしまう。その結果どうなるか。
function sleep(ms){
var started = +(new Date);
while(+(new Date) - started < ms) { /* do nothing */ }
return;
}
var button = document.getElementById('ex0');
button.value = "Running...";
sleep(1000);
button.value = "Done.";
sleep(1000);
button.value = "Run";
どうなっただろうか?なんと、ウスノロどころかきちんと要求さえ満たしていない。二秒間ただボタンが押されっぱなしになってそれでおしまいだ。Unix上の通常のプログラムならこれで正解なのに、JavaScript では関数の実行中は文字通り「仕事をしている」ので、ブラウザーは何も出来なくなってしまう。
「使える奴」は、こうなる。
var button = document.getElementById('ex1');
button.value = "Running...";
window.setTimeout(function(){
button.value = "Done.";
window.setTimeout(function(){
button.value = "Run";
}, 1000)
}, 1000);
今度はうまく行く。何が違うのだろう。
それが、「やる」と「やっておく」の違いである。「まじめなグズ」は「ボタンを押したらボタンの表示を"Running..."にして、さらに一秒たったら"Done."にして、そしてその一秒後に元の名前である"Run"に戻す」をそのままプログラムしたが、「使える奴」は、「ボタンを押したらボタンの表示を"Running..."に」しておき、それが終終わって一秒後に「"Done."にする」ようにしておき、そしてさらに一秒後に「"Run"に戻すように」しておいたのだ。
ここで、もう一度プログラムを見ておこう、どちらが簡単かといえば、もう圧倒的に「まじめなグズ」な方である。言われたことをそのまま順繰りに「やっている」だけだ。ところが「やっておく」ようにしたとたん、ネストが三重になるのだ。
さらに、上司の気が変わって、「やっぱり"Running...."って表示するだけじゃ進捗がわからないから、10からカウントダウンするようにして」と言われたら、プログラムはこうなってしまう。
var button = document.getElementById('ex2');
var count = 10;
button.value = count--;
window.setTimeout(function(){
button.value = count--;
var next = count >= 0 ? arguments.callee : function(){
button.value = "Done.";
window.setTimeout(function(){
button.value = "Run";
}, 1000)
};
window.setTimeout(next,1000);
}, 1000);
これで、以下のことがわかった。
- 「まじめなグズ」は「やる」、「使える奴」は「やっておく」ことにする
- 「やっておく」というのは、遅延実行のことである。
- 「やっておく」の連鎖で仕事を「やる」のは、仕事を「順序通りにやる」よりずっと手間がかかる。
ところで、先ほど「Unix上の通常のプログラムならこれで正解なのに」と書いた。なぜ正解かといえば、「やる」の連鎖を「やっておくことにする」連鎖に変えるような仕組みがあるからだ。上の例で言えば、それがsleep()の実装だ。Unixにおいてはsleep(n)は「n秒後にここに戻ってくる」ことしか意味しない。だからその間にいくらでも「他のこと」をしていられる。上のように「その時が来るまで延々と時計を見続ける」なんてことはしない。
しかも、実はsleepなんぞしなくても、「やっている」途中でそれを脇にどけて、別の「やりかけ」の仕事をやることさえする。というかそれがUnixのデフォルトであり、それがプリエンプティヴ・マルチタスク(pre-emptive multitasking)という意味である。
残念ながら、今のブラウザーには、上司の「まじめでグズな」命令を、「使える手順」にしてくれるための仕組みは用意されていない。用意されていないので、その仕事はプログラマーの仕事ということになるが、おかげでプログラマーの仕事が「見える化」されるのだからよしあしとも言えるかもしれない。
「やる」を「やったこと」にすると、全体としての手間は増える、それゆえに「やったことにする」を基本とする仕事術のためには、「やる」もずっとテキパキできなければならない。なぜプリエンプティヴ・マルチタスクを普通のパソコン上で出来るようになったかといえば、OSが「やる」アプリケーションを「やったことにする」ように動かしてくれることもさることながら、純粋に「やる」能力が、「やったことにする」ことによって手間の分を補ってあまりあるようになったからだ。
結局のところ、「使える奴」というのは、「まじめにグズ」に仕事をしても「まじめなグズ」より仕事は出来るし、そして実は「まじめにグズに」仕事をすればもっと仕事が出来るものなのである。このことに電脳も肉脳も差はないのではないか。
そうそう。さらに付け加えれば、仕事術というものが、関係者の中で最も「まじめなグズ]にあわせて設計されねばならないというのも、電脳も肉脳の共通点だ。実は JavaScript でも、1.7以降はyield()というものが使えるので、「まじめにグズ」に書いても「やっておく」プログラミングを成立させやすくなる。しかしこれは今のところ Firefox しかサポートしていない。どのブラウザーでも動くようにしたかったら、相変わらず自分で「やっておく」しかないのである。とほほ。
Dan the Thrashing Man
(もちろん重くはなりますよ)