出力の整え方は分かったので、ここからWebアプリケーションを作りますが、今回は見通しを良くするため、mod_perlなどは使わず、CGIプログラムとしてアプリケーションを作っていきます。
Webアプリケーションというと大層な感じがしますが、すでにWWW::OpenSearchで検索、結果を受け取るという中核の処理、それから検索結果を整形して表示するという出力部分は分かっています。残る作業は、入力を受け取ってそれに応じてアプリケーションを動かす部分の作成くらいです。
この部分、つまり入力を受け取ってうんぬんというスクリプトを、実装するとどんな具合でしょうか。よくあるのはリスト5のようなパターンです。
#!/usr/local/bin/perl
use strict;
use warnings;
my $q = CGI->new;
if ($q->param('mode') eq 'search') {
&do_search($q);
} elsif ($q->param('mode') eq 'config') {
&do_admin($q);
} else {
&do_index($q);
}
sub do_search {
my $q = shift;
:
:
}
sub do_admin {
:
:
}
sub do_index {
:
:
}
このスクリプトでは、アプリケーションのトップページ、検索結果ページ、設定ページの出力処理をすべて1つのファイルにまとめています。それぞれの動作は、URLに与えられたmodeなどのクエリパラメータの変数によって切り替え、サブルーチンを呼び出すことで実装するというものです。うーん、ちっとも「いまどき」な感じがしませんね。この方法だと、アプリケーションを拡張するとどんどんスクリプトの行数が増えていって、後からメンテナンスするのが大変になってしまいます。
そうならないためには、どうすれば良いでしょうか? こういった問題を追究すると、例えば各ページごとにモジュールやクラスを切り分けて……といった方向へ発展していくわけですが、その仕組みそのものを一から作るのは「車輪の再開発」にほかなりません。「Webアプリケーションを作るための仕組み」は、フレームワーク*としてすでにあるものを使ってしまうのが良いでしょう。これもやっぱりCPANです。
CGI::Applicationを使うと、先の例のような一枚っぺらでメンテナンス性の低い構成ではなく、ページ(機能)ごとにクラスを分けつつ、かつmodeでの条件分岐のような泥臭い処理を書かずにWebアプリケーションを作れるようになります。
CGI::Applicationでは、CGIスクリプトそのものには処理を書きません。CGIスクリプトからはクラスを呼び出して実行するだけです。例えば次のようになるでしょう。
#!/usr/local/bin/perl
use WebApp; # CGI::Application のサブクラス
my $webapp = WebApp->new;
$webapp->run;
具体的な処理が入っているWebAppクラスの実装はリスト6のようになります。CGI::Applicationを継承して、setupメソッドをオーバーライドしオブジェクト指向インタフェースでどのモードがどのメソッドを呼ぶか、というふうに記述していきます。if文で分岐処理を書くよりもずいぶんすっきりしますね。
package WebApp;
use base qw (CGI::Application); # CGI::Application を継承
# 各モードのディスパッチ先メソッドのセットアップ
sub setup {
my $self = shift;
$self->start_mode('search');
$self->mode_param('__mode');
$self->run_modes(
search => 'do_search',
config => 'do_config',
);
}
sub do_search { …… }
sub do_config { …… }
CGI::Applicationは$self->mode_paramで指定した名前のURLのクエリパラメータをモードとして扱い、その値によってメソッドのディスパッチ*先を決定します。またstart_modeで指定した値がデフォルトのモードになります。つまり、前述の書き方だと、・cgiapp.cgi?__mode=search → do_searchが呼ばれる
といった具合になります。また、各メソッドの戻り値がそのモードのページの出力です。例えば、
sub do_search {
return "hoge";
}
のようにすると、「cgiapp.cgi?__mode=search」にアクセスしたときの画面には、「hoge」と1行表示されます。
CGI::Applicationでは、ページの切り替えはmodeパラメータで行うか、別のクラスを作って分けるといった具合に設計していくことができます。ある特定の機能に関連したページは1つのクラスの中にまとめて適宜modeで切り替え、異なる機能のページはクラスを分けるといった感じでページ設計をしていくと良いでしょう。
CGI::Applicationを単体で使うのもいいですが、ページごとにクラスを用意するような設計を行う場合はCGI::Application::Dispatchを使うと便利です。例えば、リスト7がcgiapp.cgiというCGIプログラムだとすると、「cgiapp.cgi/<モジュール名>/<モード>」というURLで該当ページにアクセスできるようになります。具体的には、
といった具合でディスパッチされます。
#!/usr/local/bin/perl
use strict;
use CGI::Application::Dispatch;
CGI::Application::Dispatch->dispatch(
PREFIX => 'UU',
DEFAULT => 'Index',
);
それではフレームワークの解説はここまでにして、次回は実際にWWW::OpenSearchを使ってアプリケーションを組み立てていきましょう。
Perlの代表的なWebアプリケーションフレームワークとして、次のものが挙げられる。
この中でも特に、最近はCatalystが非常に注目されているが、これは、「Ruby on Rails」というRubyで利用するフレームワークが流行している影響もある(CatalystはRailsを参考に作られている)。Catalystは便利だが、利用方法を覚えるまでに若干敷居が高く今回は解説しなかった。興味のある方はぜひ挑戦してほしい。
処理を振り分けること。会社の受付が来客の応対と対応部署への誘導を専門に行うのと同様、プログラムにおいても、入力データを受け付けて該当処理を呼び出すプログラム構造を持つことがある。こういった処理をディスパッチと呼ぶ。
本記事は、オープンソースマガジン2005年9月号「作って学ぶ、今どきのWebサービス 第3回」を再構成したものです。
Copyright © ITmedia, Inc. All Rights Reserved.