Vous faites erreur…

Erreur, ou exception ?
Erreur, ou exception ?

Vous faites erreur…

Exception ? Erreur ? Une seule et même chose ?

Non !

Prenons le temps de définir chaque notion :

  • Une erreur arrivera, tôt ou tard. Qu'un utilisateur tente de diviser par 0, de retirer 37€ à un distributeur automatique ou bien que sa demande n'aboutisse pas suite à une perte de réseau mobile, ces cas arriveront de manière certaine. Gérer l'erreur consiste donc à communiquer auprès de l'utilisateur pour l'éduquer : si ce dernier ne comprend pas que demander 37€ est un problème, il recommencera et interprétera le refus répété du distributeur comme un dysfonctionnement. Jusqu'à taper dessus, puisqu'il est bien connu que cela résout les problèmes.

  • Une exception, en revanche, ne devrait pas arriver. On a contraint la saisie en amont, on a fait toutes les validations nécessaires, mais on se retrouve quand-même à devoir distribuer 37€. Si la demande nous parvient, c'est qu'on a un (gros) problème de développement. Gérer une exception consiste donc à communiquer non auprès de l'utilisateur mais de l'équipe de développement dans le but d'éviter qu'elle ne se reproduise. Autrement dit : corriger le bug.

Les exceptions sont faciles à gérer : on lance une exception et on l'intercepte au plus haut niveau possible de manière à ce que le programme puisse continuer son cours normal. On affiche une petite bafouille sympa ("Oops, something went wrong, we'll be working on it soon so it does not happen again!") plutôt que des messages cryptiques du style "ERR 30001C Attempt to use a closed socket" et surtout on log le maximum de données techniques à destination des développeurs.

Et les erreurs alors ?

Au risque de vous décevoir, lancer une exception est la dernière chose à faire. Oui, je sais, c'est pourtant ce qu'on vous a appris depuis que vous avez l'âge de tenir un clavier, mais non, trois fois non. Utiliser des exceptions pour gérer des erreurs, c'est à peu près comme si, pour se rendre à l'avant du train, vous sortiez sur le toit, remontiez tout le train et rentriez enfin dans le wagon de tête…

Le problème, c'est que lancer une exception interrompt le flux d'exécution normal du programme. Autrement dit, le programme est en PLS (Position Latérale de Sécurité). Bizarre, vu qu'une erreur, on le rappelle, est une erreur dans l'utilisation du programme (1/0), une erreur dans le contexte d'utilisation du programme (perte de réseau), mais non une erreur dans le programme lui-même. Elle arrivera donc tôt ou tard.

C'est d'autant plus gênant dans les langage qui, comme TypeScript, ne nous contraignent pas à indiquer dans la signature d'une fonction qu'elle est susceptible de lancer une exception. Dès lors, ces fonctions ne sont plus "honnêtes", donc pures. Et ça, on n'aime pas.

Au final, gérer les erreurs est un peu plus compliqué mais reste tout à fait faisable. Concrètement, cela suppose de définir une abstraction Result<T> qui représente soit le succès ({ type: "SUCCESS", result: T}) soit l'erreur ({ type: "ERROR", reason: string}). Ce qui nous contraint à faire de même tout au long du programme et nous emmène tout droit vers les monades et le Railway Programming, expliqué de belle manière par Scott Wlashing.

En résumé, les exceptions doivent rester… l'exception.

Subscribe to Mathieu Eveillard

Don’t miss out on the latest issues. Sign up now to get access to the library of members-only issues.
jamie@example.com
Subscribe