Don't use base.pm, use parent.pm instead!

使っちゃいけない標準モジュール*1の反響を見ていると、baseが非奨励ということに驚かれた方が少なくありませんでした。そこで、baseについて補足します。
まずbase.pmのドキュメントの最初の文は以下のようになっています。

Unless you are using the fields pragma, consider this module discouraged in favor of the lighter-weight parent.
(拙訳: fieldsプラグマを使用しているのでないかぎり、このモジュールは勧められない。かわりに軽量なparent.pmを使う方がよい。)

fieldsプラグマは、ハッシュリファレンスのキーを固定したオブジェクトを作成するための機能ですが、あまり一般的ではないためここでは解説しません。特に理由がない限り、ここは素直に忠告に従った方がいいでしょう。parentはPerl 5.10から標準モジュールとなっていますが、CPANにもあります。特に依存のない小さなpure Perlモジュールなので、インストールは簡単です。
ただし、parentはbaseと少しだけインターフェイスが違います。baseは指定したモジュールが空でなければそのモジュールのロードを試み、ロードに失敗しても処理を続けます*2。一方parentは常にロードを試み、モジュールのロードに失敗するとdieします。これがparentの利点です。ロードすべきモジュールをロードできないというのは致命的なエラーであり、プログラムの実行は中止する方がいいでしょう。もしロードが必要ないなら、-norequireというオプションを渡します。

{
    package Foo;
    use parent qw(HTML::Parser); # モジュールを確実にロードする
}
{
    package Bar;
    use parent -norequire => qw(Foo); # モジュールのロードは試みない
}

さて、baseにはさらに一つバグが発見されています。このバグによって以下のコードはエラーになります。parentであれば問題は起こりません。

{
    package Foo;
    use LWP::UserAgent;
    use base qw(HTML::Parser);
}
Foo->new(); # Can't locate object method "new" via package "Foo" at ...

これはbaseの「対象のパッケージが空であればロードを試みる」という処理の「パッケージが空であれば」というルーチンにバグがあるため、LWP::UserAgentをロードするだけでHTML::Parserのパッケージが空でないように見えてしまうからです。これにより、use base qw(HTML::Parser)としているすべてのモジュールは、LWP::UserAgentの前にロードしなければならないのです。具体的には、HTML::StickyQueryのversion 0.12以前のバージョンでこのバグに遭遇し、baseをparentで置き換えた0.13のリリースとなりました。
このバグはbaseにパッチをあてれば修正できますが、parentに置き換える方が容易でしょう。

*1:JPerl Advent Calendar 2010 Casual Track 23th

*2:このとき、対象のパッケージが空であれば警告を出します