c# - try - Manejo de excepciones usando un HttpModule
throw exception c# (6)
Estamos revisando el manejo de excepciones de uno de los sistemas de la compañía y encontramos un par de cosas interesantes.
La mayoría de los bloques de código (si no todos) están dentro de un bloque try / catch, y dentro del bloque catch se está lanzando una BaseApplicationException nueva, que parece provenir de las bibliotecas de Enterprise. Estoy en un problema aquí ya que no veo los beneficios de hacer esto. (lanzando otra excepción cada vez que ocurre). Uno de los desarrolladores que ha estado usando el sistema por un tiempo dijo que es porque esa clase está a cargo de publicar la excepción (enviar correos electrónicos y cosas por el estilo) pero no estaba muy seguro al respecto. Después de pasar algún tiempo revisando el código, estoy bastante seguro de decir que eso es todo lo que hace es recopilar información sobre el entorno y luego publicarlo.
Mi pregunta es: ¿Es razonable ajustar todo el código dentro de los bloques try {} catch {} y lanzar una nueva excepción? Y si lo es, ¿por qué? ¿Cuál es el beneficio?
Mi opinión personal es que sería mucho más fácil usar un HttpModule, registrarse para el evento Error del evento de la Aplicación y hacer lo que sea necesario dentro del módulo. Si vamos por este camino, ¿perderemos algo? ¿Alguna desventaja?
Tu opinión es muy apreciada.
Echa un vistazo a ELMAH . Hace lo que estás hablando. Muy bien.
Cuando creo bibliotecas trato de proporcionar siempre un número reducido de excepciones para que las personas que llaman puedan manejarlas. Por ejemplo, piense en un componente de repositorio que se conecta a una base de datos sql. Hay TONELADAS de excepciones, desde excepciones de cliente SQL a excepciones de lanzamiento no válidas, que teóricamente pueden arrojarse. Muchos de estos están claramente documentados y pueden ser contabilizados en tiempo de compilación. Por lo tanto, capturo todos los que puedo, los coloco en un solo tipo de excepción, digamos una RepositoryException, y dejo que esa excepción suba la pila de llamadas.
La excepción original se conserva, por lo que se puede diagnosticar la excepción original. Pero mis interlocutores solo deben preocuparse por manejar un único tipo de excepción en lugar de dejar su código en un montón de bloques de captura diferentes.
Hay, por supuesto, algunos problemas con esto. En particular, si la persona que llama puede manejar algunas de estas excepciones, tiene que rootear en RepositoryException y luego encender el tipo de la excepción interna para manejarlo. Es menos limpio que tener un único bloque catch para un único tipo de excepción. Sin embargo, no creo que eso sea un problema.
Parece que la excepción que se lanza no debería haberse implementado como una excepción.
De todos modos, diría que, dado que esta BaseApplicationException es una excepción general de uso múltiple, sería bueno lanzar excepciones que sean más específicas del contexto. Por lo tanto, cuando intente recuperar una entidad desde una base de datos, es posible que desee una EntityNotFoundException. De esta forma, cuando está depurando, no tiene que buscar excepciones internas y apilar trazas para encontrar el verdadero problema. Si esta BAseApplicationException está recopilando información sobre la excepción (como hacer un seguimiento de la excepción interna), entonces esto no debería ser un problema.
Usaría el HttpModule solo cuando no pudiera acercarme más a dónde realmente están pasando las excepciones en el código. Realmente no desea un evento HttModule OnError que sea una declaración de cambio gigante dependiendo de la información de error de BaseApplicationexception.
Para concluir, vale la pena arrojar diferentes excepciones cuando puede dar excepciones más específicas que le dicen la raíz del problema desde el principio.
Según mi experiencia, capture la excepción, agregue el error al objeto Servidor (?). Esto permitirá a .NET hacer lo que necesite hacer, luego mostrará su excepción.
Si estoy leyendo la pregunta correctamente, diría que la implementación de un try / catch que intercepte excepciones (usted no menciona, ¿está captando todas las excepciones, o solo una específica?) Y arroja una excepción diferente, generalmente es algo malo. .
Desventajas:
Como mínimo, perderá la información de rastreo de la pila; la pila que verá solo se extenderá al método en el que se lanza la nueva excepción: es posible que pierda aquí una buena información de depuración.
Si está capturando Exception, corre el riesgo de enmascarar excepciones críticas, como OutOfMemory o con una excepción menos crítica, y dejar así el proceso en ejecución, donde tal vez debería haber sido derribado.
Posibles ventajas:
En algunos casos muy específicos, podría tomar una excepción que no tenga mucho valor de depuración (como algunas excepciones que vuelven de una base de datos) y envolver con una excepción que agregue más contexto, por ejemplo, id del objeto con el que estaba tratando.
Sin embargo, en casi todos los casos, este es un mal olor y debe usarse con precaución.
En general, solo debería detectar una excepción cuando haya algo realista que pueda hacer en esa ubicación, es decir, recuperar, retroceder, ir al plan B, etc. Si no hay nada que pueda hacer al respecto, simplemente deje que pase por alto la cadena . Solo debe capturar y lanzar una nueva excepción si hay datos específicos y útiles disponibles en esa ubicación que pueden aumentar la excepción original y, por lo tanto, ayudar a la depuración.
Soy de la escuela de pensamiento donde deberían usarse los bloqueos try / catch y las excepciones no se vuelven a lanzar. Si tiene código de ejecución que probablemente sea un error, debe ser procesado, registrado y devuelto algo. Retirar la excepción solo sirve para volver a iniciar sesión más adelante en el ciclo de vida de la aplicación.
Aquí hay una publicación interesante sobre cómo usar un HttpModule para manejar excepciones: http://blogs.msdn.com/rahulso/archive/2008/07/13/how-to-use-httpmodules-to-troubleshoot-your-asp- net-application.aspx y http://blogs.msdn.com/rahulso/archive/2008/07/18/asp-net-how-to-write-error-messages-into-a-text-file-using- a-simple-httpmodule.aspx
Nunca 1 catch (Exception ex)
. Período 2 . No hay manera de que pueda manejar todos los diferentes tipos de errores que puede atrapar.
Nunca 3 capture un tipo derivado de una Excepción si no puede manejarlo o proporcionar información adicional (para ser utilizado por los manejadores de excepciones posteriores). Mostrar un mensaje de error no es lo mismo que manejar el error.
Un par de razones para esto, desde lo más alto de mi cabeza:
- Atrapar y volver a tirar es costoso
- Terminarás perdiendo el rastro de la pila
- Tendrás una baja relación señal-ruido en tu código
Si sabe cómo manejar una excepción específica (y reinicie la aplicación al estado previo al error), recójala. (Es por eso que se llama manejo de excepciones ).
Para manejar excepciones que no están atrapadas, escuche los eventos apropiados. Al hacer WinForms, deberá escuchar System.AppDomain.CurrentDomain.UnhandledException
y, si lo hace, Threading
- System.Windows.Forms.Application.ThreadException.
Para las aplicaciones web, existen mecanismos similares ( System.Web.HttpApplication.Error
).
En cuanto a envolver excepciones de marcos en su aplicación (no) excepciones específicas (es decir, throw new MyBaseException(ex);
): completamente sin sentido, y un mal olor. 4
Editar
1 Nunca es una palabra muy dura, especialmente cuando se trata de ingeniería, como señaló @Chris en los comentarios. Admitiré que soy alto en principios cuando primero escribí esta respuesta.
2,3 Ver 1 .
4 Si no traes nada nuevo a la mesa, sigo de pie con esto. Si ha detectado Exception ex
como parte de un método que sabe que podría fallar de muchas maneras, creo que el método actual debería reflejarlo en su firma. Y como sabe, las excepciones no son parte de la firma del método.