前回の(1)はこちら から。
Mojoliciousから見る内部DSLの利点と欠点
まず、Mojoliciousのルーティング定義を通してPerlの内部DSLの一例を紹介し、DSLを使わなかった場合との比較を行います。
Mojoliciousは人気のあるPerlのWebアプリケーションフレームワークです[1] 。ルーティング定義の方法として、
routesオブジェクトにルーティングを定義していくオブジェクト指向的なやり方
RubyのSinatraに端を発した簡潔な内部DSLで定義するやり方
の2種類をサポートしています。それぞれの方法で定義したものが以下です。
オブジェクト指向版
{
package MyApp;
use Mojo::Base 'Mojolicious';
sub startup {
my $self = shift;
my $routes = $self->routes;
$routes->get('/')->to('example#index');
$routes->post('/count')->to('example#count');
}
}
{
package MyApp::Controller::Example;
use Mojo::Base 'Mojolicious::Controller';
sub index {
my $self = shift;
$self->render(text => "Hello, World!");
}
sub count {
my $self = shift;
my $count = $self->session('count') || 0;
$self->session(count => ++$count);
$self->render(text => "Posted $count");
}
}
require Mojolicious::Commands;
Mojolicious::Commands->start_app('MyApp');
DSL版
use Mojolicious::Lite;
get '/' => sub {
my $self = shift;
$self->render(text => "Hello, World!");
};
post '/count' => sub {
my $self = shift;
my $count = $self->session('count');
$self->session(count => ++$count);
$self->render(text => "Posted $count");
};
app->start;
まずオブジェクト指向版を見てみます。ルーティングを定義しているのはルートオブジェクト$routes
のget
、post
メソッドを実行しているところです。これで、
/にGETリクエストが来たらMyApp::Controller::Exampleのindexメソッドを実行する
/countにPOSTリクエストが来たらMyApp::Controller::Exampleのcountメソッドを実行する
というルーティングが定義されます。
次にDSL版のほうを見ています。おそらくこちらのほうは、Mojoliciousを触ったことがない人にもどのようにルーティングされるかがわかるのではないでしょうか。すなわちget
、post
サブルーチンによって、
/にGETリクエストが来たら後続のサブルーチンリファレンスを実行する
/countにPOSTリクエストが来たら後続のサブルーチンリファレンスを実行する
と定義しています。
DSL版の利点
さて、この2つの比較でDSLの利点が見えます。DSLを使ったほうが明らかに簡潔です。誰にとってもわかりやすいですし、開発者はルーティングに集中してプログラムが書けます。そして、これは筆者の主観も入りますが、DSL版のほうがクールに感じます。このクールさだけでもDSL版を書く動機になると思います。
DSL版の欠点
一方でDSL版の欠点はあるでしょうか。
第一に、やはりその学習コストが挙げられます。筆者が初めてDSL版でルーティングを書いたとき、get"/" => sub { my $self = shift; ... };
の$self
に何が渡されているのかわかりませんでした。またルーティングとは少し離れますが、Mojolicious::Liteにはほかにもhelper、pluginなどのDSLのキーワードが用意されています。これらがあること自体、知るのに時間がかかりました。
すなわち、DSLを書くにはまずそのDSLの世界観を知る必要があるということです。その世界観を共有できて初めて、DSLを有効に使えます。
第二に、重複するコードを集約できないことが挙げられます。ある程度ルーティング定義が多くなったときを考えてみてください。この場合、DSL版では1つのスクリプトにかなりの量のコードが書かれます。その中には重複しているコードも出てくるでしょう。それに対してオブジェクト指向版では、処理の実体はコントローラのメソッドにあり、コントローラクラスを複数用意すれば見通し良くコードを書いていくことができます。そして重複コードの集約はオブジェクト指向の視点から対処できるでしょう。
以上、Mojoliciousのルーティング定義をオブジェクト指向とDSLの両方で行い、その比較を行いました。DSLには利点も欠点もありますので、適材適所で使うことが重要です。
<続きの(3)はこちら 。>