Perl:包广泛的eval错误处理的最佳实践

时间:2015-08-07 09:23:47

标签: perl error-handling 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
}

有没有办法实现自动化? 一种似乎有用的方法是使用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公共方法。有没有人有解决方案?

1 个答案:

答案 0 :(得分:2)

你的第一种方法是最好的。或者你可以使用TryTry::Tiny做一个略微漂亮的变体,它们都会降低第二种方法的冗长度。

避免使用第二种和第三种方法的主要原因与代码的详细程度关系不大(我承认在第一种方法中很烦人),而更多地与可读性有关你的代码。

如果您最终扩展您导入的每个课程,您的代码几乎完全无法被其他人阅读,或者更糟糕的是:它显示是可读的("哦,我知道如何MIME :: Parse工作!"),但不会做出预期的事情("嗯,为什么MIME :: Parse没有用这个糟糕的输入失败?&# 34)

你的第二种方法基本上存在相同的问题,但至少它并没有假装不进行错误处理。但它仍然使调试变得更加困难。

我知道经常重新输入相同的错误处理代码很烦人(我会花时间!),但这是最好的做法。