八発白中

技術ブログ、改め雑記

Day 7: CL-DBI

これは fukamachi products advent calendar 2016 の7日目の記事です。

今日はCL-DBIについて話します。

フレームワークバトルは次のステージへ

Cavemanに一定数のファンがついた頃、Star数がRESTASに並びました。そのとき僕はうれしくて、@snmstsさんに言いました。「佐野さん!CavemanがようやくRESTASを超えたよ!」

すると佐野さんが言ったことはCommon Lispフレームワークの歴史的な一幕です。

「もうCommon Lispフレームワーク同士で争っていても仕方がない。他の言語と比較して優位性が出せなければ」

他の言語のフレームワークと比較してCavemanはどういった利点があるのか、ということを言えなければCommon Lispの導入など到底できないということです。

なんでPerlを書いてるの?

はてなで働いている頃の話。確か東京から@m2ymさんが遊びに来たときだったと思います。はてなエンジニアたちで御池通間之町を下がった「みまでり」という店に行きました。奥の階段を昇って2階の手前のテーブルに座ったことまで覚えています。

酒も2杯目くらいでほどほどに料理も食べたとき id:antipop さんがおもむろに「にとろ君、なんでCommon Lispで(仕事のコードを)書かないの?」といつもの調子で絡んできました。

いつもの調子、というのは、僕が個人的にCommon Lispが好きであり趣味のコードはCommon Lispで書いているにも関わらず仕事で平気な顔でPerlなんて書いているのか、全部Common Lispにしちゃえよ、という無責任な煽りです。

ひょっとするとCommon Lispで書くことや技術力に自信がないからじゃないの?という含みもあったかもしれません。

もちろん僕はCommon Lispが好きですが、すべてのプログラムをCommon Lispで書くべきだと思っているわけではありません。ライブラリや結合予定のアプリケーションとの都合もあります。チームで開発する場合は自分以外のメンバーのスキルセットも考慮する必要があるでしょう。やりたいことと天秤にかけて実現可能性が高いほうを選びます。Common Lispで書いてもプロジェクトが失敗すれば意味ないですからね。

当時、はてなの規模のWebサービスCommon Lispで書くのはかなりチャレンジングだったでしょう。そして実現可能性はPerlに比べて極めて低かったです。僕がそのときantipopさんに言ったマジレスの一つはDBIの欠如でした。

DBI

DBI (Database independent interface) とは使うRDBMSに依らずに統一したインターフェイスを提供するライブラリです。最近の言語では標準ライブラリとして付属していて当然ですが、Common Lispには標準ライブラリがありません。

Common Lispに当時あったのはCLSQLでした。ただこれが恐ろしく使いづらい。なんで使いづらいのかうまく説明できないのだけど、おそらくインターフェイスをリッチにしすぎているために抽象レイヤーが厚くなっていてわかりづらいのかなと思われます。いわゆるORMのような機能も入っていました。また、コードとしてもとても古くFFIとしてUFFIという今では非推奨となっているライブラリを使っています。開発も止まっておりメンテナンスも十分ではないようです。

これを改善していくよりも新しく作ったほうがよかろう。そう思ってより薄い抽象レイヤーで、DBの統一インターフェイスの提供のみを行うライブラリを作りました。それが「CL-DBI」です。

2つの統一インターフェイスの違い

統一インターフェイスという意味でCL-DBIClackと似ているかもしれません。

Clackは各Webサーバに対して統一的なインターフェイスを提供することで、同じアプリケーションをコードを書き換えることなくまったく別のWebサーバーで動かすことを可能にしました。一方でCL-DBIは使うRDBMSを自由に切り替えることができます。

しかし、作ってみてわかったことですが、CL-DBIの抽象化は不十分でした。

RDBMSは汎用的なSQLという言語を使ってデータにアクセスできるという意味で共通ですが、そのSQLRDBMSごとに微妙に違い、同じSQLではエラーとなる場合が多々あります。たとえばMySQLにはAUTO_INCREMENTがありますが、PostgreSQLの場合はSERIAL型を使い、実装もsequenceとしてテーブル定義とは別扱いになります。SQLiteはAUTOINCREMENTです。さらにインデックスはありません。

そのため、CL-DBIはClackのようにまったくコードを修正しなくても動く、というほど理想的ではないのです。

また、需要の面でも違いがありました。

Webサーバと違ってRDBMSの場合は複数種類を使うというユーザーが少ないです。MySQLファンはPostgreSQLは使わないですし、PostgreSQLファンはMySQLを使いません。そういう意味で、PostgreSQLだけ使うつもりの人はCL-DBIではなくcl-postgresやPostmodernで十分なのです。それにPostmodernは可搬性を捨てた代わりにPostgreSQL独自の機能が使えるというメリットを掲げています。

CL-DBIの有用性

それではCL-DBIは失敗だったのか。他の言語で当たり前になっている統一インターフェイスは間違ったデザインなのか。

結果から言えばそうでもありませんでした。

CL-DBIはとても薄い抽象レイヤーのため、Webアプリケーションで使おうと思ったらもう少し扱いやすくしたものを使いたいという願望が生まれます。そこでCL-DBIを前提としたツールが作られました。それがIntegralCranedataflyMitoなどです。

CL-DBIを使ったこれらの周辺ツールは、一つのRDBMSには依存しません。*1 そのためMySQLユーザもPostgreSQLユーザも共通して使うことができます。

共通のツールを使えるということはいくつもの利点があります。知識がユーザ間で共有しやすく、コミュニティを形成しやすくなります。さらに、同じライブラリの開発者も増えることが見込めます。バグ報告も増え、クオリティの向上にも有利です。

CL-DBIは僕のプロダクトの中では結構初期からあるライブラリですが、年を減るごとに重要性は増しています。

おわりに

CL-DBIGitHubで公開されており、現在Starは74です。

明日のアドベントカレンダーは8日目のShellyについてです。お楽しみに。

*1:IntegralはSQLの抽象化ができていないためPostgreSQLに対応していません。これは後継のMitoにより解決されています。