Ad. 1. Yes and no - [there are still some pitfalls][1] (please read further).

Ad. 2. You must remember about returning truthy value from `eval` block because it evaluates to last value in block **unless** some code died, in which case `undef` is returned, so `1;` as last statement in `eval` block is important.

You also have to localize `$@` somehow (`my $error = $@` in your example) because it's a global variable which can be changed silently (see Conclusion).

Ad. 3. `if ($@)` can have one pitfall, i.e. it doesn't catch error when it's false:

    eval {
      die '';
      do_something();
    };
    if ($@) {
      # ooops... we don't get here
    }


while `or do { }` block will always be activated in case of exception

    eval {
      die '';
      do_something();
      1;
    } or do {
      # caught!
    };

**Conclusion:**

I personally use "eval or do # process error" style of catching errors but common and widely used alternative, which eleminates boilerplate code, is to use [`Try::Tiny`][2]. It's a simple, 0-dependency CPAN module which addresses `$@` issues. Its documentation (especially BACKGROUND section) is really worth reading as it answers some of your questions and with even more details.

See also [this SO question][3].

  [1]: https://metacpan.org/module/Try::Tiny#BACKGROUND
  [2]: https://metacpan.org/module/Try::Tiny
  [3]: https://stackoverflow.com/questions/10364975/is-trytiny-still-recommended-for-exception-handling-in-perl-5-14-or-later