Est-ce que Try :: Tiny est toujours recommandé pour la gestion des exceptions dans Perl 5.14 ou ultérieur?

Le consensus de la communauté Perl semble être que Try::Tiny est la manière préférée de gérer les exceptions.

Perl 5.14 (qui est la version que j’utilise) semble résoudre les problèmes avec les adresses eval que Try::Tiny . Va Try::Tiny encore fournir des avantages pour moi?

Ma réponse est impopulaire, mais je ne pense pas que les programmeurs Perl devraient essayer d’utiliser la notion extrêmement pauvre de ce que nous appelons des “exceptions” en Perl. Ce sont essentiellement une valeur de retour de canal secondaire. Cependant, toujours séduites par l’idée d’exceptions, même avec toutes les complexités liées à l’utilisation d’une variable globale pour contourner un état, les gens continuent d’essayer de le faire fonctionner.

Pratiquement, cependant, les gens utilisent die pour signaler un échec. Certains diront que vous pouvez die avec une référence et renvoyer des objects d’erreur, mais vous n’avez pas besoin de die pour cela. Nous avons des objects, nous devons donc utiliser toute la puissance des objects:

  sub some_sub { ... return Result->new( error => 1, description => ... ) if $something_went_wrong; return Result->new( error => 0, ... ); } my $result = some_sub( ... ); if( $result->is_error ) { ... }; 

Cela n’implique pas de variables globales, d’action à distance, de maux de tête ou nécessitant des promotions spéciales. Vous créez une classe Result minuscule, ou tout ce que vous voulez l’appeler, pour envelopper vos valeurs de retour afin d’avoir des données structurées au lieu de valeurs uniques sans identité. On ne se demande plus ce que signifie une valeur de retour. Est-ce que c’est une valeur réelle ou une indication d’échec? La valeur de retour est-elle bonne si elle est définie ou si elle est vraie? Votre object peut vous dire ces choses. Et, vous pouvez utiliser le même object avec die . Si vous utilisez déjà l’object avec die et que vous l’utilisez comme valeur de retour, il y a très peu de choses à recommander pour tolérer $@ .

J’en parle plus dans “Retour des objects d’erreur au lieu de lancer des exceptions”

Cependant, je sais que vous ne pouvez pas aider ce que les autres font, alors vous devez toujours prétendre que Perl a des exceptions.

C’était toujours un cas de préférence personnelle. Préfères-tu

 my $rv; if (!eval { $rv = f(); 1 } ) { ... } 

ou

 my $rv = try { f(); } catch { ... }; 

Mais gardez à l’esprit que ce dernier utilise des sous-marins, ce qui perturbe le return , ainsi que le next et les autres. Try :: Tiny risque de devenir beaucoup plus compliqué lorsque vous ajoutez des canaux de communication entre le bloc catch et l’extérieur de celui-ci.

Le meilleur scénario (le plus simple) pour renvoyer une exception est si $rv est toujours vrai lorsqu’il n’y a pas d’exception. Cela ressemblerait à ceci:

 my $rv; if ($rv = eval { f() }) { ... return; } 

contre

 my $rv = try { f(); } catch { ... }; if (!$rv) { return; } 

C’est pourquoi j’utiliserais TryCatch au lieu de Try :: Tiny pour utiliser un tel module.

La modification de Perl signifie simplement que vous pouvez recommencer if ($@) . En d’autres termes,

 my $rv; if (!eval { $rv = f(); 1 } ) { ... } 

peut être écrit

 my $rv = eval { f() }; if ($@) { ... } 

Si rien d’autre, Try::Tiny est toujours bon sucre syntaxique. Si vous voulez quelque chose d’un peu plus lourd, il y a aussi TryCatch , qui résout certains problèmes liés au fait que les clauses de Try::Tiny sont des sous-routines (par exemple, ce return ne quitte pas la fonction englobante).

Try::Tiny est facile et léger. Trop facile. Nous avons eu deux problèmes:

  • sous-marins anonymes – il y avait toujours des problèmes avec la return « return » à l’intérieur
  • attraper toujours et tout

J’ai donc apporté quelques modifications à Try::Tiny , cela nous aide. Maintenant nous avons:

 try sub {}, catch 'SomeException' => sub {}, catch [qw/Exception1 Exception2/] => sub {}, catch_all sub {}; 

Je sais – cette syntaxe est un peu exotique, mais grâce à ‘ sub ‘ évidente, nos programmeurs savent maintenant que l’instruction ‘ return ‘ sort juste du gestionnaire d’exceptions, et nous ne capturons que les exceptions que nous voulons attraper 🙂

Soit faire:

 local $@; eval { … } 

… Pour empêcher que les modifications apscopes à $ @ n’affectent la scope mondiale ou utilisez Try :: Tiny.

Syntaxiquement, il y a des situations où je préfère l’un ou l’autre.