当使用Perl(CPAN)模块时,我经常发现我想以相同的方式为所有方法调用实现错误处理(例如,对某些错误代码进行自动重试,对某些错误代码进行自动重试,对其他错误代码进行死亡……).代码最终看起来非常重复:
my $result1 = eval{
$obj->method1 ( @arg );
};
if ( $@ )
{
# error handling code
}
my $result2 = eval{
$obj->method2 ( @arg );
};
if ( $@ )
{
# error handling code
}
有没有办法实现自动化?
似乎有用的一种方法是使用sub {}:
sub error_handler
{
my $method = shift;
my $result = eval{ shift()->$method ( @_ ); };
if ( $@ )
{
# error handling code
}
else
{
return ( $result );
}
}
my $result1 = error_handler ( 'method1', $obj, @arg );
my $result2 = error_handler ( 'method2', $obj, @arg );
但我仍觉得这段代码很繁琐.我的另一个想法是尝试扩展包:
package My::Package;
use Moo;
extends 'Package';
our $AUTOLOAD;
sub AUTOLOAD
{
$AUTOLOAD =~ s/^My::Package:://;
my $result = eval{ no strict 'refs'; shift()->$AUTOLOAD ( @_ ); };
if ( $@ )
{
# error handling code
}
else
{
return ( $result );
}
}
但是这段代码不起作用 – 我需要一种只用这种方式来处理AUTOLOAD公共方法的方法.有没有人有办法解决吗?
最佳答案 你的第一种方法是最好的.或者你可以用
Try或
Try::Tiny做一个稍微漂亮的变化,它们都接近你的第二种方法的冗长度.
避免使用第二种和第三种方法的主要原因与代码的详细程度关系不大(我承认在第一种方法中很烦人),更多的是与代码的可读性有关.
如果你最终扩展你导入的每个类,你的代码几乎完全不会被其他人读取,或者更糟:它看起来是可读的(“哦,我知道MIME :: Parse如何工作!”),但不会做什么预期(“嗯,为什么MIME :: Parse没有输入这个错误的输入?”)
您的第二种方法基本上存在相同的问题,但至少它不会假装不进行错误处理.但它仍然使调试更加困难.
我知道经常重新输入相同的错误处理代码很烦人(我会这样做时间!),但这是最好的做法.