使用Try :: Tiny还是Eval?

时间:2013-08-02 09:33:11

标签: perl

哪个更安全&更好的&清洁与清洁更推荐使用?

我用过:

sub insert_exec {
    my ($self, $c, $args) = @_;
    my ($params, $table, $model) = $self->_init({context => $c, args => $args});
    eval {  $model->insert($table, $params);
    };
    if ($@) {  return $c->show_error($@);  } ## error
    $c->redirect("/index");
}

但对于这种情况(参见错误部分),我被告知使用Try :: Tiny更好吗?

我的问题是:你会怎么写这个,为什么你会这样选择?

3 个答案:

答案 0 :(得分:11)

<强>更新

感谢匿名用户,我已经能够纠正我的答案中的错误。 return块中的catch没有达到预期的效果,因为它仅从catch子例程返回。

如果没有异常,try将返回try块的值,否则返回catch块的值。因此,如果$c->redirect("/index")成功,则此版本正确执行并返回insert的值,否则它将调用并返回$c->show_error($_)的值。

sub insert_exec {
  my ($self, $c, $args) = @_;
  my ($params, $table, $model) = $self->_init({context => $c, args => $args});
  try {
    $model->insert($table, $params);
    $c->redirect("/index");
  }
  catch {
    $c->show_error($_);
  };
}

Try::Tiny非常重要,因为使用eval进行错误处理在一般情况下确实很难实现。该模块的文档说明了这个

  

这个模块提供了基本的try / catch / finally语句,旨在最大限度地减少eval块的常见错误,并且没有其他错误。

     

本模块的主要重点是为那些仍然想要编写正确的eval块的人提供简单而可靠的错误处理。每次都没有5行样板文件。

您的代码看起来像这样

use Try::Tiny;

sub insert_exec {
  my ($self, $c, $args) = @_;
  my ($params, $table, $model) = $self->_init({context => $c, args => $args});
  try {
    $model->insert($table, $params);
  }
  catch {
    return $c->show_error($_);
  };
  $c->redirect("/index");
}

我希望你会同意的更好。

有两点值得注意:

  • trycatch子例程,其编码看起来像语言字。这意味着最后一个闭合支撑后的分号是必不可少的。

  • 出于同样的原因,returntry块中的catch将无法按预期工作,只会退出该块,返回到父子例程。请参阅上面的更新。

  • catch块中$@的原始值来自try之前。错误产生的值在$_

答案 1 :(得分:4)

不使用Try::Tiny可以为您节省额外的依赖。

使用它可以编写可以理解的代码,而无需了解Perl习语(通过用业界更普遍认可的术语替换它们)。

你需要决定哪一个对你更有价值,因为很难客观地衡量它们的相对价值。

答案 2 :(得分:1)

最好不要依赖$@来表示错误,而只是将其用作错误消息的来源,所以我会把它写成:

my $success = eval { $model->insert($table, $params) };
unless ($success) {
    return $c->show_error($@);
}

如果你评价的某些东西可能不会成功,那么:

my $success = eval { $model->insert($table, $params); 1 };

当事情变得比这更复杂时,我可能会使用Try :: Tiny,例如,函数返回你想要保存的值,但可能不是真正的值(或者甚至可能没有被定义),并且你想要捕捉异常。