3年以上前に過去形で語っている話ですが、かつて自分の作ったバグを記録していたことがあります(http://dev.ariel-networks.com/blog/inoue.php?blogid=2&archive=2004-9-17)。

この時の結論は、バグの大半がAPIの仕様の理解不足から生じていた、でした。ここの「API」という用語は、非常に広義な意味で使っています。21世紀になって自分の作るバグの多くがマルチスレッド絡みになってきたという変化はありますが、APIの仕様の理解不足がバグの要因として大きい事実は変わっていません。

上記の記事では、次のようにも書いています。

当時、言語仕様の理解不足で生じるバグを作ることは無くなっていました。

ほとんどC言語オンリーで、かつ充分に経験を積んでいたので、言語仕様の理解不足で作るバグはありませんでした。

時代の要請か、多くのプログラミング言語を使う機会が増えました。ひとつひとつの言語に対する理解が浅いせいか、今の方が言語仕様の理解不足で作るバグが増えたようです。先日のRubyで作ったバグ(http://dev.ariel-networks.com/Members/inoue/ruby-and-bugs)も、この例です。

言語が高級になっていることも要因のひとつかもしれません。いくつかはコンパイル型言語でないことも影響しているかもしれません。長らく、コンパイラにバグを見つけさせる技術を磨いてきたので、コンパイラが無いと大きな武器を失った気分になるのです。

今日はJavaScriptでのバグの話です。実は自分の作ったバグではありませんが、恐いバグだと感じました。

バグには、恐いバグと恐くないバグがあります。バグを作っても、今後、同じようなバグを作らない対策を打てるバグはあまり恐くありません。ある種のコーディングで同じバグを防げることが分かるなら、バグの経験は良い経験です。一方、同じようなバグを作らない対策が、今後気をつける、しか無いバグは恐いです。注意していても忘れるからです。うっかりコードを書いてもバグを防ぎたいのです。ミスはコンパイル時に検出できればベストです。最悪でも実行時にそれと分かりたいのです。このために、いわゆる防衛的なコーディングとして知られる技術があります。

JavaScriptの恐いバグの話に戻ります。

prototype.jsのバージョン1.5.xを使っていたコードでした。そのコードはElement(prototype.jsが定義したクラス)のオブジェクトに独自に select というプロパティを加えていました。用途はフラグ変数でした。

prototype.jsのバージョンをv1.6.0.2に上げた時、問題が発生しました。prototype.js側で、Elementクラスにselectというメソッドが追加されていたためです。フラグ変数を期待していた参照箇所がすべて真になりました。

些細な話と思うのは簡単ですが、ぼくはこの話を聞いて恐いと思いました。外部ライブラリの更新で壊れるコードは、JavaScriptに限りませんが、このケースの場合、決してエラーは起きませんし、防衛するためにどう書けばよいのか分からないからです。

selectはフラグとして名称がおかしいので、selectedにすべきだった、という指摘はもっともですが、プログラマはそんなに予知的ではありません。第一、この指摘は本質的ではありません。selectedというプロパティがprototype.js側で追加されれば同じことだからです。