DBIC のソースを読んでたら、不意に出てきた Carp::Clan。気になって調べてみました。
Carp との違い
一番分かりやすい Carp との違いは、どのサブルーチン内でエラーが起こったかまでが、エラーメッセージとともに出力されることです。
#!/opt/local/bin/perl use strict; use warnings; package Pack::A; sub exception { Pack::B::exception(); } package Pack::B; sub exception { Pack::C::exception(); } package Pack::C; use Carp; # use Carp::Clan; sub exception { carp "exception"; } package main; Pack::A::exception();
use Carp の場合
exception at ./carp-clan.pl line 9
use Carp::Clan の場合
Pack::C::exception(): exception at ./carp-clan.pl line 9
Carp は、呼び出し元がどこか (line 9) だけしか分かりませんが、Carp::Clan にするとで、どこ(Pack::C::exception()) でエラーが発生しているかも分かるようになります。
ただ、これだけでは Clan (一族とかを意味します) の意味をまだ成していません
Clan をスキップ
Carp::Clan では、use 時にどのモジュールを Clan (一族) とするかを決めることができます。
例えば、上記のソースでの Pack::C パッケージを以下のようにしてみます。
package Pack::C; # use Carp; use Carp::Clan qw(Pack::[BC]); sub exception { carp "exception"; }
ここでは、Pack::A、及び Pack::B を Clan として定義しています。このときの出力は、以下のようになります。
Pack::B::exception(): exception at ./carp-clan.pl line 6
呼び出し元は今までの "line 9" から "line 6" になり、エラーの発生源は今までの Pack::C::exception からPack::B::exception に変わりました。
これはどういうことかというと、Clan として定義した Pack::[BC] は一族(Clan) ですから、例えPack::C::exception() で例外が発生しても、Pack::B::exception で例外が発生したのと同じだよって(ユーザには)見えるようにするってことです。
DBIC::Schema::Loader では
use Carp::Clan qw/^DBIx::Class/;
って形で定義されてますが、これは DBIx::Class::* ていうモジュールは全部 Clan だから、その中で起きた例外は全て、コールスタック上を最も遡ったところにある DBIx::Class メソッドの呼び出しで例外が発生したようにユーザには見えることになります。