Las excepciones comprobadas de Java han tenido mala prensa a lo largo de los años. Una señal reveladora es que es, literalmente, el único idioma del mundo que los tiene (ni siquiera otros lenguajes JVM como Groovy y Scala). Prominentes bibliotecas de Java como Spring e Hibernate tampoco las usan.
Personalmente, he encontrado un uso para ellos ( en la lógica de negocios entre capas), pero de lo contrario, soy una excepción bastante verificada.
¿Hay otros usos que no conozco?
java
exceptions
errors
Brad Cupit
fuente
fuente
Respuestas:
En primer lugar, como cualquier otro paradigma de programación, debe hacerlo correctamente para que funcione bien.
Para mí, la ventaja de las excepciones comprobadas es que los autores de la biblioteca de tiempo de ejecución de Java YA han decidido por mí qué problemas comunes podría razonablemente esperar que pueda manejar en el punto de llamada (en lugar de una captura de impresión de nivel superior) morir bloqueado) y considerar 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 mí esto hace que mi código sea más robusto, ya que me obliga a considerar casos extraños de esquina muy temprano en el proceso en lugar de decir "Vaya, mi código no se maneja si el archivo aún no existe" basado en un error en la producción, que luego debe modificar su código para manejarlo. Agregar el manejo de errores al código existente puede ser una tarea no trivial, y por lo tanto costosa, cuando se realiza el mantenimiento en lugar de hacerlo desde el principio.
Puede ser que el archivo faltante sea algo fatal y deba causar que el programa se incendie, pero luego tomas esa decisión con
Esto también muestra un efecto secundario muy importante. Si envuelve una excepción, puede agregar una explicación que va en el seguimiento de la pila . Esto es extremadamente poderoso porque puede 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 directamente en el seguimiento de la pila, que con frecuencia es lo único que usted necesita. obtener cuando un programa se ha bloqueado.
La gente puede decir "podemos ejecutar esto en el depurador para reproducir", pero he descubierto que con frecuencia los errores de producción no pueden reproducirse más tarde, y no podemos ejecutar depuradores en producción, excepto en casos muy desagradables en los que esencialmente está en juego su trabajo.
Cuanta más información haya en su seguimiento de pila, mejor. Las excepciones marcadas me ayudan a poner esa información allí, y temprano.
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 haciendo que sea menos tedioso de usar.
fuente
Tienes dos buenas respuestas que explican en qué se han convertido las excepciones marcadas en la práctica. (+1 a ambos.) Pero también valdría la pena examinar para qué estaban destinados en teoría, porque la intención realmente vale la pena.
Las excepciones marcadas tienen la intención de hacer que el idioma sea más seguro. Considere un método simple como la multiplicación de enteros. Puede 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. Considerando 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 decir que las excepciones marcadas no han llegado a otros idiomas. Simplemente no han tomado la forma que usaba Java. En las aplicaciones de Haskell, es común usar tipos de datos algebraicos para distinguir entre la finalización exitosa y la no exitosa de la función. Aunque esto no es una excepción, per se, la intención es muy similar a una excepción marcada; es una API diseñada para obligar al consumidor de API a manejar tanto a los exitosos como a los casos no exitosos, por ejemplo:
Esto le dice al programador que la función tiene dos resultados posibles adicionales además del éxito.
fuente
En mi opinión, las excepciones marcadas son una implementación defectuosa de lo que podría haber sido una idea bastante decente (en circunstancias completamente diferentes, pero en realidad ni siquiera es una buena idea en las circunstancias actuales).
La buena idea es que sería bueno que el compilador verifique que se detectarán todas las excepciones que un programa tiene el potencial de 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 que se declare para lanzar una excepción marcada. Una de las ideas más básicas (y ventajas) 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 por completo su existencia. Las excepciones marcadas (como se implementan en Java) no permiten eso, destruyendo así una ventaja importante (¿la principal?) Del manejo de excepciones para empezar.
En teoría, podrían haber hecho que las excepciones comprobadas fueran útiles al aplicarlas solo en todo el programa, es decir, al "construir" el programa, construir un árbol de todas las rutas de control en el programa. Se anotarían varios nodos en el árbol con 1) excepciones que pueden generar y 2) excepciones que pueden atrapar. Para asegurarse de que el programa fuera correcto, caminaría por el árbol y verificaría que cada excepción que se haya lanzado en cualquier nivel del árbol se haya capturado en algún nivel superior del árbol.
La razón por la que no hicieron eso (supongo, de todos modos) es que hacerlo sería insoportablemente difícil; de hecho, dudo que alguien haya escrito un sistema de construcción que pueda hacer eso para cualquier cosa que no sea extremadamente simple (bordeando el "juguete" ") lenguajes / sistemas. Para Java, cosas como la carga dinámica de clases lo hacen 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) compilado / vinculado estáticamente a un ejecutable. Eso significa que nada en el sistema realmente tiene la conciencia global para tratar de hacer este tipo de aplicación hasta que el usuario final realmente comience a cargar el programa para ejecutarlo.
Hacer cumplir en ese momento no es práctico por un par de razones. En primer lugar, incluso en el mejor de los casos, ampliaría los tiempos de inicio, que ya son una de las quejas más grandes y comunes sobre Java. En segundo lugar, para hacer mucho bien, realmente necesita detectar el problema lo suficientemente temprano como para que un programador lo solucione. 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, en caso de que pueda haber una excepción eso no fue atrapado.
Tal como están, las excepciones marcadas son peores que inútiles, pero los diseños alternativos para las excepciones marcadas son aún peores. Si bien la idea básica para las excepciones comprobadas parece ser buena, en realidad no es muy buena, y resulta ser particularmente inadecuada para Java. Para algo como C ++, que normalmente se compila / enlaza en un ejecutable completo sin nada parecido a la carga de clase de reflexión / dinámica, tendrías un poco más de posibilidades (aunque, francamente, incluso luego aplicarlas correctamente sin el mismo tipo de desorden) la causa actual en Java probablemente aún estaría más allá del estado actual de la técnica).
fuente
UnexpectedException
tipo derivado deRuntimeException
. Tenga en cuenta que "tiros" y "no espera" no son contradictorios; sifoo
lanzaBozException
y llamabar
, eso no significa que esperabar
lanzarBozException
.Son realmente buenos para los programadores molestos y fomentan la deglución de excepciones. La mitad del punto de excepciones es para que tenga una forma sensata predeterminada de manejar los errores y no tenga que pensar en propagar explícitamente las condiciones de error que no puede manejar. (El valor predeterminado correcto es que si nunca maneja el error en cualquier parte de su código, ha afirmado efectivamente que no puede suceder, y se queda con una salida sensata y un seguimiento de la pila si está equivocado). esta. Tienen muchas ganas de propagar errores explícitamente en C.
fuente
throws FileNotFoundException
. Solución difícil:catch (FileNotFoundException e) { throw RuntimeException(e); }
Creo que es justo decir que las excepciones marcadas fueron un experimento un poco fallido. Donde se equivocaron es que rompieron las capas:
La agradable separación de los interesados está rota, porque ahora el conocimiento de los errores que podrían haberse limitado a A y C ahora debe dispersarse sobre B.
Hay una buena discusión sobre las excepciones marcadas en Wikipedia.
Y Bruce Eckel también tiene un buen artículo al respecto. Aquí hay una cita:
Creo que para el caso de C ++, si todos los métodos tienen la
throws
cláusula de especificación, entonces puede tener algunas buenas optimizaciones. Sin embargo, no creo que Java pueda tener esas ventajas porqueRuntimeExceptions
no están marcadas. Un JIT moderno debería poder optimizar el código de todos modos.Una buena característica de AspectJ es el suavizado de excepciones: puede convertir las excepciones marcadas en excepciones no marcadas, específicamente para mejorar la estratificación.
Quizás sea irónico que Java haya pasado por todos estos problemas, cuando podría haberlo verificado
null
, lo que podría haber sido mucho más valioso .fuente
Me encantan las excepciones.
Sin embargo, estoy constantemente desconcertado por su mal uso.
No los use para manejar el flujo. No desea un código que intente hacer algo y utilice una excepción como desencadenante para hacer otra cosa, porque las excepciones son objetos que deben crearse y usar memoria, etc., etc. simplemente porque no puede molestarse en escribir algunos tipo de control if () antes de hacer su llamada Eso es simplemente vago y le da un mal nombre a la gloriosa Excepción.
No te los tragues. Nunca. Bajo cualquier circunstancia. Como mínimo absoluto, debe pegar algo en su archivo de registro para indicar que ocurrió una excepción. Intentar rastrear tu camino a través del código que traga excepciones es una pesadilla. De nuevo, ¡maldiga a los tragadores de excepciones por desacreditar a la poderosa Excepción!
Trate las excepciones con su sombrero OO puesto. Crea tus propios objetos de excepción con jerarquías significativas. Capa su lógica de negocios y sus excepciones de la mano. Solía encontrar que si comenzaba en una nueva área de un sistema, encontraría la necesidad de subclasificar Exception dentro de la media hora de la codificación, así que en estos días empiezo escribiendo las clases de Exception.
Si está escribiendo fragmentos de código 'frameworky', asegúrese de que todas sus interfaces iniciales estén escritas para lanzar sus propias Excepciones nuevas cuando sea apropiado ... y asegúrese de que sus codificadores tengan algún código de muestra alrededor del lugar de qué hacer cuando su código lanza una IOException pero la interfaz en la que están escribiendo quiere lanzar una 'ReportingApplicationException'.
Una vez que haya aprendido cómo hacer que las Excepciones funcionen para usted, nunca mirará hacia atrás.
fuente
initCause
o inicialice la excepción con la excepción que la causó. Ejemplo: tiene una utilidad de E / S que solo necesita una excepción si falla la escritura. Sin embargo, hay varias razones por las que una escritura podría fallar (no se pudo obtener acceso, error de escritura, etc.) Lanza tu excepción personalizada con la causa para que no se trague el problema original.Las excepciones marcadas también están en ADA.
(Advertencia, esta publicación contiene creencias muy arraigadas que puede encontrar confrontado).
Los programadores no les gustan y se quejan, o escriben código de deglución de excepción.
Existen excepciones comprobadas porque las cosas no solo pueden dejar de funcionar, también puede hacer un análisis de modo / efectos de falla y determinar esto de antemano.
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 "camino feliz". Ninguno de los casos límite funcionó jamás. En estos días hace Python para una compañía de código abierto. Dijo Nuff.
Si no desea manejar las excepciones marcadas, lo que realmente está diciendo es
Por lo tanto, los programadores no les agradarán a las excepciones marcadas, porque significa más trabajo.
Por supuesto, otras personas podrían haber querido hacer ese trabajo.
Es posible que hayan querido la respuesta correcta incluso si el servidor de archivos falló / la memoria USB se apaga.
Es una creencia extraña en la comunidad de programación que deberías estar usando 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 permitiéndote participar en la improvisación programática de Jazz.
Si eres un programador aficionado (no estás programando por dinero), no dudes en programar en C # o en algún otro lenguaje sin excepciones comprobadas. Diablos, corta al intermediario y programa en Logo. Puedes dibujar bonitos patrones en el suelo con la tortuga.
fuente
Las excepciones marcadas deberían haber alentado a las personas a manejar errores cerca de su fuente. Cuanto más lejos de la fuente, más funciones han terminado en el medio de la ejecución, y es más probable que el sistema haya entrado en un estado inconsistente. Además, es más probable que atrape la excepción incorrecta por accidente.
Lamentablemente, la gente ha tendido a ignorar las excepciones o agregar especificaciones de lanzamiento cada vez mayores. Ambos pierden el sentido de lo que se supone que alentarán las excepciones marcadas. Son como transformar el código de procedimiento para usar muchas funciones de Getter y Setter que supuestamente lo hacen OO.
Esencialmente, las excepciones marcadas intentan probar 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 toda esa prueba adicional requiere esfuerzo y ¿vale la pena el esfuerzo?
fuente