¿Existe una teoría de las jerarquías de excepción?

18

Estoy familiarizado con una docena de lenguajes de programación que tienen excepciones de alguna manera, sin embargo, llegué a ser testigo de dos tendencias "patológicas".

  1. No parece haber un patrón común o jerarquía de excepciones. Básicamente, cada idioma presenta su propia versión, y si las excepciones se convierten en el estándar, los tipos de excepciones que se encuentran en el estándar serían bastante arbitrarios (principalmente aquellos que se implementaron al crear herramientas de lenguaje, como leer el código fuente de cadena o una excepción para invocar al depurador, o la que ocurre cuando no se puede encontrar el archivo, etc.)

  2. Los programas de usuario rara vez reutilizan las excepciones definidas por el lenguaje. Habrá generalmente una o dos excepciones populares ("no implementar", por ejemplo). Aunque la mayoría de las veces los programadores crearán sus propias excepciones. (Compare esto con, por ejemplo, crear nuevos tipos numéricos o nuevos tipos de colección).

Esto me parece una terrible omisión. ¿Cómo es que nadie sabe qué tipo de errores se necesitarán en los programas de usuario? Esperaba que hubiera una especie de jerarquía agradable, similar a los tipos numéricos, colecciones, sistema de objetos, etc.

Peor aún, Goolge y Wikipedia proporcionan muy poca ayuda sobre el tema. Hasta ahora solo he encontrado un documento sobre la excepción funcional que se abre en un pasaje:

Este artículo argumenta que la programación funcional perezosa no solo hace innecesario el mecanismo incorporado de manejo de excepciones, sino que proporciona una herramienta poderosa para desarrollar y transformar programas que usan excepciones

(Una teoría funcional de las excepciones, Mike Spivey, 1988)

Pero creo que las excepciones son buenas. No quiero transformar programas que usan excepciones, por el contrario, quiero hacer que el uso de excepciones sea menos caótico.

La pregunta:

¿Existe una teoría de excepciones? Si es así, ¿cómo se llama? ¿Cuáles son, si las hay, la piedra angular que describe su base?

wvxvw
fuente
Las excepciones son un invento bastante nuevo, quizás de menos de ~ 20 años de antigüedad, que surge algo del "longjmp" de C. en su mayoría están conectados a OOP. parece un uso ideal / teoría / mejores prácticas todavía están en evolución. Java tiene uno de los modelos más elaborados. Hay muchos "antipatterns" relacionados con las excepciones, como se observa. algo de esto está relacionado con la teoría de la "computación tolerante a fallas" que también parece un tanto incipiente en general.
vzn
Podría considerar las excepciones como un subconjunto de la teoría de la continuación. Ver en.wikipedia.org/wiki/Continuation
jmite
@jmite Las excepciones y continuaciones son muy diferentes. Las excepciones se unen dinámicamente a sus controladores, mientras que las continuaciones lo hacen de forma estática. En general, las continuaciones por sí solas no se pueden usar para implementar excepciones, al menos en presencia de tipos, consulte, por ejemplo, Excepciones y Continuaciones Tipo no pueden Macroexpresarse entre sí .
Martin Berger
"Los programas de usuario rara vez reutilizan las excepciones definidas por el lenguaje". ¡Esto es tan cierto! Definir excepciones personalizadas rara vez es necesario. Por ejemplo, python y su stdlib definen algo así como 160 excepciones. Las posibilidades de que la excepción en la que está pensando no se haya definido allí son muy pequeñas. Algunas (¿la mayoría?) De estas excepciones no se conocen ampliamente. Por ejemplo, LookupErrorestaría perfectamente bien para cada contenedor personalizado, pero mucha gente ni siquiera sabe que existe.
Bakuriu
1
@jmite Un encuentro más que tuve con excepciones antes de este tema fue del libro Tipos y lenguajes de programación de Benjamin C. Pierce. Donde menciona errores en el contexto de la definición de un tipo de función. Es decir, desde su punto de vista, los errores son solo otros valores devueltos por las funciones (y junto con el otro argumento forman un tipo completo, si se me permite decirlo).
wvxvw

Respuestas:

8

Hay una gran cantidad de publicaciones sobre excepciones, con bastantes investigaciones teóricas. Aquí hay una lista desestructurada y lejos de ser completa con algunos ejemplos. Lo siento, no tengo tiempo en este momento para una respuesta más centrada.

  • B. Randell, Estructura del sistema para tolerancia a fallas de software.
  • JB Goodenough. Manejo de excepciones: problemas y una notación propuesta.
  • JB Goodenough. Manejo estructurado de excepciones.
  • BG Ryder, ML Soffa, Influencias en el diseño de manejo de excepciones.
  • D. Teller, A. Spiwack, T. Varoquaux, Atrápame si puedes: Hacia una gestión de errores de tipo seguro, jerárquica, ligera, polimórfica y eficiente en OCaml.
  • X. Leroy, F. Pessaux, Análisis basado en tipos de excepciones no capturadas.
  • R. Miller, A. Tripathi, Problemas con el manejo de excepciones en sistemas orientados a objetos.
  • S. Drew, KJ Gough, J. Ledermann, Implementación de manejo de excepciones de cero gastos generales.
  • B. Stroustrup, seguridad de excepción: conceptos y técnicas.
  • D. Malayeri, J. Aldrich, Especificaciones prácticas de excepción.
  • H. Nakano, una formalización constructiva del mecanismo de captura y lanzamiento.
  • A. Nanevski, Un cálculo modal para el manejo de excepciones.
  • P. de Groote, Un simple cálculo de manejo de excepciones.
  • H. Thielecke, Sobre Excepciones y Continuaciones en Presencia de Estado.
  • JG Riecke, H. Thielecke, excepciones y continuaciones mecanografiadas no pueden macroexpresarse entre sí.
  • M. van Dooren, E. Steegmans, Combinando la robustez de las excepciones marcadas con la flexibilidad de las excepciones no verificadas mediante declaraciones de excepciones ancladas.
  • JA Vaughan, una interpretación lógica de las excepciones de estilo Java.
  • S. Marlow, S. Peyton Jones, A. Moran, Excepciones asincrónicas en Haskell.
  • B. Jacobs, F. Piessens, Failboxes: manejo de excepciones demostrablemente seguro.
Martin Berger
fuente
Wow, muchas gracias! Me llevará unos meses (si no más) volver con la respuesta positiva :) ¡Ahora estoy dividido entre pocos libros que no saben por dónde empezar!
wvxvw
2
Muchos de estos documentos tratan sobre implementar o modelar excepciones en lenguajes de programación, y no sobre cómo diseñar una jerarquía de excepciones. ¿Podría reducir la lista a los documentos relevantes?
Gilles 'SO- deja de ser malvado'
@Gilles La pregunta original era un poco confusa. Creo que lo que cuenta como excepciones apropiadas depende principalmente de la aplicación. El único problema teórico real con excepciones es la compensación entre (1) el acoplamiento de módulos no relacionados a través de excepciones (es por eso que ningún lenguaje después de Java tiene especificaciones de excepción obligatorias), (2) dando al usuario de un módulo alguna indicación de qué tipo de errores esperar , y (3) ayuda del compilador con el manejo de errores. Hasta donde puedo ver, todavía no se ha encontrado una solución realmente convincente para este enigma.
Martin Berger
6

No sé si existe o no una teoría, pero puede haber una ciencia experimental pragmática emergente.

La mejor fuente que se me ocurre es Bjarne Stroustrup, The Design and Evolution of C ++, Addison-Wesley, 1994 . Si recuerdo correctamente (es un libro muy bueno y la gente me lo sigue pidiendo prestado y no me lo devuelve, por lo que no tengo una copia en este momento) hay un capítulo sobre excepciones. El comité C ++ bajo Stroustrup requirió mucha evidencia empírica de que una característica propuesta era necesaria antes de que estuvieran dispuestos a agregarla a la definición del lenguaje. La página de Wikipedia sobre excepciones tiene la siguiente cita de ese libro:

En la reunión de Palo Alto [estandarización de C ++] en noviembre de 1991, escuchamos un resumen brillante de los argumentos para la semántica de terminación respaldados con experiencia personal y datos de Jim Mitchell (de Sun, anteriormente de Xerox PARC). Jim había utilizado el manejo de excepciones en media docena de idiomas durante un período de 20 años y fue uno de los primeros defensores de la semántica de reanudación como uno de los principales diseñadores e implementadores del sistema Cedar / Mesa de Xerox. Su mensaje de terminación es preferible a la reanudación; Esto no es una cuestión de opinión, sino una cuestión de años de experiencia. La reanudación es seductora, pero no válida. Respaldó esta declaración con experiencia de varios sistemas operativos. El ejemplo clave fue Cedar / Mesa: fue escrito por personas a las que les gustó y usaron la reanudación, pero después de diez años de uso, solo quedaba un uso de la reanudación en el sistema de medio millón de líneas, y esa fue una investigación de contexto. Debido a que la reanudación no era realmente necesaria para dicha investigación de contexto, la eliminaron y encontraron un aumento significativo de la velocidad en esa parte del sistema. En todos y cada uno de los casos en que se había utilizado la reanudación, durante los diez años se había convertido en un problema y un diseño más apropiado lo había reemplazado. Básicamente, cada uso de la reanudación había representado una falla en mantener separados los niveles de abstracción. En todos y cada uno de los casos en que se había utilizado la reanudación, durante los diez años se había convertido en un problema y un diseño más apropiado lo había reemplazado. Básicamente, cada uso de la reanudación había representado una falla en mantener separados los niveles de abstracción. En todos y cada uno de los casos en que se había utilizado la reanudación, durante los diez años se había convertido en un problema y un diseño más apropiado lo había reemplazado. Básicamente, cada uso de la reanudación había representado una falla en mantener separados los niveles de abstracción.

En C ++, la verdadera victoria es RAII , lo que hace que sea mucho más fácil manejar la desasignación de recursos durante los errores. (No acabar con la necesidad de throwe try- catch, sino que significa que no es necesario finally.)

Creo que lo que los convenció de que necesitaban excepciones son los contenedores genéricos: el escritor del contenedor no sabe nada sobre los tipos de errores que los objetos contenidos podrían necesitar devolver (mucho menos cómo manejarlos), pero el código que insertó esos objetos en el El contenedor debe saber algo sobre la interfaz de esos objetos. Pero como no sabemos nada acerca de qué tipo de errores pueden arrojar los objetos contenidos, no podemos estandarizar los tipos de excepción. (Contradictoriamente: si pudiéramos estandarizar los tipos de excepción, entonces no necesitaríamos excepciones).

La otra cosa que la gente parece haber aprendido a lo largo de los años es que las especificaciones de excepción son difíciles de poner correctamente en un idioma. Vea, por ejemplo, esto: http://www.gotw.ca/publications/mill22.htm , o esto: http://www.gotw.ca/gotw/082.htm . (Y no se trata solo de C ++, los programadores de Java también tienen largos argumentos sobre sus experiencias con excepciones marcadas frente a no marcadas ).

Un poco sobre la historia de las excepciones. El artículo clásico es: John B. Goodenough: "Manejo de excepciones: problemas y una notación propuesta", Commun. ACM 18 (12): 683-696, 1975. Pero antes se conocían excepciones. Mesa los tenía aproximadamente en 1974, y PL / I puede haberlos tenido también. Ada tenía un mecanismo de excepción antes de 1980. Creo que las excepciones de C ++ fueron más influenciadas por la experiencia con el lenguaje de programación CLU de Barbara Liskov de alrededor de 1976. Barbara Liskov: "Una historia de CLU", en Historia de los lenguajes de programación --- II , Thomas J. Bergin, Jr. y Richard G. Gibson, Jr. (Eds.). pp. 471-510, ACM, 1996 .

Lógica Errante
fuente
Esto es interesante y tendré que investigar más para responder mejor. Pero hasta ahora: sé que existe una fuerte objeción para usar excepciones en C ++ (tal vez una anécdota, pero las convenciones de codificación de Google de iirc solían prohibir el uso de excepciones). Las excepciones comprobadas en Java son ciertamente un experimento único y, por lo tanto, interesante, pero la característica obtuvo tantos créditos malos en el transcurso de su historia ... la mayoría de las personas simplemente los vuelven a lanzar en tiempo de ejecución (aunque esto puede estar relacionado con la sintaxis).
wvxvw
Estoy más familiarizado con la clasificación de excepciones Common Lisp, donde intentaron (aunque con poco éxito) dividirlas de acuerdo con el nivel de amenaza que representan para el programa. por ejemplo serious-conditionvs simple-condition. Ahora también estoy leyendo JL Austing, donde clasifica los errores (no relacionados con la programación) en grupos en función de cómo el sistema no pudo realizar la tarea (por ejemplo, partes incorrectas utilizadas frente a intenciones poco sinceras). Lo cual no es inmediatamente aplicable a la programación, pero podría ser después de algún refinamiento.
wvxvw
@Wandering Logic He actualizado porque has explicado por qué los excpetios de C ++ son sux y que la inclusión educada de características podría destruir el lenguaje.
Val
@wvxvw Las very strong objectionexcepciones en contra en C ++ provienen de dos hechos: no hay finallyconstructo y nadie más usa excepciones. El primer problema también agrava el segundo. Es decir, cuando no tiene finally, no puede cerrar el recurso cuando ocurre una excepción. Debido a que nadie usa excepciones, todas las funciones / API las evitan, debe invertir mucho reconstruyendo toda la infraestructura tradicional de C ++ envolviendo todas las funciones con sus excepciones para comenzar a obtener beneficios de ellas en su código. Pero la falta de finallyhace que este enfoque sea imposible también.
Val
@wvxvw: las convenciones de Google prohíben lanzar excepciones a través de los límites del módulo (.so). Esto se debe a que las excepciones en C ++ usan información de tipo de tiempo de ejecución (RTTI), y Linux no hizo un buen trabajo al implementar la tipificación en tiempo de ejecución. En Linux, solo puede pasar tipos de tiempo de ejecución de manera confiable entre módulos si compiló los módulos con la misma versión del mismo compilador y se vinculó con la versión idéntica de libstdc ++. Realmente esto es un rechazo de C ++ en general por parte de la comunidad de Linux, no un rechazo de excepciones específicamente.
Lógica errante
3

Permítanme señalar que las excepciones son un caso de efecto computacional . Otros efectos computacionales son estado mutable, E / S, no determinismo, continuaciones y muchos otros. Por lo tanto, su pregunta podría formularse de manera más general: ¿cómo formamos jerarquías de efectos computacionales, cómo los organizamos y por qué tenemos los que tenemos, y no otros, etc.

Andrej Bauer
fuente
1
Creo que esto es completamente irrelevante. La pregunta no se trata de modelar la noción de excepciones, sino de asignarla a errores: creo que la forma correcta de describirla desde una perspectiva PLT sería una teoría de las jerarquías de excepción.
Gilles 'SO- deja de ser malvado'
Hmm, tienes razón. Arreglé la respuesta para señalar esto, pero creo que no hay necesidad de eliminarlo. ¿Qué piensas?
Andrej Bauer