Using Try :: Tiny or Eval?

Which is safer, better and cleaner and recommended?

I used:

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"); } 

But for such cases (see part of the error) I was told that it is better to use Try :: Tiny?

My question is: how would you describe it and why would you choose this method?

+7
perl
source share
3 answers

Update

Thanks to an anonymous user, I was able to correct the error in my answer. return in the catch did not have the desired effect, since it was returned only from the catch routine.

If there was no exception, try returns the value of the try block; otherwise, the value of the catch . Thus, this version correctly executes and returns the value $c->redirect("/index") if insert succeeds, otherwise it calls and returns the value $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 is pretty much necessary, since error handling with eval very difficult to get right in the general case. The module documentation says this

This module contains simple try / catch / finally commands that are designed to minimize common errors with eval and NOTHING else blocks.

The focus of this module is on simple and reliable error handling for those who still want to write the correct eval blocks without 5 lines of a template each time.

Your code will look like this:

 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"); } 

which, I hope you agree, is much nicer.

Two points are noticeable:

  • try and catch are routines encoded as language words. This means that the semicolon after the final closing parenthesis is important.

  • For the same reason, return in try or catch blocks will not work as expected, and will simply exit the block, returning to the parent routine. See My update above.

  • In the catch $@ has its original value before try . The value resulting from the error is in $_

+10
source share

Do not use Try::Tiny retains an additional dependency.

Using this, you can write code that is understandable without knowing the Perl idioms (by replacing them with more industry-recognized terms).

You need to decide which one is of great value to you, because it is difficult to objectively evaluate their relative value.

+4
source share

It’s better not to rely on $@ to signal errors, but just use it as a source of error messages, so I would write it as:

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

If you are evaluating something that may not return the true meaning of success, then:

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

I would probably use Try :: Tiny when things get complicated, for example, the function returns the value that you want to save, but may not be the true value (or even not defined), and you want catch exceptions.

+1
source share

All Articles