Day 12: Qlot
これは fukamachi products advent calendar 2016 の12日目の記事です。
今日はQlotについて話します。
背景
はてなを退職することが決まってから、今までできていなかった開発時間を取り戻すかのようにCommon Lispを書き続けました。当時は起業する気でいたのですが、まだまだWebサービスを作るために足りないライブラリはいくつもあったからです。
ここから数日間のアドベントカレンダーのプロダクトはこの期間に作られたものです。どれも必要でありながら手がつけられていなかったものです。
Quicklispをプロジェクト毎に
Quicklisp のβリリースから3年以上経ち、もはやQuicklispはCommon Lispの開発にはなくてはならないものにまでなりました。
しかし、問題もあります。アップデートが月に一回なので最新のリリースを使えるようになるまで待たなければいけません。また、いくつかのライブラリだけを古いライブラリを使い続けるといったこともできません。使えるライブラリ群は毎月のQuicklispのdistリリース時のスナップショットであり、柔軟なバージョン指定などはありません。
さらにQuicklispのインストールはユーザーローカルであり、プロジェクトごとに分けることができません。このため複数のプロジェクトを同時に動かしたい場合にも共通のライブラリバージョンを使わなければいけません。お互いのプロジェクトに依存関係がなくとも。
そして、複数人で開発するときにも問題になります。ある人は最新のライブラリを、またある人は数ヶ月前のライブラリを使っているみたいな状況では同じ挙動と保証できません。
これらを解決するのが「Qlot」です。
まあ長々説明せずとも、Rubyで言うBundlerですって言えば重要度がわかる人も多いかと思います。
QlotではQuicklispの個別バージョン指定だけでなく、gitリポジトリやHTTPでのtarballからもインストールできます。
Qlotのやり方
説明するとシンプルな仕組みに思えるかもしれませんが、中では少し複雑なことをやっています。
Quicklispはライブラリを配信する機構だと思っている人も多いかもしれませんが、実はQuicklispのdistを自分で作ってインストールすることもできます。フォーマットさえ合っていればinstall-dist
とupdate-dist
でQuicklispではないライブラリ群をQuicklisp経由でインストールさせることが可能です。
Qlotはこの仕組みを使っています。指定されたgitリポジトリなどを一つのQuicklisp distにしてしまい、ローカルでClackサーバーを立ち上げてinstall-dist
をします。
ここまでしてQuicklispに寄せる必要があったかは作ってみては疑問ですが、依存関係の解決やdist間の優先順位付けなどはQuicklispの標準機構を使えるのでそれほど悪くない設計だと思います。
ASDF拡張という可能性の否定
たまに、独立したqlfile
ではなくASDFの:depends-on
に書けたほうがいいのではないかという意見を聞きます。そのほうが依存関係を明示する場所が1ヶ所になるというメリットがありますが、ASDファイルにそのような情報を記述するのは難しいです。
おそらく指定のgitリポジトリを指定するだけを想定しているかもしれませんが、ではそのgitリポジトリが更新されたときはどうでしょうか。ロードする度に使うバージョンが結局固定できません。つまり、qlfile.lock
に当たるものがないのです。
リビジョンまで指定してしまえばいけないことはないかもしれません。けれど更新が面倒ですし、ASDファイルのロード時にどのQuicklisp distを使うかという情報が決まらないならばどのバージョンがロードされるかは環境依存になってしまい危険です。
おわりに
QlotはGitHubで公開されており、Starは78です。
Common Lispでチーム開発をするところやデプロイの必要なWebサービスなどを作っているところでしか必要にならないのでそれほど使われている印象もなかったのですが、最近はプロキシ対応のPRがきたりして意外にもこっそり使われているのかもしれません。
明日のアドベントカレンダーは13日目のwebsocket-driverについてです。お楽しみに。