理系学生日記

おまえはいつまで学生気分なのか

Exporter を使ったプラグイン機構

CGI::Application では、Plugin を読み込むことで、CGI::Application に新たにメソッドを生やすことができます。

CGI::Application を継承した MyApp。

package MyApp;
use base qw(CGI::Application);
# use CGI::Application::Plugin::DBH qw(dbh_config);

1;

MyApp に dbh_config がメソッドとして生えているかの確認。

use MyApp;

my $app = MyApp->new;
print "MyApp ",
    $app->can('dbh_config')? q{can} : q{can't}, 
    " call dbh_config\n";

これは、use CGI::Application::Plugin::DBH qw(dbh_config); の行がコメントアウトされていれば "MyApp can't call dbh_config"、コメントでなくなれば "MyApp can call dbh_config" となります。

こういうプラグイン機構(というかメソッドを生やす方法)を CGI::Application ではどうやって実現してんだろうとか思ってたんですけど、POD/ソースを見てたら Exporter で実現できるんだなってことに気づいた。


ぼくの中では、Exporter は関数(もちろん変数とかもだけど)を export するときに使うという固定観念があったのだけど、よくよく考えてみると Perl 的にはメソッドも関数も区別しないため、Exporter を使ったらメソッドも export することが当たり前のようにできる。
CGI::Application の Plugin が行っているのは、CGI::Application::Plugin::* という名前空間の中で関数を定義し、それを Exporter を使って @EXPORT{,_OK} にセットしているだけ。MyApp みたいな CGI::Application を継承したモジュールで Plugin を use することで、この関数が MyApp の名前空間に export される。あとは、

$app->dbh_config( ... )

とすれば、現在の名前空間にある dbh_config がルックアップされるという仕掛け。$app->dbh_config( ... ) は dbh_config( $app, ... ) と等価であることを考えれば、この方法は CGI::Application だけでなくどんなモジュールにも適用できる。


Exporter の仕組み的には当然といえば当然の帰結なんだけど、そういうアイディアとかぼくの中になかったので、すごく新鮮に感じました。