8

哪个更安全、更好、更清洁、更推荐使用?

我用了:

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 更好?

我的问题是:你会怎么写这个,你为什么会选择那种方式?

4

3 回答 3

14

更新

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

如果没有异常,则try返回try块的值,否则返回块的值catch。所以这个版本正确执行并返回$c->redirect("/index")ifinsert成功的值,否则它调用并返回 的值$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");
}

我希望你会同意更好。

有两点值得注意:

  • try并且catch是编码成看起来像语言单词的子程序。这意味着最后一个右大括号后的分号是必不可少的。

  • 出于同样的原因,returntryorcatch块内将不会按预期工作,并且将简单地退出块,返回父子程序。请参阅上面的更新。

  • catch块内$@有它之前的原始值try。错误产生的值在$_

于 2013-08-02T09:48:40.220 回答
4

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

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

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

于 2013-08-02T09:36:07.947 回答
2

最好不要依赖$@信号错误,而只是将其用作错误消息的来源,因此我将其写为:

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

如果您正在评估可能不会在成功时返回真值的东西,那么:

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

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

于 2013-08-02T15:19:48.370 回答