En cualquier método o bloque de código donde puede esperar excepciones específicas (interactuando con una base de datos o un servicio externo que puede o no estar disponible, etc.) ajusta ese código en un Try/Catch para atrapar la (s) excepción (es) específica (s) en cuestión. Querrá saber exactamente qué tipo de excepciones se produjeron para manejarlos correctamente. (Naturalmente, use un bloque Finally para deshacerse de cualquier recurso abierto). La manera correcta de manejarlos depende de usted y de cómo desea que se comporte su aplicación.
Definitivamente debe tener un manejo de excepción global para atrapar todo lo inesperado que no se haya resuelto. En no punto, una excepción no controlada debe aparecer para el usuario. El manejador de excepción global solo debe presentar al usuario un mensaje de error amigable y debe registrar la excepción y notificarle lo sucedido. En general, un buen objetivo es identificar la excepción y agregar el código de manejo de errores para capturarlo en su estado localizado antes de que llegue a ser global. El objetivo, con el tiempo, debería ser tener la menor cantidad posible de excepciones globales y tener cualquier código generador de excepciones que tenga su propio manejo de errores para evitar esos casos.
Un ejemplo de esto último podría ser algo tan simple como un método particular que recibe null
argumentos que desea verificar antes de usar esos argumentos. Sin embargo, una cosa que desea evitar es utilizar el manejo de excepciones para el flujo lógico. Por ejemplo ...
Digamos que usted tiene un método que toma un objeto personalizado como un argumento:
public MyMethod(MyObject obj)
{
// ...
}
Su código original asume que obj
siempre tendrá un valor. Sin embargo, después de algún tiempo de uso de producción, descubres que obj
es a veces null
y que arroja un NullReferenceException
desde ese método, que está siendo capturado por el manejador de excepción global.
Puede tener la tentación de simplemente ajustar el código en MyMethod
en su propio bloque de Prueba/Captura para detectar esa excepción. Esto no es necesariamente una buena idea (aunque puede haber casos en que lo sea). En su lugar, usted desea comprobar si null
al comienzo del método:
public MyMethod(MyObject obj)
{
if (obj == null) throw new ArgumentNullException("obj can not be NULL");
// ...
}
Esto encapsula el método mejor y permite que se generen excepciones controladas. Las excepciones no son malas, solo excepciones inesperadas. Tenga en cuenta que lo anterior arrojará la excepción que seguirá burbujeando hasta el controlador global. Por lo tanto, también es una buena idea ajustar las llamadas a este método en un bloque Try/Catch para capturar el ArgumentNullException
y manejarlo en consecuencia. Quizás el código que llama a este método puede corregir la referencia nula e intentarlo de nuevo, tal vez puede probar otra cosa, etc.De todas formas, no desea que el controlador global llegue al administrador global, ya que se ha convertido en una excepción "esperada" y se puede gestionar de forma acorde.
Naturalmente, todavía desea evitar el lanzamiento/captura de las excepciones esperadas en el ejemplo anterior, por lo que las comprobaciones similares para null
deben ocurrir antes de llamar al método para que ni siquiera se llame al método.
Tal vez si el objeto es null
se puede presentar directamente al usuario con un mensaje de error y registrar el error y le notificará de tanta información sobre el estado de cosas como sea posible de manera que se puede investigar por qué es null
y solucionarlo. Quizás ser null
es un estado perfectamente aceptable de ese objeto en ese momento según la lógica de la aplicación. Si es así, verifique si es null
y no se moleste en llamar al método. Solo sigue como siempre.
Es una gran cantidad de código de control de errores y manejo, pero eso es algo bueno.
Editar: Otra cosa a tener en cuenta sobre el manejo de excepciones es que usted debe capturar la excepción solamente si en realidad se puede mango en ese momento. Si el método no puede manejarlo internamente, permita que la excepción salte del método al método de llamada, y así sucesivamente. Por lo tanto, las únicas excepciones que deberían llegar al controlador global son excepciones que no puede manejar en ningún lugar del código (por lo que es un buen objetivo corregir y evitar excepciones globales).
"Manejar" en este caso significaría poder hacer algo al respecto. Tal vez ese algo sea solo registrarlo y continuar, tal vez sea algo para realizar alguna lógica específica, etc. Pero capturar, registrar y relanzar es un mal diseño. Si no puede recuperarse de la excepción, déjelo burbujear.
Gracias David, en resumen, ¿debo capturar y registrar excepciones en MODELO o Controlador (donde se llaman los objetos del Modelo)? –
@flybyte: Ambos. En cualquier lugar donde tenga un código que pueda generar o manejar un error, debe colocar allí el código de comprobación de errores y de manejo de errores. Los modelos generalmente tendrán más, ya que los modelos deben contener toda la lógica comercial. Los controladores pueden hacer algunas comprobaciones básicas de entrada desde la interfaz de usuario, los modelos pueden verificar su estado y manejar errores al interactuar con servicios, etc. – David
por lo que está sugiriendo que el modelo nunca debe arrojar la excepción de regreso a Controlador luego a Globa.aspx? Lo que hice fue intentar capturar en Model. Luego, Model lanza a Controller y luego a global.aspx donde se registrará cualquier excpección que haya surgido. –