Mathieu Eveillard

Vous faites erreur…

Vous faites erreur…

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

Erreur et Exception : 2 notions bien différentes

Prenons le temps de définir chaque notion :

Gestion des exceptions

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…

Gestion des erreurs : le Railway Oriented Programming

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 » (elles ne font pas ce qu’elles disent), et encore moins 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 Oriented Programming, expliqué de belle manière par Scott Wlashing.

Ce sujet vous est présenté en détail dans la formation La programmation fonctionnelle en pratique. Pour le reste, les exceptions doivent rester… l’exception 😉

← Tous les articles