哪个更安全&更好的&清洁与清洁更推荐使用?
我用过:
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更好吗?
我的问题是:你会怎么写这个,为什么你会这样选择?
答案 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");
}
我希望你会同意的更好。
有两点值得注意:
try
和catch
是子例程,其编码看起来像语言字。这意味着最后一个闭合支撑后的分号是必不可少的。
出于同样的原因,return
或try
块中的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,例如,函数返回你想要保存的值,但可能不是真正的值(或者甚至可能没有被定义),并且你想要捕捉异常。