Estoy trabajando como contratista diseñando aplicaciones Java empresariales para mi cliente en el rol de líder técnico. La aplicación será utilizada por los usuarios finales y habrá un equipo de soporte que la respaldará cuando nos vayamos.
Los otros clientes potenciales técnicos con los que estoy trabajando tienen la impresión de que el manejo de excepciones ensuciará el código. El sistema debe lanzar excepciones verificadas solo desde el nivel de Servicio y el resto del código debe lanzar excepciones de tiempo de ejecución de todos los demás niveles para que no sea necesario manejar las excepciones no verificadas.
¿Cuál es la necesidad de lanzar una excepción no verificada en una aplicación comercial?
De mi experiencia en el pasado sobre excepciones de tiempo de ejecución:
1) Las excepciones no marcadas hacen que el código sea impredecible porque no se muestran ni siquiera en el Javadoc.
2) Lanzar excepciones no verificadas en una aplicación comercial no tiene sentido porque cuando lo lanzas y va directo a la cara de los usuarios, ¿cómo se lo explicas al usuario? He visto suficientes aplicaciones web que muestran lo 500 -Internal Error. Contact Administrator
que no significa nada para un usuario final o para el equipo de soporte que administra la aplicación.
3) Lanzar excepciones de tiempo de ejecución obliga a los usuarios de la clase que lanza la excepción a recorrer el código fuente para depurar y ver por qué se lanza la excepción. Esto solo se puede evitar si el Javadoc de la excepción de tiempo de ejecución está excelentemente documentado, lo que nunca es un caso.
fuente
@throws
etiqueta, lo que por cierto es una buena práctica.@throws
etiqueta Javadoc para documentar cada excepción no verificada que un método puede lanzar, pero no use la palabra clave throws para incluir excepciones no verificadas en la declaración del método.Respuestas:
Las excepciones marcadas son un expriment fallido en el diseño del lenguaje. Te obligan a tener abstracciones extremadamente agujereadas y código sucio. Deben evitarse tanto como sea posible.
En cuanto a sus puntos:
1) Las excepciones marcadas ensucian el código y no son menos impredecibles porque aparecen en todas partes .
2) ¿Cómo se muestra mejor una excepción marcada al usuario? La única diferencia real entre las excepciones marcadas y no marcadas es técnica y afecta solo al código fuente.
3) ¿Has oído hablar de los rastros de la pila? Le dicen exactamente dónde se produjo la excepción, sin importar si está marcada o no. En realidad, las excepciones marcadas tienden a ser peores para la depuración porque a menudo se envuelven, lo que conduce a trazas de pila más largas y feas, o incluso se pierden juntas porque el ajuste se realizó incorrectamente.
Hay dos tipos de excepciones: las que ocurren "normalmente" y generalmente se manejan muy cerca de donde ocurren, y las que son realmente excepcionales y se pueden manejar genéricamente en una capa muy alta (simplemente cancele la acción actual y regístrela / muestra un error).
Las excepciones marcadas fueron un intento de poner esta distinción en la sintaxis del lenguaje en el punto en que se definen las excepciones. Los problemas con esto son
fuente
SQLException extends Exception
signifique que elegir lanzar unaSQLException
porque un error tiene que ver con el acceso a la base de datos automáticamente significa que la excepción está marcada. Y puede documentar excepciones no verificadas en los comentarios Javadoc muy bien. Funciona bien para todos los demás idiomas.Mi opinión es que el tipo de excepción que se produce depende de lo que esté haciendo su código.
Lanzo excepciones comprobadas cuando espero que sucedan con bastante frecuencia (usuarios que ingresan datos dudosos, por ejemplo) y espero que el código de llamada maneje la situación.
Lanzo excepciones no verificadas / en tiempo de ejecución (no tan a menudo como marcadas) cuando tengo una situación rara que no espero que maneje el código de llamada. Un ejemplo podría ser algún tipo de error extraño relacionado con la memoria que nunca espero que ocurra. Sin marcar están los tipos de errores que esperas que la aplicación caiga.
Ninguna excepción debería aparecer frente a un usuario sin algún nivel de soporte. Incluso si es solo un "corte y pegue este volcado de error en un correo electrónico". Nada es más molesto para un usuario que saber que hay un error, pero no recibir detalles ni acciones que puedan tomar para iniciar la reparación.
Supongo que la filosofía que mencionas proviene de una de dos fuentes:
fuente
Si no desea excepciones de tiempo de ejecución no verificadas, ¿por qué está utilizando Java? Existe la posibilidad de excepciones de tiempo de ejecución en casi todas partes, en particular las excepciones NullPointerException, ArithmeticException, ArrayIndexOutOfBounds, etc.
Y cuando lea una vez los archivos de registro de algún sistema J2EE, como, por ejemplo, una instalación de SAP NetWeaver, verá que tales excepciones ocurren literalmente todo el tiempo.
fuente
Hay algunas reglas para el manejo de excepciones que debe tener en cuenta. Pero primero, debe recordar que las excepciones son parte de la interfaz expuesta por el código; documentarlos . Esto es especialmente importante cuando la interfaz es pública, por supuesto, pero también es una muy buena idea en las interfaces privadas.
Las excepciones solo deben manejarse en el punto donde el código puede hacer algo sensato con ellas. La peor opción de manejo es no hacer nada al respecto, lo que solo debe hacerse cuando esa es exactamente la opción correcta. (Cuando tengo una situación así en mi código, incluyo un comentario al respecto para que no me preocupe por el cuerpo vacío).
La segunda peor opción es lanzar una excepción no relacionada sin el original adjunto como causa. El problema aquí es que la información dentro de la excepción original que permitiría el diagnóstico del problema se pierde; está creando algo con lo que nadie puede hacer nada (aparte de quejarse de que "no funciona", y todos sabemos cómo odiamos esos informes de errores).
Mucho mejor es registrar la excepción. Eso le permite a alguien descubrir cuál es el problema y solucionarlo, pero solo debe registrar la excepción en el punto en el que de otro modo se perdería o informaría a través de una conexión externa. Esto no se debe a que el registro más frecuente sea un problema importante como tal, sino a que el registro excesivo significa que el registro consume más espacio sin contener más información. Una vez que haya registrado la excepción, puede informar un resumen al usuario / cliente con buena conciencia (siempre y cuando también incluya el tiempo de generación u otro identificador de correlación) en ese informe para que la versión corta pueda coincidir arriba con los detalles si es necesario).
La mejor opción es, por supuesto, manejar completamente la excepción, lidiando con la situación de error en su totalidad. Si puedes hacer esto, ¡hazlo! Incluso podría significar que puede evitar tener que registrar la excepción.
Una forma de manejar una excepción es lanzar otra excepción que proporcione una descripción de nivel superior del problema (por ejemplo, "
failed to initialize
" en lugar de "index out of bounds
"). Este es un buen patrón siempre que no pierda la información sobre la causa de la excepción; use la excepción detallada para inicializar lacause
excepción de nivel superior o registre los detalles (como se discutió anteriormente). El registro es más apropiado cuando está a punto de cruzar un límite entre procesos, como una llamada IPC, porque no hay garantía de que la clase de excepción de bajo nivel esté presente en el otro extremo de la conexión. Mantenerse como una causa adjunta es lo más apropiado al cruzar un límite interno.Otro patrón que ves es atrapar y soltar:
Este es un antipatrón a menos que tenga restricciones de tipo de otras
catch
cláusulas que significan que no puede dejar que la excepción pase sola. Entonces es solo una característica fea de Java.No existe una diferencia real entre las excepciones verificadas y las no verificadas, aparte del hecho de que debe declarar las excepciones verificadas que cruzan los límites del método. Todavía es una buena idea documentar excepciones no verificadas (con el
@throws
comentario de javadoc) si sabe que su código las arroja deliberadamente. No arrojes deliberadamentejava.lang.Error
o sus subclases (a menos que estés escribiendo una implementación JVM).Opinión: Un caso de error inesperado siempre representa un error en su código. Las excepciones marcadas son una forma de gestionar esta amenaza, y cuando los desarrolladores usan deliberadamente excepciones no verificadas como una forma de evitar el problema de manejar casos de error, está acumulando una gran cantidad de deudas técnicas que tendrá que limpiar en algún momento si quieres un código robusto El manejo descuidado de errores no es profesional (y observar el manejo de errores es una buena manera de determinar qué tan bueno es realmente un programador).
fuente
Creo que SOLO deberías lanzar una excepción marcada cuando la aplicación pueda recuperarse. Por lo tanto, los usuarios de su biblioteca deben detectar esas excepciones y hacer lo que sea necesario para recuperarse. Cualquier otra cosa debe ser desmarcada.
Como un ejemplo,
Si su aplicación carga datos desde un archivo o una base de datos. Entonces,..
la persona que llama siempre puede detectar la MissingDataFileException marcada y luego intentar cargar los datos de la base de datos.
fuente