Arn*_*erg 5 error-handling perl try-catch autoload
当使用 Perl (CPAN) 模块时,我经常发现我想要以相同的方式对所有方法调用实现错误处理(例如,自动重试某些错误代码、记录一些错误代码、终止其他错误代码......)。代码最终看起来非常重复:
my $result1 = eval{
$obj->method1 ( @arg );
};
if ( $@ )
{
# error handling code
}
my $result2 = eval{
$obj->method2 ( @arg );
};
if ( $@ )
{
# error handling code
}
Run Code Online (Sandbox Code Playgroud)
有没有办法自动执行此操作?一种似乎有效的方法是使用 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 );
Run Code Online (Sandbox Code Playgroud)
但我仍然觉得这段代码很乏味。我的另一个想法是尝试扩展这个包:
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 );
}
}
Run Code Online (Sandbox Code Playgroud)
但这段代码不起作用 - 我需要一种方法来仅以这种方式自动加载公共方法。有没有人有办法解决吗?
你的第一个方法是最好的。或者,您可以使用Try或Try::Tiny做一个稍微漂亮的变体,这两种方法都可以减少第二种方法的冗长。
避免使用第二种和第三种方法的主要原因与代码的冗长性关系不大(我承认这在第一种方法中很烦人),而更多地与代码的可读性有关。
如果你最终扩展了你导入的每个类,那么你的代码对于其他任何人来说几乎完全不可读,或者更糟:它看起来是可读的(“哦,我知道 MIME::Parse 是如何工作的!”),但不会执行预期的操作(“嗯,为什么 MIME::Parse 没有因为这个错误的输入而失败?”)
您的第二种方法本质上有相同的问题,但至少它不会假装不进行错误处理。但它仍然使调试变得更加困难。
我知道频繁地重新输入相同的错误处理代码很烦人(我每次都会这样做!),但这是最佳实践。