Mojoを使って自作ウェブアプリをよりポータブルに!

第4回Mojoの歴史と展望

MojoとHTTP::Engine

ここまでMojoとそのサンプルフレームワークであるMojoliciousについて見てきましたが、国内でもYappoこと大沢和宏さんとtokuhiromこと松野徳大さんが中心となって、HTTP::Engineという同じような趣旨のフレームワークが開発されていることをご存知の方も多いと思います。今回はそのHTTP::EngineとMojoを比較しながら、Mojoの歴史や展望を見ていきましょう。

HTTP::Engineの誕生

HTTP::Engineも、もとをただせばMojoの作者ゼバスティアン・リーデル(Sebastian Riedel)氏が4年ほど前にリリースしたCatalystというフレームワークから派生したものです。だから、Mojoとは義理のおじ、あるいは いとこ・はとこ くらいの関係になるでしょうか。

CatalystもCPANモジュールをつなぐ「触媒」と言われていたくらいで、もとよりWSGI的なミドルウェアになる素質は持っていました。ところが、原作者リーデル氏や、その後メンテナンスを引き継いだ開発チームがコミュニティを根底から揺るがすような方針変更を繰り返したため、Catalystの周辺モジュールに対する期待感や信頼感はがた落ちしていきます。あれもだめ、これもだめという具合にブラックリストに載る周辺モジュールの数が増えていった結果、結局コアのエンジン部分だけあればよいのではないかという話になったのがHTTP::Engine誕生のきっかけでした。

アプリケーションの書き方に大差はありません

そのインタフェースについては紆余曲折がありましたが、いまではCatalyst(や、Mojo)とは多少異なったものになっています。比較のために連載第1回でとりあげたHelloWorldアプリケーションをHTTP::Engineで書き直してみましょう。lib/HelloWorld.pmからコンテキスト(トランザクション)オブジェクトが消えているのがわかるでしょうか(ここではあえて冗長に書いていますが、実際にはもう少しコンパクトに書くこともできます⁠⁠。

package HelloWorld;

use strict;
use warnings;
use HTTP::Engine::Response;

sub handler {
    my $req = shift;
    my $res = HTTP::Engine::Response->new;
    $res->status(200);
    $res->headers->content_type('text/plain');
    $res->body('Hello HTTP::Engine!');
    return $res;
}

1;

スタンドアロンサーバを起動するためのスクリプトはこんな感じです。

#!perl
use strict;
use warnings;
use lib 'lib';
use HTTP::Engine;
use HelloWorld;

HTTP::Engine->new(interface => {
    module => 'ServerSimple',
    args => {
        port => 3000,
    },
    request_handler => 'HelloWorld::handler',
})->run;

このくらいのアプリケーションであればlib/HelloWorld.pmの中身をスクリプト内部に書いてしまうこともできるのですが、それはさておき、HTTP::Engineのアプリケーションの書き方も、基本的にはMojoの場合と大差ありません。開発コミュニティが日本人に偏っていたとはいえ、Catalystの開発チームからはおおむね好意的に迎えられた結果、HTTP:EngineのIRCチャンネルには海外の開発者の姿も見られるようになっていました。リーデル氏にはHTTP::Engineの改善を進めるという道もあったはずです。

それなのに、なぜリーデル氏はあえてMojoを生み出したのでしょうか。

DRYとDIY

MojoとHTTP::Engineのもっとも顕著な違いは、CPANモジュールに対する態度といえます。

HTTP::Engineや、そのもととなったCatalystは、Perl界の定石にのっとって、定番のCPANモジュールがあればなるべくそちらを利用するような形で開発が行われてきました。

ただし、定番のモジュールといっても、かならずしもインターネットの標準に準拠しているとは限りません。速度や手間とのトレードオフを考えて手抜きが行われていたり、そもそも標準が制定される前の実装であったりと、理由はさまざまですが、どこかしら不完全な部分を抱えているものです。

たとえば、HTTP::EngineやCatalystが利用しているHTTP::BodyやCGI::Simpleには、いまなおRFCに準拠していない箇所があるというバグレポートが届いていますし[1]⁠、スタンドアロンサーバに利用しているHTTP::Server::SimpleもHTTP/1.1の機能をフルに実装しているわけではありません。

そんなHTTP::EngineやCatalystを反面教師に生まれたMojoは、一部のコアモジュールを除いて外部のモジュールは利用していません。フォームデータのパースも、URLの操作も、リクエストやレスポンスの取り扱いも、すべて自前で行っています。

リーデル氏のねらいは、ともすれば標準が定まる前からあるような古いモジュール、実装の不十分なモジュールを一掃することで、つもりつもったバッドノウハウや古びたインタフェースに引きずられることなく、より現代的な、標準に準拠した、統一感のある実装を行うことにありました(これまで詳しく取り上げませんでしたが、paramメソッドひとつとってもCGI.pmなどのparamメソッドとは細かな挙動が異なっています⁠⁠。

リーデル氏は現在CPANにあがっているモジュールのなかでMojoだけがクッキーを正しく処理できると主張していますが、その是非はさておき、インターネットの標準に対する意識が高いことはリポジトリにRFCのテキストが含まれていることからもうかがえます。

初心者にもやさしく

また、ウェブアプリケーションは初心者の独習用教材となることも多いため、Mojoは、初心者にコードを読んでもらうことも念頭において書かれています。Mojoにはコーディング規約が定められていますが(lib/Mojo/Manual/CodingGuidelines.pod⁠⁠、そこにはコードはシンプルにまとめるべしといった記述のほかに、できれば読んで楽しいコメントをつけるようにという記述も見られるほどです。

ただし、コードを読んでもらうには、まず使おうという気になってもらう必要があります。インストールに困るようなモジュールのコードを読む人はいません。

HTTP::Engineも最近はずいぶん手軽になったので比較の対象とはなりづらくなっていますが、圧縮ファイルを解凍すれば使える、FTPでレンタルサーバにアップロードするだけで動かせるというMojoの依存関係の少なさは、この点でも大きなメリットでした。

なにしろこの文脈でライバルとなるのは、資料や実績が豊富で初心者の目にもとまりやすく、単一ファイルでアップロードも簡単な、コアモジュールのCGI.pmです。10年以上前のコードではなく、いまのコードを参考にしてもらおうと思ったら、インストールはどれだけ簡単でも簡単すぎることはありません。当時インストールにコンパイラが必要だったHTTP::Engineとは、この点でも大きく方針が異なっていたわけです。

再発明の影

もちろんこのような車輪の再発明にはかならず影の部分もあります。

たとえば、Mojoにはまだ十分なテスト体制が整っていません。テストそのものも少ないですし、歴史が浅くコミュニティも育っていませんから、コードをチェックしてくれる人の数も多くありません(この点ではHTTP::Engineも似たようなものですが、こちらは一度大きな書き換えがあった分、後退テストが充実しています⁠⁠。標準に沿って実装したといっても、それを担保してくれるテストがなければ絵に描いた餅にすぎないわけで、TODOファイルにはMojoの永遠の課題としてRFCに対するテストが明記されています。

Mojoが独自のアクセサ/ミューテータを用意したことに対しては、Catalystとその関連モジュールがいたずらに多くのアクセサモジュールを利用していることに辟易してMooseに全面移行することをめざしていたグループから、⁠屋上屋を架すな」と激しく非難されました(HTTP::EngineはMooseを採用することでこの批判から免れたのですが、のちに高速化のためShikaというモジュールを採用したときには同じように非難が寄せられました。いまはMouseというモジュールに切り替えて難を逃れています⁠⁠。

また、理想を追求するあまり後方互換性を無視した変更を繰り返した過去の経緯から、リーデル氏のソフトウェアやプロダクト管理そのものに不信の目を向ける人もいます。氏はCatalystのエンジンをMojoで置き換える提案もしていたのですが、Catalystの開発陣の中には氏がプロジェクトから去ったら検討してもいいとまで言い放つ人もいたくらいで、いまのところにべもなく拒絶されています。

もっと利用者を増やすために

そういった感情的なしこりや、政治的な思惑の混じった批判はさておくとしても、Mojo(やHTTP::Engine)のような抽象化の進んだフレームワークは、単体ではなかなかその魅力をわかってもらえません。このようなミドルウェアは、それを組み込んでくれるアプリケーションやフレームワークがあってこそ真価を発揮します。

前回紹介したMojoliciousは、Catalystの開発チームにMojoの可能性を見せるために開発されたサンプルでした(Mojoliciousという名前は、MojoとCatalystを組み合わせたMojolystから生まれたものです⁠⁠。サンプルと繰り返し強調しているのは、できあいの周辺モジュールをそのまま利用しようとして、スタイルの不一致や機能の衝突に悩まされたCatalyst時代の反省なのでしょう。Mojoliciousは、実際にはMojoと、いくつかの拡張モジュール(MojoX::*)を組み合わせてつくられています。気に入らない部分はどんどん差し替えてもらってかまわないし、気に入った部分はどんどん使ってもらってかまわない(そうすることでもっと採用フレームワークが増えてほしい)というのがMojo(licious)のスタンスです。

また、実際のコードだけでは敷居が高かろうということで、リーデル氏は昨年末、The Perl FoundationにMojoの文書化計画の助成金を申請して、無事受理されました。順調にいけば、春先までには初心者向けのガイドやさまざまなコード片からなるクックブック、追加のサンプルアプリケーションなどが用意されることになっています[2]⁠。

見通しはやや不透明でしたが

残念なことに、リーデル氏が昨年12月に医療事故に遭ったことからMojoの開発は一時ストップしていましたが、2ヶ月ほどの長い「冬期休暇」をはさんで、昨日ようやく開発に復活できる旨のアナウンスがありました。ところどころバグが残っているとはいえ、Mojo本体はもう正式リリース間近なところまで仕上がってきていますから、これからまた開発が進むことが期待できます。

その昔、CGI.pmがその前身ともいえるcgi-lib.plを呑み込むことでひとつの時代が終わったように、MojoがCGI.pmを呑み込む日がくれば、Perlを取り巻く環境も変わるかもしれません。

Mojoはまだ生まれて4ヶ月という若いプロジェクトでもあり、コミュニティも小さく、まだめだった実績もありませんが、リーデル氏のポテンシャルの高さはPerl界を代表するフレームワークに育ったCatalystで実証されています。

いますぐに、とはいいません。MojoのかわりにHTTP::Engineを使ってもよいと思います。が、もしこの先CGI.pm(や、それすら使っていない昔ながらのCGIアプリケーション)に触れる機会があったら、ぜひもっと現代的な代替品を試してみてください(あるいは、試すようにすすめてあげてください⁠⁠。実際に本番サーバの環境を変えることはないかもしれませんが、開発やテストを統一的な環境で行える(本番と同じ環境を構築する必要がない)だけでも利用する価値は十二分にあるはずです。

おすすめ記事

記事・ニュース一覧