Perso, le code que j'ecris a pour but de resoudre un probleme extremement precis (calcul les plus petites valeures propre de cette matrice). Le code est court (<<10Kloc) et va tourner longtemps (>>1 CPU-jour). Toute erreur a l'execution veut dire que je n'aurais pas de resultat. Donc exit a du sens
Pour moi, c'est un peu comme si tu écrivais une routine d'importation de donnée pour ton usage perso. En ce sens tu vas pas faire de la super gestion d'erreur. A la fin de l'exécution du programme ça a marché ou pas avec éventuellement un message d'erreur, c'est tout ce qui intéresse.
Et la façon la plus facile de transmettre des erreurs avec des explications à une couche supérieure, ça reste quand même les exceptions.
Je veux tout à fait admettre que c'est largement acceptable pour certains cas, mais quand les architectures deviennent plus complexes, avec des sources de données, des IO, des contraintes de disponibilité, ça devient vite insuffisant.
Perso pour tout projet sérieux, j'accepterai jamais qu'une fonction de mon programme non rattachée au fil conducteur principal affiche des trucs en console ou décide de la fin du processus.
Pour moi, le rôle d'une d'une couche de service ou d'une lib, c'est de fournir une API de haut-niveau à disposition d'une interface GTK/console/web ou dieu sait quoi et c'est cette interface qui décide de comment elle réagit en cas d'erreur, si elle quitte silencieusement, si elle log puis elle envoie un http 500 ou autre.