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