読者です 読者をやめる 読者になる 読者になる

八発白中

はてなブログに引越しました。

Day 25: Utopian

advent-calendar/2016

メリークリスプマス!

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

今日はUtopianについて話します。

アドベントカレンダー最終日

このアドベントカレンダーも今日が最後ですが、テーマになっているプロダクトのリリース日がだいたい時系列になっていることに気づいていましたか。

CL-TEST-MOREから始まってClack、Cavemanなどのフレームワークがあり、途中にIntegralやWooなどもありました。

そして最後が今日のUtopianです。これはまだ開発中であり、そういう意味では未来の話とも言えるかもしれません。

未来はどこにあるか

2011年10月、Shibuya.lispのLTで「深町英太郎はどこへ向かっているのか」というトークをしました。

タイトルはネタっぽいですが5年前から向かうべき場所としてのUtopianが出てきています。

Utopianとは何か

アリエルで松山さんと働いていたときにClackとCavemanを作りましたが、それでもCommon LispでWebアプリケーションを作るには足りないものが多すぎました。DB周りはほとんど整備されてないし、テンプレートエンジンも心もとありません。Webサーバーも実績不足でどこまで実用に耐えうるのか疑問でした。

最終的にはRailsのようなフルスタックなWebフレームワークも欲しい。それはClackよりもCavemanよりも高い抽象度になるだろう。名前はどうする。薄いフレームワークが原始人だったから、厚いのは未来人? いや、そういう年代の違いではないだろう。もっと夢のような。じゃあ桃源郷? Utopianか?

そうして夢の話をしてるうちにその名がプロジェクト名としてしっかりとした重みを持ち始め、向かうべき象徴となりました。

そして、Utopianは長くGitHubの空のリポジトリとして放置されていましたが、ついに今年の2月にMitoを基幹としてUtopianの開発が始まりました。

「いつ完成するんですか」という質問をたまにされます。わかりません。まだまだ遠いような気もします。

おわりに

UtopianはGitHubで開発中です。

では皆さん、良いお年を。

Day 24: Mito

advent-calendar/2016

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

今日はMitoについて話します。

Integralの失敗

11日目のIntegralの「抽象化の失敗」のところで取り上げましたが、Common LispのORMとして作られたIntegralはPostgreSQLのサポートに失敗し、サポートするには根幹部分から再設計が必要となりました。

その後dataflyを作ったりして、ORMよりももっと軽量なライブラリを好んで使っていました。けれどそれも、サムライトでIntegralを採用してから話が変わってきました。

いよいよ真面目にメンテナンスしないといけなさそうだけれども、Integralに手を入れ続けるのは限界がありそうです。そこで自信を持って使ってもらえるORMは必要だなと思って一から書き直したのが「Mito」でした。

Mito

Integralの経験を活かしてMitoでは慎重に抽象化を行いました。具体的にはdefclassCREATE TABLE文と紐付けるメタクラス層と、そのメタクラスをData Access Objectとして扱えるようにするメタクラス層で分離しました。

また、Integralではdefclass:typeRDBMSのカラム型に変換できる機能もあったのですが、Mitoではそこまでの高度な抽象化はしませんでした。そのため少し保守的な設計になっていますが、何よりちゃんと動くことが大事です。

最近は僕もいくつかのプロジェクトでMitoを使っており、マイグレーションも含めて問題なく動いています。

名前の由来

どうでもいいことなんですが、「なんでMitoって名前なんですか」とサムライトの社内ミーティングで訊かれました。

Mitoというのは京都市動物園にいるアジアゾウの「美都」からつけました。

これは猛暑真っ只中の写真で、飼育員さんに水浴びしてもらっているところです *1

f:id:nitro_idiot:20130817131454j:plain

飼育員さんがプールに入らせようと好物のりんごをプールに放ったのですが、プールが嫌いな美都は鼻を伸ばしてりんごだけ取っています。水こわいけどりんごは食べたい。

なぜアジアゾウの名前をつけたかというと。

昔、ElephantというCommon Lispのオブジェクトストアがありました。このAPIはよくできており、CLOSオブジェクトを永続化させるという高度な抽象化を行っていました。このElephantには問題も多かったのですが、目指した夢としての印象は僕にとっては強烈で、僕のORMにもその心意気は込めたいと思ったからです。あと愛着が湧くからです。美都かわいい。

まったく技術的な話ではありませんでした。

おわりに

MitoはGitHubで公開されており、現在Starは35ついています。

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

*1:写真は2013年当時のゾウ舎。今はゾウ舎が移築されて広くなっており、ゾウも4頭増えています。しばらく美都は奥のゾウ舎から出てこなくてまったく会えなかったのですが最近は見られるのでしょうか。

Day 23: Psychiq

advent-calendar/2016

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

今日はPsychiqについて話します。

はてなでの経験

僕の経歴の中ではてなで働いていた時期はあまりOSS活動もせず、Common Lispを書いていませんでした。仕事がPerlということも理由の一つでしょう。

けれど直接的ではないにせよはてなでの経験は少なからず僕の活動には影響を与えています。Webアプリケーションのサーバーサイドからフロントエンドまで担当でき、どのようにWebアプリケーションを構成し運用するかを学ぶことができました。どこがボトルネックになりやすいのか、長期的に運用する上でどういう面が問題になるのかなどの生きた知見が得られました。

はてなではWebフレームワークから作ることもそう珍しいことではなく、その経験はCaveman2の開発にも活かせたり。

その過程でCommon Lispに足りないものもありました。それがメッセージキューでした。

メッセージキュー

メッセージキューはアプリケーションで実行に時間がかかりそうだが同期的にやらなくてもいいものを他のプロセスやスレッドに投げて非同期で実行できるミドルウェアです。

はてなではTheSchwartzを使っていました。サムネイル画像を作ったり動画の変換、通知やその他バッチ処理を走らせたりするのに使われていました。

最近だとAmazon SQSとか使ってるところが多いんでしょうか。

必ずしもすべてのアプリケーションで必要なわけではないですが、必要になったときにCommon Lispになければ導入が困難になるかもしれません。

Lesque

そこで2014年の1月に作ったのが「Lesque」です。

これはRubyのResqueを元に作ったメッセージキューでした。作ったタイミングとしてははてなを退職する少し前くらいで、それから新しいWebサービスを作るのに必要だと見越しての開発でした。

blog.8arrow.org

Psychiq

さて、Lesqueを使ったはいいものの当初の予定とはかなり違って、使う機会のないまま日は経ちました。

そして2年後、とうとうLesqueを使えるかもな、というタイミングで見てみると、そのコードは古いですしCommon Lispの環境にもついていけておらず継続して開発するのもためらわれるものでした。この2年でRoswellがスタンダードになったにも関わらずRoswellスクリプトが提供されていなかったり、Travis CIでのテストが行われていなかったり。

メッセージキューの世界でも世代交代がありました。Sidekiqという新しいプレイヤーが現れました。Resqueのプリフォークスタイルではなく、スレッドを使うため高速に動作し、シンプルなアーキテクチャであるということが売りのようです。

そこで新たにSidekiqをCommon Lispに移植することにしました。それが「Psychiq」でした。

blog.8arrow.org

落語Bot

とはいえPsychiqもそれからしばらく使うことはなかったんですけど、先日とうとう使う機会がありました。

11月の末にLINE Botの「落語Bot」をリリースしました。これは落語の定席や落語家のスケジュール検索ができるLINE Botです。現在、その落語会情報のクローリング部分にPsychiqを使っています。

Psychiqを使ってみてJonathanのバグを見つけたりCL-DBIの問題を見つけたりとかありましたが今のところ順調に動いています。

おわりに

PsychiqはGitHubで公開されており、現在のStar数は16です。

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

Day 22: cl-coveralls

advent-calendar/2016

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

今日はcl-coverallsについて話します。

CI

Common LispTravis CIのオフィシャルサポートはありませんが、cl-travisやRoswellを使って複数処理系をテストすることができます。

Common LispライブラリのCIは僕にとってはなかなかライフチェンジングで、今まで手元でSBCLでテストしてpushしていたのがClozure CLでは落ちるとかがすぐわかったり。CL-DBIのようにテスト用にRDBMSをたくさん用意しなければいけないようなものもPull Requestでテストできるのでパッチをもらっても安心してマージできます。

僕のライブラリはもちろんのこと、他の新しいライブラリでもTravis CIは当たり前に使われるようになりました。

しかし、それだけでは足りません。

テストがなくてもbuild passing

κeenさんのテンプレートエンジンのZenekindarl *1Travis CIでのテストが行われており、READMEに「build passing」という緑のバッジがありました。

しかし、じゃあ使えるのか、品質が高いのかというとそうではありません。当時はまだ機能を実装中でありテストもほとんどなかったのです。

このバッジだけでは品質の保証はできない。そこでテストがどれだけ書かれているかをカバレッジとして出すのはどうだろうと考えました。

他の言語ではテストカバレッジを表示するのにCoverallsというサイトを使っていました。Travisでテストを実行したときにカバレッジを計算し、JSONをCoverallsに投げることで表示されます。

Common LispはCoverallsではサポートしていないのでAPIを叩いてどうにか作りました。

それが「cl-coveralls」です。

カバレッジを表示することの意義

カバレッジは無意味だ、テストが十分かどうかはわからない、という意見もあるかと思います。もちろんそうです。けれど、無意味ではないと思います。テストが十分かはわからずとも、テストが不十分なときをいくらか拾えますから。

おわりに

cl-coverallsはGitHubで公開されており、Starは17ついています。

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

*1:当時はArrowsだったか

Day 21: Lack

advent-calendar/2016

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

今日はLackについて話します。Rackではないです。

Clackの高速化

サムライトに入社してWooによるサーバーの高速化を主な課題と取り組んでいましたが、アプリケーション全体で見ればその基盤部分のClackの高速化も重要でした。Wooは十分に高速だけど、Clackに載ることで大きくパフォーマンスが下がるなら残念なことです。

まあ正直、当時でも十分な速度は出ていたんですけどね。ずっと高速化ばっかりやってたので頭がもう高速化脳になっていて、何でも高速でなければ気がすまなくなっていたんでしょう。

疎結合性を確保しつつなのでWooのようにinline化や型宣言などの高速化のテクニックは使えませんが、それでもClackに速度面で改善の余地はありました。

ClackではComponentもMiddlewareも全部CLOSクラスになっており、Clack.Builderでビルドしたとしても実行時にメソッドディスパッチが挟みます。これをフラットなクロージャーにするだけで少しは高速化できるのではないか、と考えました。

実はこれには違う目論見もありました。

Clackを使うメリットは疎結合性でした。けれどClackのコアは開発の過程でだんだん大きくなり、依存ライブラリもまた多くなりました。単にclackupをしたいだけで、セッションを使わないアプリケーションだとしてもClack.Middleware.Sessionで使われているIroncladまでロードされてしまいます。

こういった目的意識を持って、高速に、もっと疎結合に、そういう意図を持って作り始めたのが「Lack」です。

LackはClackから分離したもの

LackはClackからアプリケーション構築フレームワーク部分を抜き出したライブラリです。ミドルウェアやLack.Builderなどがここに入ります。

Clackにはハンドラーが残り、Webサーバーの抽象化ライブラリの役割だけを与えました。

Common Lisperの多くはWeb開発に疎く、最近のWebアプリケーション構築にキャッチアップできているわけではありません。そういう中でClackは説明が難しかったですし、LackとClackの2つの目的別のライブラリに分離したほうがわかりやすいかなという意図もありました。

Lackの疎結合

Lackが提供する疎結合性は完全なものです。Middlewareはもはや単なるクロージャーを返すクロージャーであり、Clack.Middlewareを継承する必要がありません。これはLackのミドルウェアがLackにすら依存しなくてもよくなったという意味でもあります。

意味わかりますか。LackのミドルウェアがLackに依存する必要がないのです。単に呼び出すとappをラップしたapp (関数) を返すだけなんです。そのルールに従っていればLack.Builderに渡すことができます。

Lackというのはアプリケーションを構成するルールのようなものです。つまりは仕組みは単なる関数群ですし、自前でLackのような新たな疎結合フレームワークを構築することもできます。

ちなみにClackについても依存の形式は同じです。たとえば、WooがClackに依存していないというと驚かれることがあります。ningleやCavemanもClackに依存していません。ライブラリごとに必要な部分だけをロードできることでロード時間が短くなりますし、柔軟に部品を入れ替えてアプリケーションを構築できるようになります。

速度

リリース当時に取ったベンチマークによると、結果的にLackはClackの1.1倍程度の高速化に成功しました。

Hunchentootより1.25倍の高速化とも書いてあります。勘がいい人は不思議に思うかもしれません。ClackでもLackでも裏側はHunchentootなはずなのに、なぜ素のHunchentootより速いのか。

理由はHunchentootのセッションミドルウェアです。セッション処理が遅すぎるためHunchentootはClackと比較しても遅くなっています。

おわりに

LackはGitHubで公開されており、Starは30ついています。

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