2012年04月05日

僕はSQLができない

 C.J.Date『データベース実践講義』を読んだ。
 私はSQLが死ぬほど苦手で、少しでも複雑なクエリを書くたびに参考になるものを探す。さっぱり理解できない要素も山ほどある。たとえばIN。主にぐぐれないせいだが。
 なぜ私はこうもSQLが苦手なのか、この本を読んでよくわかった。SQLが糞だからだ。

 どう糞なのか。
・値と変数を分けて扱うことができない。たとえばSQLの「テーブル」とは値なのか変数なのか
・テーブルの値は行の集合、つまり(Javaでいうところの)Setであるべきなのに、Listになっている。シンプルなSetのかわりに、妙なものがゴチャゴチャついたListを使わされるのがSQL
・SQLの型サポートは貧弱で、意味的にありえないクエリがエラーにならない。品物の個数とID番号がどちらも整数型というだけで比較できてしまう
 
 上記の問題点をご覧になって、なにかお気づきにならないだろうか。
 これらはそっくりそのまま、過去30年にわたって耳にタコができるほどさんざん批判されつづけながら、今もなお再生産されつづけている問題にほかならない――汎用プログラミング言語の世界で。
 
 たとえば.NET Frameworkには、JavaのSetに相当するコレクションがない。Dictionaryのvalueを使わないことで代用するものらしい。
 こういう「代用」は空恐ろしいほど日常的に行われている。JavaのSetが必要十分のところで配列やリストを代用することは完全に習慣になっており、問題意識を喚起するのも難しいほどだ。(Array Considered Harmful あるいは、なぜC言語のポインタは難しいのか
 必要十分をはるかに超えたコレクションで代用することのなにが悪いのか? 『Array Considered Harmful』では理解の難しさを挙げたが、SQLはこの害悪の巨大な実例だ。
 
 Webプログラミングの世界には、「サニタイズ」という狂気の言葉がある。「SQLインジェクションを防ぐサニタイズ」という具合に使われる。これは根本的には、「品物の個数とID番号がどちらも整数型というだけで比較できてしまう」という事態を気にしないのと同じ問題だ。
 彼らの頭の中はこうなっている――
・整数型に格納できるデータは整数であり、文字列型に格納できるデータは文字列である
・だから個数とID番号が比較できてもいいし、SQLのクエリを文字列結合で組み立ててもいい
・個数とID番号を比較するのはバグであり、プログラマが「気をつけて」防ぐ
・SQLのクエリを文字列結合で組み立てるときには「サニタイズ」する
 「整数型に格納できるデータは整数」という習慣は、「JavaのSetが必要十分のところで配列を代用する」という習慣とそっくりだ。
 
 以上2点に頷いてくださった向きも、汎用プログラミング言語が「値と変数を分けて扱うことができない」という点は意味不明かもしれない。
 では、クラスのインスタンスを値として、つまり整数の値と同じように扱える機能を備えた、オブジェクト指向の汎用プログラミング言語を挙げてみていただきたい。
 そのインスタンスは当然immutableでなければならない。整数の値10の「中身」をいじって、見かけは10のまま「中身」を11にする方法が存在してはならない。そうした変更をプログラマが「気をつけて」防ぐという回答は禁止する。さて、どうか。主流といえる言語はひとつも挙げられないはずだ。
 言語がそうした機能を備えることを妨げるものは何もない。ただプログラマがそうした機能を欲しないだけだ。プログラマは、少なくとも現在の主流を構成する(ということは必然的に糞な)プログラマは、値と変数の区別を欲していない。
 SQLの「値と変数を分けて扱うことができない」という性質は、こうしたプログラマの習性によく適応している。
 
 著者は「今から数百年後にもリレーショナルモデルが使われていることが容易に想像できる」と書く。そうかもしれない。だが著者が本書で述べているような、まともなリレーショナルモデルの実装が主流になることはないだろう。
 私は、今から数百年後にも、SQLが使われているのではないかと想像する。SQLは、キーボードのQWERTY配列がそうであるのと似た意味で、最後の言語かもしれない。SQLより学習しやすく、生産性が高く、リスクが小さい言語がありうることは容易に想像できる。しかし、大多数の(=平均的な=糞な)プログラマの習性に適応するという仕事をSQL以上にうまくやってのける言語は、おそらく現れない。

Posted by hajime at 21:58 | Comments (0)