En Java, ¿para qué sirven las excepciones comprobadas? [cerrado]

14

Las excepciones comprobadas de Java han tenido mala prensa a lo largo de los años. Un signo revelador es que, literalmente, es el único idioma en el mundo que los tiene (ni siquiera otros idiomas JVM como Groovy y Scala). Las bibliotecas de Java prominentes como Spring y Hibernate tampoco las usan.

Personalmente, he encontrado un uso para ellos ( en lógica de negocios entre capas), pero por lo demás soy bastante Excepciones anti-verificadas.

¿Hay otros usos que no conozco?

    
pregunta Brad Cupit 16.11.2010 - 02:42
fuente

8 respuestas

22

En primer lugar, como cualquier otro paradigma de programación, debe hacerlo correctamente para que funcione bien.

Para yo , la ventaja de las excepciones comprobadas es que los autores de la biblioteca de tiempo de ejecución de Java YA han decidido qué problemas comunes puedo esperar razonablemente que pueda manejar en la llamada punto (a diferencia de un bloque de huellas de impresión de alto nivel) y considere lo antes posible cómo manejar estos problemas.

Me gustan las excepciones marcadas porque hacen que mi código sea más robusto al obligarme a pensar en la recuperación de errores lo antes posible.

Para ser más precisos, para yo esto hace que mi código sea más robusto, ya que me obliga a considerar casos extraños en una esquina al principio del proceso, en lugar de decir "Oops, mi código no se controla si el archivo aún no existe "basado en un error en la producción, que luego tendrá que volver a trabajar su código para manejar. Agregar el manejo de errores al código existente puede ser una tarea no trivial, y por lo tanto costosa, cuando se alcanza el mantenimiento en lugar de hacerlo desde el principio.

Puede ser que el archivo faltante sea una cosa fatal y debería causar que el programa se caiga en llamas, pero usted toma esa decisión con

} catch (FileNotFoundException e) {
  throw new RuntimeException("Important file not present", e);
}

Esto también muestra un efecto secundario muy importante. Si ajusta una excepción, puede agregar una explicación que va en el seguimiento de la pila . Esto es extremadamente poderoso porque puedes agregar información sobre, por ejemplo, el nombre del archivo que faltaba o los parámetros pasados a este método u otra información de diagnóstico, y esa información está presente justo en el seguimiento de la pila , que frecuentemente es lo único que se obtiene cuando un programa tiene se estrelló.

La gente puede decir "podemos ejecutar esto en el depurador para reproducirlo", pero he encontrado que muy a menudo los errores de producción no se pueden reproducir más adelante, y no podemos ejecutar los depuradores en la producción excepto por muy casos desagradables en los que esencialmente está en juego tu trabajo.

Cuanta más información haya en el seguimiento de tu pila, mejor. Las excepciones comprobadas me ayudan a obtener esa información allí, y pronto.

EDITAR: Esto también se aplica a los diseñadores de bibliotecas. Una biblioteca que uso a diario contiene muchas, muchas excepciones comprobadas que podrían haber sido diseñadas mucho mejor, por lo que es menos tedioso de usar.

    
respondido por el user1249 16.11.2010 - 06:13
fuente
11

Tiene dos buenas respuestas que explican qué excepciones marcadas se han convertido en práctica. (+1 a ambos). Pero también valdría la pena examinar a qué se destinaron en teoría, porque la intención realmente vale la pena.

Las excepciones comprobadas tienen la intención de hacer que el idioma sea más seguro. Considere un método simple como la multiplicación de enteros. Podría pensar que el tipo de resultado de este método sería un entero, pero, estrictamente hablando, el resultado es un entero o una excepción de desbordamiento. Teniendo en cuenta el resultado entero por sí mismo como el tipo de retorno del método no expresa el rango completo de la función.

Visto desde este punto de vista, no es estrictamente cierto que las excepciones comprobadas no hayan llegado a otros idiomas. Ellos simplemente no han tomado la forma que Java utiliza. En las aplicaciones de Haskell, es común usar tipos de datos algebraicos para distinguir entre la finalización exitosa y no exitosa de la función. Aunque esto no es una excepción, per se, la intención es muy parecida a una excepción comprobada; es una API diseñada para obligar al consumidor de API a manejar tanto el caso exitoso en el caso no exitoso, por ejemplo:

data Foo a =
     Success a
   | DidNotWorkBecauseOfA
   | DidNotWorkBecauseOfB

Esto le dice al programador que la función tiene dos resultados posibles adicionales además del éxito.

    
respondido por el Craig Stuntz 16.11.2010 - 03:34
fuente
11

OMI, las excepciones comprobadas son una implementación defectuosa de lo que podría haber sido una idea bastante decente (en circunstancias completamente diferentes, pero en realidad no es una buena idea en la circunstancia actual). / p>

La buena idea es que sería bueno que el compilador verifique que se capturarán todas las excepciones que un programa tiene potencial para lanzar. La implementación defectuosa es que para hacer eso, Java te obliga a lidiar con la excepción directamente en cualquier clase que invoque cualquier cosa declarada para lanzar una excepción marcada. Una de las ideas (y ventajas) más básicas del manejo de excepciones es que, en caso de error, permite que las capas intermedias de código que no tienen nada que ver con un error en particular, ignoren completamente su existencia. Las excepciones comprobadas (tal como se implementaron en Java) no permiten eso, por lo que se destruye una ventaja importante (¿la principal?) De comenzar con el manejo de excepciones.

En teoría, podrían haber hecho útiles las excepciones verificadas al aplicarlas solo en todo el programa, es decir, mientras "construyen" el programa, construyen un árbol de todas las rutas de control en el programa. Varios nodos en el árbol se anotarían con 1) excepciones que pueden generar, y 2) excepciones que pueden capturar. Para asegurarte de que el programa era correcto, luego caminarías por el árbol, verificando que todas las excepciones que se lanzaron a cualquier nivel en el árbol fueron capturadas en algún nivel más alto en el árbol.

La razón por la que no hizo eso (supongo que, de todos modos) es que hacerlo sería extremadamente difícil; de hecho, dudo que alguien haya escrito un sistema de compilación que pueda hacer eso para cualquier cosa que no sean extremadamente lenguajes / sistemas simples (que limitan con "juguete"). Para Java, cosas como la carga dinámica de clases hacen que sea aún más difícil que en muchos otros casos. Peor aún, (a diferencia de algo como C) Java no está (al menos normalmente) estáticamente compilado / vinculado a un ejecutable. Eso significa que nada en el sistema realmente tiene la conciencia global de incluso intentar hacer este tipo de cumplimiento hasta que el usuario final comience a cargar el programa para ejecutarlo.

Hacer cumplir la ley en ese punto no es práctico por un par de razones. En primer lugar, incluso en el mejor de los casos extendería los tiempos de inicio, que ya son una de las quejas más grandes y comunes de Java. Segundo, para hacer mucho bien, realmente necesitas detectar el problema lo suficientemente temprano para que un programador lo arregle. Cuando el usuario está cargando el programa, es demasiado tarde para hacer mucho bien: sus únicas opciones en ese momento son ignorar el problema, o negarse a cargar / ejecutar el programa, con la posibilidad de que pueda ser una excepción que no fue detectada.

Tal como están, las excepciones verificadas son peores que inútiles, pero los diseños alternativos para las excepciones verificadas son aún peores. Si bien la idea básica para las excepciones marcadas parece ser buena, en realidad no es muy buena, y resulta que es particularmente pobre para Java. Para algo como C ++, que normalmente se compila / vincula en un ejecutable completo sin nada parecido a la carga dinámica / reflexiva de clases, tendrías un poco más de oportunidad (aunque, francamente, incluso aplicándolos correctamente sin el mismo tipo de desorden) la causa actual en Java probablemente aún esté más allá del estado actual de la técnica).

    
respondido por el Jerry Coffin 16.11.2010 - 05:33
fuente
10

Son realmente buenos para los programadores molestos y alentar la excepción para tragar. La mitad del punto de las excepciones es para que tenga una forma predeterminada de manejar los errores y no tenga que pensar en propagar explícitamente las condiciones de error que no puede manejar. (El criterio predeterminado es que si nunca maneja el error en cualquier lugar de su código, ha afirmado efectivamente que no puede suceder, y se le deja una salida sana y un seguimiento de la pila si está equivocado). Se anulan las excepciones comprobadas esta. Se sienten como si tuvieran que propagar explícitamente los errores en C.

    
respondido por el dsimcha 16.11.2010 - 02:47
fuente
5

Creo que es justo decir que las excepciones comprobadas fueron un poco un experimento fallido. Donde se equivocaron es que rompieron capas:

  • El Módulo A podría estar construido sobre el Módulo B, donde
  • El Módulo B podría estar construido sobre el Módulo C.
  • El módulo C podría saber cómo identificar un error, y
  • El módulo A podría saber cómo manejar el error.

La buena separación de preocupado está rota, porque ahora el conocimiento de los errores que podrían haberse limitado a A y C ahora tiene que estar dispersos sobre B.

Hay una buena discusión de las excepciones verificadas en Wikipedia.

Y Bruce Eckel tiene también un buen artículo . Aquí hay una cita:

  

[T] las reglas más aleatorias que acumulas   El programador, reglas que tienen.   nada que ver con resolver el problema   a la mano, cuanto más lento pueda el programador   Produce. Y esto no parece   Ser un factor lineal, pero un exponencial.   uno

Creo que para el caso de C ++, si todos los métodos tienen la cláusula de especificación throws , entonces puede tener algunas optimizaciones agradables. Sin embargo, no creo que Java pueda tener esas ventajas, porque RuntimeExceptions no está marcado. Un JIT moderno debería poder optimizar el código perfectamente bien de todos modos.

Una buena característica de AspectJ es el suavizado de excepciones: puede convertir las excepciones marcadas en excepciones no verificadas, específicamente para mejorar las capas.

Quizás es irónico que Java haya pasado por todo este problema, cuando podría haber revisado null en su lugar, lo que podría han sido mucho más valiosos .

    
respondido por el Macneil 16.11.2010 - 03:07
fuente
5

Me encantan las excepciones.

Sin embargo, estoy constantemente desconcertado por su mal uso.

  1. No los use para manejar el flujo. No desea código que intente hacer algo y use una excepción como disparador para hacer otra cosa, ya que las excepciones son objetos que se deben crear y usar memoria, etc., simplemente porque no se pudo molestar en escribir algo. tipo de si () verifique antes de hacer su llamada. Eso es simplemente perezoso y le da a la gloriosa excepción un mal nombre.

  2. No los trague. Siempre. Bajo cualquier circunstancia. Como mínimo absoluto, debe pegar algo en su archivo de registro para indicar que ocurrió una excepción. Tratar de rastrear su camino a través del código que traga las excepciones es una pesadilla. Nuevamente, ¡maldita sea la excepción-los tragadores por poner en desacreditación a la poderosa Excepción!

  3. Trata las excepciones con tu sombrero OO encendido. Cree sus propios objetos de excepción con jerarquías significativas. Ponga su lógica empresarial y sus excepciones de la mano. Solía encontrar que si comenzaba en una nueva área de un sistema, encontraba la necesidad de subclasificar Excepción dentro de la media hora de codificación, por lo que en estos días comienzo escribiendo las clases de Excepción.

  4. Si está escribiendo bits de código 'marco', asegúrese de que todas sus interfaces iniciales estén escritas para lanzar sus propias Excepciones nuevas cuando corresponda ... y asegúrese de que sus codificadores tengan algún código de ejemplo en el lugar de qué hacer cuando su código arroja una excepción IOException, pero la interfaz a la que están escribiendo quiere lanzar una 'Explicación de aplicación de informe'.

Una vez que haya asimilado la forma de hacer que las excepciones funcionen para usted, nunca volverá a mirar hacia atrás.

    
respondido por el DanW 18.11.2010 - 16:58
fuente
4

Las excepciones comprobadas también están en ADA.

(Advertencia, esta publicación contiene convicciones sólidas con las que puedes encontrarte).

A los programadores no les gustan y se quejan, o escriben códigos de excepción para tragar.

Existen excepciones comprobadas porque las cosas no solo no pueden funcionar, también puede hacer un análisis de modo / efectos de falla y determinar esto por adelantado.

Las lecturas de archivos pueden fallar. Las llamadas RPC pueden fallar. La red IO puede fallar. Los datos pueden tener un formato incorrecto cuando se analizan.

El "camino feliz" para el código es fácil.

Conocí a un chico en la universidad que podía escribir un gran código de "ruta feliz". Ninguno de los casos de borde nunca funcionó. En estos días él hace Python para una compañía de código abierto. Nuff dijo.

Si no quieres manejar las excepciones marcadas, lo que realmente estás diciendo es

While I'm writing this code, I don't want to consider obvious failure modes.

The User will just have to like the program crashing or doing weird things.

But that's okay with me because 

I'm so much more important than the people who will have to use the software

in the real, messy, error-prone world.

After all, I write the code once, you use it all day long.

Por lo tanto, los programadores no van a gustar las excepciones comprobadas, porque significa más trabajo.

Por supuesto, otras personas podrían haber querido que se hiciera ese trabajo.

Es posible que hayan deseado la respuesta correcta, incluso si el servidor de archivos falló o la memoria USB muere.

Es una extraña creencia en la comunidad de programación que debes usar un lenguaje de programación que te haga la vida más fácil, que disfrutes, cuando tu trabajo es escribir software. Tu trabajo es resolver el problema de alguien, no permitirte participar en la improvisación programática de Jazz.

Si eres un programador aficionado (no estás programando por dinero), siéntete libre de programar en C # o en algún otro idioma sin excepciones marcadas. Heck, cortar el hombre medio y el programa en Logo. Puedes dibujar bonitos patrones en el piso con la tortuga.

    
respondido por el Tim Williscroft 16.11.2010 - 03:46
fuente
4

Las excepciones comprobadas deberían haber alentado a las personas a manejar los errores cerca de la fuente. Cuanto más lejos de la fuente, más funciones terminaron en medio de la ejecución, y más probable es que el sistema haya entrado en un estado inconsistente. Además, es más probable que detecte una excepción incorrecta por accidente.

Lamentablemente, las personas han tendido a ignorar las excepciones o agregar especificaciones de lanzamiento cada vez mayores. Ambos pierden el punto de lo que las excepciones marcadas deben suponer para alentar. Son como transformar código de procedimiento para usar muchas funciones de Getter y Setter que supuestamente lo hacen OO.

Esencialmente, las excepciones comprobadas intentan demostrar un cierto grado de corrección en su código. Es más o menos la misma idea que la escritura estática, ya que intenta probar que ciertas cosas son correctas incluso antes de que se ejecute el código. El problema es que todas esas pruebas adicionales requieren esfuerzo y ¿vale la pena el esfuerzo?

    
respondido por el Winston Ewert 16.11.2010 - 05:12
fuente

Lea otras preguntas en las etiquetas