Existe-t-il une théorie des hiérarchies d'exceptions?

18

Je connais une douzaine de langages de programmation qui ont des exceptions d'une certaine manière, pourtant j'en suis venu à être témoin de deux tendances "pathologiques".

  1. Il ne semble pas y avoir de modèle ou de hiérarchie commun d'exceptions. Chaque langue roule essentiellement sa propre version, et si les exceptions en font la norme, alors les types d'exceptions que l'on trouve dans la norme seraient plutôt arbitraires (principalement ceux qui ont été implémentés lors de la création d'outils de langue, tels que la lecture du code source à partir de chaîne ou une exception pour appeler le débogueur, ou celle qui se produit lorsque le fichier est introuvable, etc.)

  2. Les exceptions définies par le langage sont très rarement réutilisées par les programmes utilisateurs. Il y aurait généralement une ou deux exceptions courantes ("non implémenté" par exemple). Bien que la plupart du temps, les programmeurs créent leurs propres exceptions. (Comparez cela à, par exemple, la création de nouveaux types numériques ou de nouveaux types de collection).

Cela ressemble à une terrible omission pour moi. Comment se fait-il que personne ne sait quels types d'erreurs seront nécessaires dans les programmes utilisateur? J'espérais qu'il y aurait une sorte de belle hiérarchie, similaire aux types numériques, aux collections, au système d'objets, etc.

Pire encore, Goolge et Wikipedia fournissent très peu d'aide sur le sujet. Jusqu'à présent, je n'ai trouvé qu'un article sur l'exception fonctionnelle qui s'ouvre dans un passage:

Cet article soutient que la programmation fonctionnelle paresseuse rend non seulement inutile le mécanisme de gestion des exceptions intégré, mais fournit un outil puissant pour développer et transformer des programmes qui utilisent des exceptions

(Une théorie fonctionnelle des exceptions, Mike Spivey, 1988)

Mais je pense que les exceptions sont bonnes. Je ne veux pas transformer les programmes qui utilisent des exceptions, au contraire, je veux rendre l'utilisation des exceptions moins chaotique.

La question:

Existe-t-il une théorie des exceptions? Si oui, comment s'appelle-t-il? Quelles sont, le cas échéant, la pierre angulaire décrivant la base de celui-ci?

wvxvw
la source
les exceptions sont une invention relativement nouvelle, peut-être datant de moins de ~ 20 ans, découlant quelque peu du "longjmp" de C. ils sont principalement connectés à la POO. il semble qu'un usage idéal / théorie / meilleures pratiques soient encore en évolution. java possède l'un des modèles les plus élaborés. il y a de nombreux "antipatterns" relatifs aux exceptions comme vous le constatez. une partie de cela est liée à la théorie du "calcul tolérant aux pannes" qui semble également quelque peu à ses balbutiements dans l'ensemble.
vzn
Vous pouvez considérer les exceptions comme un sous-ensemble de la théorie de la continuation. Voir en.wikipedia.org/wiki/Continuation
jmite
@jmite Les exceptions et les suites sont très différentes. Les exceptions se lient dynamiquement à leurs gestionnaires, tandis que les continuations le font statiquement. En général, les continuations ne peuvent pas être utilisées seules pour implémenter des exceptions, du moins en présence de types, voir par exemple, les exceptions typées et les continuations ne peuvent pas s'exprimer en macro .
Martin Berger
"Les exceptions définies par le langage sont très rarement réutilisées par les programmes utilisateur." C'est tellement vrai! La définition d'exceptions personnalisées est très rarement nécessaire. Par exemple, python et son stdlib définissent quelque chose comme 160 exceptions. Il y a très peu de chances que l'exception à laquelle vous pensez ne soit pas définie. Certaines (la plupart?) De ces exceptions ne sont pas largement connues. Par exemple, le LookupErrorserait parfaitement bien pour chaque conteneur personnalisé, mais beaucoup de gens ne savent même pas qu'il existe.
Bakuriu
1
@jmite Une autre rencontre que j'ai eue avec des exceptions avant ce sujet était du livre de Benjamin C. Pierce, Types and Programming Languages. Où il mentionne des erreurs dans le contexte de la définition d'un type de fonction. C'est-à-dire de son point de vue, les erreurs ne sont qu'une autre valeur renvoyée par les fonctions (et avec l'autre argument, elles forment un type entier, si je peux me permettre de le dire).
wvxvw

Réponses:

8

Il existe un grand nombre de publications sur les exceptions, avec pas mal de recherches théoriques. Voici une liste non structurée et loin d'être complète avec quelques exemples. Désolé, je n'ai pas le temps pour le moment pour une réponse plus ciblée.

  • B. Randell, Structure du système pour la tolérance aux pannes logicielles.
  • JB Goodenough. Gestion des exceptions: problèmes et proposition de notation.
  • JB Goodenough. Gestion structurée des exceptions.
  • BG Ryder, ML Soffa, Influence sur la conception de la gestion des exceptions.
  • D. Teller, A. Spiwack, T. Varoquaux, Catch me if you can: Vers une gestion des erreurs sûre, hiérarchique, légère, polymorphe et efficace dans OCaml.
  • X. Leroy, F. Pessaux, Analyse basée sur le type des exceptions non capturées.
  • R. Miller, A. Tripathi, Problèmes de gestion des exceptions dans les systèmes orientés objet.
  • S. Drew, KJ Gough, J. Ledermann, Implementation of Zero-Overhead Exception Handling.
  • B. Stroustrup, Exception Safety: Concepts and Techniques.
  • D. Malayeri, J. Aldrich, Spécifications d'exceptions pratiques.
  • H. Nakano, Une formalisation constructive du mécanisme de capture et de lancer.
  • A. Nanevski, Un calcul modal pour la gestion des exceptions.
  • P. de Groote, Un calcul simple de la gestion des exceptions.
  • H. Thielecke, Sur les exceptions et continuations en présence d'État.
  • JG Riecke, H. Thielecke, les exceptions et les continuations typées ne peuvent pas s'exprimer en macro.
  • M. van Dooren, E. Steegmans, Combinant la robustesse des exceptions vérifiées avec la flexibilité des exceptions non contrôlées à l'aide de déclarations d'exceptions ancrées.
  • JA Vaughan, Une interprétation logique des exceptions de style Java.
  • S. Marlow, S. Peyton Jones, A. Moran, Exceptions asynchrones dans Haskell.
  • B. Jacobs, F. Piessens, Failboxes: Provably Safe Exception Handling.
Martin Berger
la source
Wow, merci beaucoup! Cela me prendra quelques mois (sinon plus) pour revenir avec la réponse positive :) Maintenant je suis déchiré entre quelques livres ne sachant pas par où commencer!
wvxvw
2
Beaucoup de ces articles traitent de l'implémentation ou de la modélisation d'exceptions dans les langages de programmation, et non de la façon de concevoir une hiérarchie d'exceptions. Pourriez-vous réduire la liste aux documents pertinents?
Gilles 'SO- arrête d'être méchant'
@Gilles La question d'origine n'était pas claire. Je pense que ce qui compte comme exceptions appropriées dépend principalement de l'application. Le seul vrai problème théorique avec les exceptions est le compromis entre (1) le couplage de modules non liés par le biais d'exceptions (c'est pourquoi aucun langage après Java n'a de spécifications d'exception obligatoires), (2) donnant à l'utilisateur d'un module une indication des types d'erreurs à attendre et (3) l'aide du compilateur pour la gestion des erreurs. Pour autant que je puisse voir, aucune solution vraiment convaincante à cette énigme n'a encore été trouvée.
Martin Berger
6

Je ne sais pas s'il existe ou non une théorie, mais il peut y avoir une science expérimentale pragmatique émergente.

La meilleure source à laquelle je peux penser est Bjarne Stroustrup, The Design and Evolution of C ++, Addison-Wesley, 1994 . Si je me souviens bien (c'est un très bon livre et les gens continuent de me l'emprunter et de ne pas le retourner, donc je n'ai pas de copie pour le moment), il y a un chapitre sur les exceptions. Le comité C ++ de Stroustrup avait besoin de beaucoup de preuves empiriques qu'une fonctionnalité proposée était nécessaire avant de vouloir l'ajouter à la définition du langage. La page Wikipedia sur les exceptions a la citation suivante de ce livre:

Lors de la réunion de Palo Alto [normalisation C ++] en novembre 1991, nous avons entendu un brillant résumé des arguments pour une sémantique de terminaison appuyée à la fois par une expérience personnelle et des données de Jim Mitchell (de Sun, anciennement de Xerox PARC). Jim avait utilisé la gestion des exceptions dans une demi-douzaine de langues sur une période de 20 ans et était l'un des premiers partisans de la sémantique de reprise en tant que l'un des principaux concepteurs et réalisateurs du système Cedar / Mesa de Xerox. Son message était la résiliation est préférable à la reprise; ce n'est pas une question d'opinion mais une question d'années d'expérience. La reprise est séduisante, mais non valable. Il a soutenu cette déclaration avec l'expérience de plusieurs systèmes d'exploitation. L'exemple clé était Cedar / Mesa: il a été écrit par des gens qui aimaient et utilisaient la reprise, mais après dix ans d'utilisation, il n'y avait plus qu'une seule utilisation de la reprise dans le système d'un demi-million de lignes - et c'était une enquête contextuelle. Comme la reprise n'était pas réellement nécessaire pour une telle enquête contextuelle, ils l'ont supprimée et ont constaté une augmentation significative de la vitesse dans cette partie du système. Dans tous les cas où la reprise avait été utilisée, elle était devenue - au cours des dix dernières années - un problème et une conception plus appropriée l'avait remplacée. Fondamentalement, chaque utilisation de la reprise avait représenté un échec à maintenir des niveaux séparés d'abstraction disjoints. Dans tous les cas où la reprise avait été utilisée, elle était devenue - au cours des dix dernières années - un problème et une conception plus appropriée l'avait remplacée. Fondamentalement, chaque utilisation de la reprise avait représenté un échec à maintenir des niveaux séparés d'abstraction disjoints. Dans tous les cas où la reprise avait été utilisée, elle était devenue - au cours des dix dernières années - un problème et une conception plus appropriée l'avait remplacée. Fondamentalement, chaque utilisation de la reprise avait représenté un échec à maintenir des niveaux séparés d'abstraction disjoints.

En C ++, le véritable gain est RAII , ce qui facilite beaucoup la gestion de la désallocation des ressources lors d'erreurs. (Cela ne supprime pas le besoin de throwet try- catch, mais cela signifie que vous n'en avez pas besoin finally.)

Je pense que la chose qui les a convaincus qu'ils avaient besoin d'exceptions est les conteneurs génériques: l'auteur du conteneur ne sait rien des types d'erreurs que les objets contenus pourraient avoir besoin de renvoyer (encore moins comment les gérer), mais le code qui a inséré ces objets dans le le conteneur doit savoir quelque chose sur l'interface de ces objets. Mais comme nous ne savons rien des types d'erreurs que les objets contenus peuvent générer, nous ne pouvons pas standardiser les types d'exceptions. (Contrapositivement: si nous pouvions standardiser les types d'exceptions, nous n'aurions pas besoin d'exceptions.)

L'autre chose que les gens semblent avoir appris au fil des ans est que les spécifications d'exception sont difficiles à mettre correctement dans une langue. Voir par exemple ceci: http://www.gotw.ca/publications/mill22.htm , ou ceci: http://www.gotw.ca/gotw/082.htm . (Et ce n'est pas seulement C ++, les programmeurs Java ont également de longs arguments sur leurs expériences avec les exceptions vérifiées et non contrôlées .)

Un peu sur l'histoire des exceptions. L'article classique est: John B. Goodenough: "Traitement des exceptions: problèmes et proposition de notation", Commun. ACM 18 (12): 683-696, 1975. Mais des exceptions étaient connues avant cela. Mesa les avait vers 1974 et PL / I les avait peut-être aussi. Ada avait un mécanisme d'exception avant 1980. Je crois que les exceptions de C ++ ont été le plus influencées par l'expérience avec le langage de programmation CLU de Barbara Liskov vers 1976. Barbara Liskov: "A history of CLU", in History of programming languages ​​--- II , Thomas J. Bergin, Jr. et Richard G. Gibson, Jr. (éd.). pp. 471-510, ACM, 1996 .

Logique errante
la source
C'est intéressant et je devrai faire plus de recherches pour mieux répondre. Mais jusqu'à présent: je sais qu'il y a une très forte objection à l'utilisation d'exceptions en C ++ (peut-être une anecdote, mais les conventions de codage iirc de Google interdisaient l'utilisation d'exceptions). Les exceptions vérifiées par Java sont certainement une expérience unique et donc intéressante, mais la fonctionnalité a gagné tant de mauvais crédits au cours de son histoire ... la plupart des gens les rejettent simplement au moment de l'exécution (bien que cela puisse être uniquement lié à la syntaxe).
wvxvw
Je connais mieux la classification des exceptions Common Lisp, où ils ont essayé (bien qu'avec peu de succès) de les diviser en fonction du niveau de menace qu'ils représentent pour le programme. par exemple serious-conditionvs simple-condition. Je lis également maintenant JL Austing, où il classe les erreurs (sans rapport avec la programmation) en groupes en fonction de la façon dont le système n'a pas réussi à exécuter la tâche (par exemple, pièces incorrectes utilisées vs intentions non sincères). Ce qui n'est pas immédiatement applicable à la programmation, mais pourrait l'être après un certain raffinement.
wvxvw
@Wandering Logic J'ai mis à jour parce que vous avez expliqué pourquoi les excpetios C ++ sont des sux et que l'inclusion de fonctionnalités éduquées pourrait détruire le langage.
Val
@wvxvw Les very strong objectioncontre-exceptions en C ++ proviennent de deux faits: il n'y a pas de finallyconstruction et personne d'autre n'utilise d'exceptions. Le premier problème aggrave également le second. Autrement dit, lorsque vous n'avez pas finally, vous ne pouvez pas fermer la ressource lorsque survient une exception. Parce que personne n'utilise d'exceptions, toutes les fonctions / API les évitent, vous devez investir beaucoup pour reconstruire toute l'infrastructure C ++ traditionnelle en enveloppant toutes les fonctions avec vos exceptions pour commencer à en tirer des avantages dans votre code. Mais le manque de finallyrend cette approche impossible également.
Val
@wvxvw: les conventions de Google interdisent de lever des exceptions au-delà des limites du module (.so). Cela est dû au fait que les exceptions en C ++ utilisent des informations de type au moment de l'exécution (RTTI), et Linux n'a pas fait un bon travail d'implémentation du typage au moment de l'exécution. Sous Linux, vous ne pouvez transmettre des types d'exécution de manière fiable entre modules que si vous avez compilé les modules avec la même version du même compilateur et liés à la version identique de libstdc ++. Vraiment, c'est un rejet de C ++ en général par la communauté Linux, pas un rejet d'exceptions en particulier.
Wandering Logic
3

Permettez-moi de souligner que les exceptions sont un cas d' effet de calcul . Les autres effets de calcul sont l'état mutable, les E / S, le non-déterminisme, les continuations et bien d'autres. Ainsi, votre question pourrait être posée de manière plus générale: comment former des hiérarchies d'effets de calcul, comment les organiser et pourquoi avons-nous ceux que nous avons, et pas d'autres, etc.

Andrej Bauer
la source
1
Je pense que cela est complètement hors de propos. La question n'est pas de modéliser la notion d'exceptions, mais de la mapper aux erreurs - je pense que la bonne façon de la décrire du point de vue du PLT serait une théorie des hiérarchies d'exceptions.
Gilles 'SO- arrête d'être méchant'
Hmm, tu as raison. J'ai corrigé la réponse pour le signaler, mais je pense qu'il n'est pas nécessaire de le supprimer. Qu'est-ce que tu penses?
Andrej Bauer