そういえば CGI::Application::URIMapping

パストラック用に自作した CGI::Application::URIMapping が、1ファイル1コントローラーのディスパッチャ。各コントローラの先頭でマッピングを宣言すると、パッケージ名の basename を関数として呼び出す感じ。たとえば、MyApp::Users を register しておくと、MyApp::Users::users が呼び出される。

package MyApp::Users;

use base qw/CGI::Application/;

MyApp::URIMapping->register({
  path  => 'users/:category?',
  query => [
    {
      name => 'order_by',
      omit => 'name',
    },
  ],
});

sub users {
  my $self = shift;
  
  # パーマリンク形式じゃなければリダイレクト
  return if $self->normalize_uri;
  
  ...
}

上の例で言うと、指定したパーマリンク形式じゃなかったらリダイレクトとか、やってる。逆に、他のコントローラ (あるいはテンプレート) から、

my $uri = MyApp::Users->build_uri([
  { category => $cat },
  $self,
]);

とか呼び出すと、category の値だけを置き換え、他のパラメータは Users が宣言したもののみをコピーして、自動的にパーマリンクを作ってくれる。

ただ、当然、CGI::Application::URIMapping は、起動時に全コントローラの読み込みを行うので、CGI には向かない。

まあ http://kazuho.31tools.com/nanoa/nanoa.cgi の小規模から使えるウェブアプリケーションフレームワークという観点でいうと、ディスパッチテーブルとか受け付けるクエリパラメータの宣言とか重たいわけで、こういう機能は必須ではないのだろう、と。一方で、オプションとして提供するにはどうしたらいいか、という点は無考慮。

RoR っぽく、ディスパッチャを集中定義するのかなー。自分的には、CGI::Application::URIMapping のような各コントローラー内での分散定義のほうが、メンテナンス性が高いと思うんだけど。