La forma moderna de realizar el manejo de errores ...

118

He estado reflexionando sobre este problema durante un tiempo y me encuentro continuamente encontrando advertencias y contradicciones, así que espero que alguien pueda sacar una conclusión de lo siguiente:

Favorecer excepciones sobre códigos de error

Hasta donde sé, después de trabajar en la industria durante cuatro años, leer libros y blogs, etc., la mejor práctica actual para manejar errores es lanzar excepciones, en lugar de devolver códigos de error (no necesariamente un código de error, sino un tipo que representa un error).

Pero, para mí, esto parece contradecir ...

Codificación para interfaces, no implementaciones

Codificamos interfaces o abstracciones para reducir el acoplamiento. No sabemos, o queremos saber, el tipo específico y la implementación de una interfaz. Entonces, ¿cómo podemos saber qué excepciones deberíamos buscar atrapar? La implementación podría arrojar 10 excepciones diferentes, o podría arrojar ninguna. Cuando detectamos una excepción, ¿estamos haciendo suposiciones sobre la implementación?

A menos que la interfaz tenga ...

Especificaciones de excepción

Algunos lenguajes permiten a los desarrolladores afirmar que ciertos métodos arrojan ciertas excepciones (Java, por ejemplo, usa la throwspalabra clave). Desde el punto de vista del código de llamada, esto parece estar bien: sabemos explícitamente qué excepciones podríamos necesitar detectar.

Pero, esto parece sugerir un ...

Abstracción permeable

¿Por qué una interfaz debe especificar qué excepciones se pueden lanzar? ¿Qué sucede si la implementación no necesita lanzar una excepción, o necesita lanzar otras excepciones? No hay forma, a nivel de interfaz, de saber qué excepciones puede querer lanzar una implementación.

Entonces...

Para concluir

¿Por qué se prefieren las excepciones cuando parecen (en mi opinión) contradecir las mejores prácticas de software? Y, si los códigos de error son tan malos (y no necesito que me vendan los vicios de los códigos de error), ¿hay otra alternativa? ¿Cuál es el estado actual de la técnica (o que pronto será) para el manejo de errores que cumpla con los requisitos de las mejores prácticas descritas anteriormente, pero que no se base en que el código de llamada verifique el valor de retorno de los códigos de error?

RichK
fuente
12
No entiendo tu argumento sobre las abstracciones con fugas. Especificar qué excepción puede lanzar un método en particular es parte de la especificación de la interfaz . Así como el tipo del valor de retorno es parte de la especificación de la interfaz. Las excepciones simplemente no "salen del lado izquierdo" de la función, pero siguen siendo parte de la interfaz.
Fallecimiento
@deceze ¿Cómo puede una interfaz indicar lo que puede arrojar una implementación? ¡Puede arrojar todas las excepciones en el sistema de tipos! Y que muchas lenguas no son compatibles con las especificaciones de excepción sugieren que son bastante poco fiable
RichK
1
Estoy de acuerdo en que puede ser complicado administrar todas las diferentes excepciones que puede arrojar un método, si él mismo utiliza otros métodos y no detecta sus excepciones internamente. Dicho esto, no es una contradicción.
Fallecimiento
1
La suposición permeable aquí es que el código puede manejar una excepción cuando se escapa del límite de la interfaz. Eso es muy poco probable, dado que no sabe lo suficiente sobre lo que realmente salió mal. Todo lo que sabe es que algo salió mal y la implementación de la interfaz no sabía cómo lidiar con eso. Las probabilidades de que pueda hacer un mejor trabajo son pobres, más allá de informarlo y finalizar el programa. O ignorarlo si la interfaz no es crítica para la operación adecuada del programa. Un detalle de implementación que no puede ni debe codificar en un contrato de interfaz.
Hans Passant

Respuestas:

31

En primer lugar, no estaría de acuerdo con esta afirmación:

Favorecer excepciones sobre códigos de error

Este no es siempre el caso: por ejemplo, eche un vistazo a Objective-C (con el marco de Foundation). Allí, el NSError es la forma preferida de manejar errores, a pesar de la existencia de lo que un desarrollador de Java llamaría excepciones verdaderas: @try, @catch, @throw, clase NSException, etc.

Sin embargo, es cierto que muchas interfaces pierden sus abstracciones con las excepciones lanzadas. Creo que esto no es culpa del estilo de "excepción" de propagación / manejo de errores. En general, creo que el mejor consejo sobre el manejo de errores es este:

Tratar el error / excepción al nivel más bajo posible, período

Creo que si uno se apega a esa regla general, la cantidad de "fuga" de las abstracciones puede ser muy limitada y contenida.

Sobre si las excepciones lanzadas por un método deberían ser parte de su declaración, creo que deberían: son parte del contrato definido por esta interfaz: este método cumple con A o falla con B o C.

Por ejemplo, si una clase es un analizador XML, una parte de su diseño debe ser para indicar que el archivo XML proporcionado es simplemente incorrecto. En Java, normalmente lo hace declarando las excepciones que espera encontrar y agregándolas a la throwsparte de la declaración del método. Por otro lado, si uno de los algoritmos de análisis falló, no hay razón para pasar esa excepción anterior sin controlar.

Todo se reduce a una cosa: buen diseño de interfaz. Si diseñas tu interfaz lo suficientemente bien, ninguna cantidad de excepciones debería atormentarte. De lo contrario, no solo las excepciones te molestarían.

Además, creo que los creadores de Java tenían razones de seguridad muy fuertes para incluir excepciones a una declaración / definición de método.

Una última cosa: algunos idiomas, Eiffel, por ejemplo, tienen otros mecanismos para el manejo de errores y simplemente no incluyen capacidades de lanzamiento. Allí, se genera automáticamente una 'excepción' de clasificación cuando no se cumple una condición posterior para una rutina.

K.Steff
fuente
12
+1 por negar "Favorecer excepciones sobre códigos de error". Me han enseñado que las excepciones son buenas y buenas, siempre que sean, de hecho, excepciones y no la regla. Llamar a un método que arroja una excepción para determinar si una condición es verdadera o no es una práctica extremadamente mala.
Neil
44
@ JoshuaDrake: Definitivamente está equivocado. Excepciones y gotoson muy diferentes. Por ejemplo, las excepciones siempre van en la misma dirección: hacia abajo en la pila de llamadas. Y en segundo lugar, protegerse de las excepciones sorpresa es exactamente la misma práctica que DRY, por ejemplo, en C ++, si usa RAII para garantizar la limpieza, entonces garantiza la limpieza en todos los casos, no solo en la excepción, sino también en todo el flujo de control normal. Esto es infinitamente más confiable. try/finallylogra algo algo similar. Cuando garantiza adecuadamente la limpieza, no necesita considerar las excepciones como un caso especial.
DeadMG
44
@ JoshuaDrake Lo siento, pero Joel está muy lejos de allí. Las excepciones no son lo mismo que goto, siempre subes al menos un nivel en la pila de llamadas. ¿Y qué haces si el nivel anterior no puede lidiar inmediatamente con el código de error? ¿Devolver otro código de error? Parte del problema con el error es que PUEDEN ser ignorados, lo que lleva a problemas peores que el lanzamiento de una excepción.
Andy
25
-1 porque estoy completamente en desacuerdo con "Tratar con el error / excepción en el nivel más bajo posible" - eso está mal, punto. Tratar con errores / excepciones en el nivel apropiado . Muy a menudo ese es un nivel mucho más alto, y en ese caso, los códigos de error son un gran dolor. La razón para favorecer las excepciones sobre los códigos de error es que le permiten elegir libremente en qué nivel tratarlos sin afectar los niveles intermedios.
Michael Borgwardt
2
@Giorgio: consulte artima.com/intv/handcuffs.html , especialmente las páginas 2 y 3.
Michael Borgwardt
27

Solo me gustaría señalar que las excepciones y los códigos de error no son la única forma de lidiar con los errores y las rutas de código alternativas.

Fuera de la mente, puede tener un enfoque como el adoptado por Haskell, donde los errores se pueden señalar a través de tipos de datos abstractos con múltiples constructores (piense enuminos discriminados o punteros nulos, pero seguros de tipos y con la posibilidad de agregar sintácticos Sugar o funciones auxiliares para que el flujo del código se vea bien).

func x = do
    a <- operationThatMightFail 10
    b <- operationThatMightFail 20
    c <- operationThatMightFail 30
    return (a + b + c)

operationThatMightfail es una función que devuelve un valor envuelto en un Maybe. Funciona como un puntero anulable, pero la notación do garantiza que todo se evalúa como nulo si alguno de a, b o c falla. (y el compilador lo protege de hacer una NullPointerException accidental)

Otra posibilidad es pasar un objeto controlador de errores como argumento adicional a cada función que llame. Este controlador de errores tiene un método para cada posible "excepción" que puede ser señalado por la función a la que se lo pasa, y puede ser utilizado por esa función para tratar las excepciones donde ocurren, sin necesariamente tener que rebobinar la pila a través de excepciones.

Common LISP hace esto y lo hace factible al tener soporte sintáctico (argumentos implícitos) y hacer que las funciones integradas sigan este protocolo.

hugomg
fuente
1
Eso está muy bien. Gracias por responder la parte sobre alternativas :)
RichK
1
Por cierto, las excepciones son una de las partes más funcionales de los lenguajes imperativos modernos. Las excepciones forman una mónada. Las excepciones usan la coincidencia de patrones. Las excepciones ayudan a imitar el estilo aplicativo sin realmente aprender lo que Maybees.
9000
Estaba leyendo un libro sobre SML recientemente. Mencionó tipos de opciones, excepciones (y continuaciones). El consejo era usar tipos de opciones cuando se espera que el caso indefinido ocurra con bastante frecuencia, y usar excepciones cuando el caso indefinido ocurre muy raramente.
Giorgio
8

Sí, las excepciones pueden causar abstracciones con fugas. ¿Pero los códigos de error no son aún peores a este respecto?

Una forma de abordar este problema es hacer que la interfaz especifique exactamente qué excepciones se pueden lanzar bajo qué circunstancias y declare que las implementaciones deben asignar su modelo de excepción interno a esta especificación, capturando, convirtiendo y volviendo a lanzar excepciones si es necesario. Si desea una interfaz "perfecta", ese es el camino a seguir.

En la práctica, generalmente es suficiente especificar excepciones que son lógicamente parte de la interfaz y que un cliente puede querer atrapar y hacer algo al respecto. En general, se entiende que puede haber otras excepciones cuando ocurren errores de bajo nivel o se manifiesta un error, y que un cliente solo puede manejar en general mostrando un mensaje de error y / o cerrando la aplicación. Al menos la excepción aún puede contener información que ayude a diagnosticar el problema.

De hecho, con los códigos de error, casi sucede lo mismo, de una manera más implícita y con mucha más probabilidad de que la información se pierda y la aplicación termine en un estado inconsistente.

Michael Borgwardt
fuente
1
No entiendo por qué un código de error puede causar una abstracción con fugas. Si se devuelve un código de error en lugar de un valor de retorno normal, y este comportamiento se describe en la especificación de la función / método, entonces IMO no hay fuga. ¿O estoy pasando por alto algo?
Giorgio
Si el código de error es específico de la implementación, mientras que se supone que la API es independiente de la implementación, entonces al especificar y devolver el código de error se filtran detalles de implementación no deseados. Ejemplo típico: una API de registro con una implementación basada en archivos y una implementación basada en DB, donde la primera puede tener un error de "disco lleno", y la segunda un error de "conexión de DB rechazada por el host".
Michael Borgwardt
Entiendo lo que dices. Si desea informar errores específicos de implementación, la API no puede ser independiente de la implementación (ni con códigos de error ni con excepciones). Supongo que la única solución sería definir un código de error independiente de la implementación como "recurso no disponible", o decidir que la API no es independiente de la implementación.
Giorgio
1
@Giorgio: Sí, informar errores específicos de la implementación es complicado con una API independiente de la implementación. Aún así, puede hacerlo con excepciones, porque (a diferencia de los códigos de error) pueden tener múltiples campos. Por lo tanto, puede usar el tipo de excepción para proporcionar la información de error genérica (ResourceMissingException) e incluir un código / mensaje de error específico de implementación como un campo. Lo mejor de ambos mundos :-).
sleske
Y por cierto, eso es exactamente lo que hace java.lang.SQLException. Tiene getSQLState(genérico) y getErrorCode(específico del proveedor). Ahora, si solo tuviera las subclases adecuadas ...
sleske
5

Muchas cosas buenas aquí, solo me gustaría agregar que todos debemos tener cuidado con el código que usa excepciones como parte del flujo de control normal. A veces las personas entran en esa trampa donde cualquier cosa que no sea el caso habitual se convierte en una excepción. Incluso he visto una excepción utilizada como condición de terminación de bucle.

Las excepciones significan "algo que no puedo manejar aquí sucedió, necesito ir a otra persona para averiguar qué hacer". Un usuario que escribe una entrada no válida no es una excepción (la entrada debe manejarlo localmente preguntando de nuevo, etc.).

Otro caso degenerado de uso de excepciones que he visto son las personas cuya primera respuesta es "lanzar una excepción". Esto casi siempre se hace sin escribir el catch (regla general: primero escriba el catch y luego la instrucción throw). En aplicaciones grandes, esto se vuelve problemático cuando una excepción no detectada surge de las regiones inferiores y explota el programa.

No estoy en contra de las excepciones, pero parecen simples de hace unos años: se usan con demasiada frecuencia y de manera inapropiada. Son perfectos para el uso previsto, pero ese caso no es tan amplio como algunos piensan.

luego
fuente
4

Abstracción permeable

¿Por qué una interfaz debe especificar qué excepciones se pueden lanzar? ¿Qué sucede si la implementación no necesita lanzar una excepción, o necesita lanzar otras excepciones? No hay forma, a nivel de interfaz, de saber qué excepciones puede querer lanzar una implementación.

No. Las especificaciones de excepción están en el mismo depósito que los tipos de retorno y argumento: son parte de la interfaz. Si no puede cumplir con esa especificación, no implemente la interfaz. Si nunca lanzas, está bien. No hay nada de fugas al especificar excepciones en una interfaz.

Los códigos de error son más que malos. Son terribles. Debe recordar manualmente comprobarlos y propagarlos, cada vez, para cada llamada. Esto viola DRY, para empezar, y explota masivamente su código de manejo de errores. Esta repetición es un problema mucho mayor que cualquier otra que enfrentan las excepciones. Nunca puede ignorar silenciosamente una excepción, pero la gente puede ignorar silenciosamente los códigos de retorno, definitivamente es algo malo.

DeadMG
fuente
Sin embargo, los códigos de error pueden ser más fáciles de usar si tiene buenas formas de azúcar sintáctico o métodos auxiliares, y en algunos idiomas puede hacer que el compilador y el sistema de tipos le garanticen que nunca olvidará manejar un código de error. En cuanto a la parte de la interfaz de excepción, creo que estaba pensando en la notoria torpeza de las excepciones comprobadas de Java. Si bien a primera vista parecen una idea perfectamente razonable, en la práctica causan muchos pequeños problemas dolorosos.
hugomg
@missingno: Eso es porque, como de costumbre, Java tiene una implementación terrible de ellos, no porque las excepciones marcadas sean intrínsecamente malas.
DeadMG
1
@missingno: ¿Qué tipo de problemas pueden ser causados ​​por excepciones marcadas?
Giorgio
@Giorgio: es muy difícil prever todo tipo de excepción que pueda arrojar un método, ya que esto debe tener en cuenta otras subclases y códigos que aún no se han escrito. En la práctica, las personas terminan con soluciones desagradables que arrojan información, como reutilizar una clase de excepciones del sistema para todo o tener que atrapar y volver a lanzar excepciones internas con frecuencia. También escuché que las excepciones marcadas eran un gran obstáculo cuando trataban de agregar funciones anónimas al lenguaje.
hugomg
@missingno: las funciones anónimas AFAIK en Java son solo azúcar sintáctica para clases internas anónimas con exactamente un método, por lo que no estoy seguro de entender por qué las excepciones marcadas serían un problema (pero admito que no sé mucho sobre el tema). Sí, es difícil prever qué excepciones arrojará un método, por eso IMO puede ser útil tener excepciones marcadas, para que no tenga que adivinar. Por supuesto, puede escribir código deficiente para manejarlos, pero esto también puede hacerlo con excepciones no marcadas. Sin embargo, sé que el debate es bastante complejo y, sinceramente, veo ventajas y desventajas en ambos lados.
Giorgio
2

Bueno, el manejo de excepciones puede tener su propia implementación de interfaz. Dependiendo del tipo de excepción lanzada, realice los pasos deseados.

La solución a su problema de diseño es tener dos implementaciones de interfaz / abstracción. Uno para la funcionalidad y el otro para el manejo de excepciones. Y dependiendo del tipo de excepción detectada, llame a la clase de tipo de excepción apropiada.

La implementación de códigos de error es una forma ortodoxa de manejar excepciones. Es como el uso de la cadena frente al generador de cadenas.

Estefany Velez
fuente
44
en otras palabras: las implementaciones arrojan subclases de las excepciones definidas en la API.
Andrew Cooke
2

Las excepciones IM-very-HO deben juzgarse caso por caso, porque al romper el flujo de control aumentarán la complejidad real y percibida de su código, en muchos casos innecesariamente. Dejando a un lado la discusión relacionada con el lanzamiento de excepciones dentro de sus funciones, que en realidad puede mejorar su flujo de control, si se trata de lanzar excepciones a través de los límites de llamadas, considere lo siguiente:

Permitir que una persona que llama rompa su flujo de control puede no proporcionar ningún beneficio real, y puede no haber una manera significativa de lidiar con la excepción. Para un ejemplo directo, si uno está implementando el patrón Observable (en un lenguaje como C # donde tiene eventos en todas partes y no hay explícito throwsen la definición), no hay una razón real para permitir que el Observador rompa su flujo de control si se bloquea, y no hay una manera significativa de lidiar con sus cosas (por supuesto, un buen vecino no debe tirar al observar, pero nadie es perfecto).

La observación anterior se puede extender a cualquier interfaz débilmente acoplada (como usted señaló); Creo que en realidad es una norma que después de arrastrar 3-6 cuadros de pila, una excepción no detectada probablemente termine en una sección de código que:

  • es demasiado abstracto para lidiar con la excepción de manera significativa, incluso si la excepción en sí misma se presenta;
  • está realizando una función genérica (no podría importarme menos por qué falló, como una bomba de mensajes o lo observable);
  • es específico, pero con una responsabilidad diferente, y realmente no debería preocuparse;

Teniendo en cuenta lo anterior, decorar interfaces con throwssemántica es solo una ganancia funcional marginal, porque a muchas personas que llaman a través de contratos de interfaz solo les importaría si fallaras, no por qué.

Diría que luego se convierte en una cuestión de gusto y conveniencia: su enfoque principal es recuperar con gracia su estado tanto en la persona que llama como en la persona que llama después de una "excepción", por lo tanto, si tiene mucha experiencia en mover códigos de error (próximamente de un fondo C), o si estás trabajando en un entorno donde las excepciones pueden volverse malvadas (C ++), no creo que tirar cosas sea tan importante para una POO agradable y limpia que no puedas confiar en tu viejo patrones si no te sientes cómodo con él. Especialmente si lleva a romper el SoC.

Desde una perspectiva teórica, creo que una forma de manejar las excepciones de SoC-kosher puede derivarse directamente de la observación de que la mayoría de las veces a la persona que llama directamente solo le importa que hayas fallado, no por qué. La persona que llama arroja, alguien muy cerca de arriba (2-3 fotogramas) captura una versión mejorada, y la excepción real siempre se hunde en un controlador de errores especializado (incluso si solo se traza): aquí es donde AOP sería útil, porque estos controladores Es probable que sean horizontales.

vski
fuente
1

Favorecer excepciones sobre códigos de error

  • Ambos deberían coexistir.

  • Devuelve el código de error cuando anticipa cierto comportamiento.

  • Regrese la excepción cuando no anticipó algún comportamiento.

  • Los códigos de error normalmente están asociados con un solo mensaje, cuando el tipo de excepción permanece, pero un mensaje puede variar.

  • La excepción tiene un seguimiento de pila, cuando el código de error no. No uso códigos de error para depurar el sistema roto.

Codificación de interfaces no implementaciones

Esto puede ser específico de JAVA, pero cuando declaro mis interfaces no especifico qué excepciones podría generar una implementación de esa interfaz, simplemente no tiene sentido.

Cuando detectamos una excepción, ¿estamos haciendo suposiciones sobre la implementación?

Esto es totalmente de usted. Puede intentar capturar un tipo de excepción muy específico y luego capturar un tipo más general Exception. ¿Por qué no dejar que la excepción se propague por la pila y luego manejarla? Alternativamente, puede mirar la programación de aspectos donde el manejo de excepciones se convierte en un aspecto "conectable".

¿Qué sucede si la implementación no necesita lanzar una excepción, o necesita lanzar otras excepciones?

No entiendo por qué es un problema para ti. Sí, puede tener una implementación que nunca falla o arroja excepciones y puede tener una implementación diferente que falla constantemente y arroja excepciones. Si ese es el caso, no especifique ninguna excepción en la interfaz y su problema se resolverá.

¿Cambiaría algo si en lugar de excepción su implementación devolviera un objeto de resultado? Este objeto contendría el resultado de su acción junto con cualquier error / falla, si corresponde. Luego puedes interrogar a ese objeto.

CodeART
fuente
1

Abstracción permeable

¿Por qué una interfaz debe especificar qué excepciones se pueden lanzar? ¿Qué sucede si la implementación no necesita lanzar una excepción, o necesita lanzar otras excepciones? No hay forma, a nivel de interfaz, de saber qué excepciones puede querer lanzar una implementación.

En mi experiencia, el código que recibe el error (ya sea a través de una excepción, un código de error o cualquier otra cosa) normalmente no se preocuparía por la causa exacta del error: reaccionaría de la misma manera ante cualquier falla, excepto por un posible informe del error (ya sea un diálogo de error o algún tipo de registro); y este informe se realizaría ortogonalmente al código que llamó el procedimiento de falla. Por ejemplo, este código podría pasar el error a otra pieza de código que sepa cómo informar errores específicos (por ejemplo, formatear una cadena de mensaje), posiblemente adjuntando información de contexto.

Por supuesto, en algunos casos es necesario adjuntar una semántica específica a los errores y reaccionar de manera diferente en función de qué error ocurrió. Tales casos deben documentarse en la especificación de la interfaz. Sin embargo, la interfaz aún puede reservarse el derecho de lanzar otras excepciones sin un significado específico.

Ambroz Bizjak
fuente
1

Creo que las excepciones permiten escribir un código más estructurado y conciso para informar y manejar errores: el uso de códigos de error requiere verificar los valores de retorno después de cada llamada y decidir qué hacer en caso de un resultado inesperado.

Por otro lado, estoy de acuerdo en que las excepciones revelan detalles de implementación que deberían ocultarse al código que invoca una interfaz. Dado que no es posible saber a priori qué parte del código puede lanzar qué excepciones (a menos que se declaren en la firma del método como en Java), al utilizar excepciones, estamos introduciendo dependencias implícitas muy complejas entre diferentes partes del código, que es Contra el principio de minimizar las dependencias.

Resumiendo:

  • Creo que las excepciones permiten un código más limpio y un enfoque más agresivo para las pruebas y la depuración porque las excepciones no detectadas son mucho más visibles y difíciles de ignorar que los códigos de error (fallan pronto).
  • Por otro lado, los errores de excepción no detectados que no se descubren durante las pruebas pueden aparecer en un entorno de producción en forma de bloqueo. En ciertas circunstancias, este comportamiento no es aceptable y en este caso creo que usar códigos de error es un enfoque más sólido.
Giorgio
fuente
1
Estoy en desacuerdo. Sí, las excepciones no detectadas pueden bloquear una aplicación, pero los códigos de error no verificados también pueden hacerlo, por lo que es un lavado. Si usa las excepciones correctamente, las únicas no detectadas serán las fatales (como OutOfMemory), y para estos, estrellarse de inmediato es lo mejor que puede hacer.
sleske
El código de error es parte del contrato entre la persona que llama m1 y la persona que llama m2: los posibles códigos de error se definen solo en la interfaz de m2. Con excepciones (a menos que esté utilizando Java y declarando todas las excepciones lanzadas en las firmas de métodos) tiene un contrato implícito entre el llamador m1 y todos los métodos que m2 puede llamar de forma recursiva. Por supuesto, es un error no verificar un código de error devuelto, pero siempre es posible hacerlo. Por otro lado, no siempre es posible verificar todas las excepciones generadas por un método, a menos que sepa cómo se implementa.
Giorgio
Primero: puedes verificar todas las excepciones, solo haz "manejo de excepciones de Pokémon" (tienes que atraparlas a todas, es decir, catch Exceptiono incluso Throwable, o equivalente).
sleske
1
En la práctica, si la API está diseñada correctamente, especificará todas las excepciones que el cliente puede manejar de manera significativa; estas deben capturarse específicamente. Estos son los equivalentes de los códigos de error). Cualquier otra excepción significa "error interno", y la aplicación deberá cerrar, o al menos cerrar el subsistema correspondiente. Puedes atraparlos si quieres (ver arriba), pero por lo general solo debes dejarlos burbujear. Ese "burbujeo" es la principal ventaja de usar excepciones. Todavía puede atraparlos más arriba, o no, según las necesidades.
sleske
-1

Sesgado a la derecha tampoco.

No se puede ignorar, se debe manejar, es completamente transparente. Y SI usa el tipo de error correcto para zurdos, transmite la misma información que una excepción de Java.

¿Abajo? El código con el manejo adecuado de errores se ve desagradable (cierto para todos los mecanismos).

Keynan
fuente
Esto no parece ofrecer nada sustancial sobre los puntos hechos y explicados en las 10 respuestas anteriores. ¿Por qué toparse con una pregunta de dos años con cosas así?
mosquito
Excepto que nadie aquí mencionó el sesgo correcto tampoco. Hugomg se acercó hablando de Haskell, sin embargo, Quizás es un controlador de errores de mierda, ya que no deja ninguna explicación de por qué ocurrió el error, ni ningún método directo para recuperarse, y las devoluciones de llamadas son uno de los pecados más grandes en el diseño del flujo de control. Y esta pregunta surgió en google.
Keynan