utilizar usuario una try tipos sharp que programacion por para más manejar excepción excepciones específicos errores ejemplos definidas comunes como catch c# java exception error-handling

usuario - Mejores prácticas para la gestión de excepciones en Java o C#



try catch c# (15)

Algunas respuestas excelentes aquí. Me gustaría agregar, que si terminas con algo como lo publicado, al menos imprime más que el seguimiento de la pila. Di lo que estabas haciendo en ese momento, y Ex.getMessage (), para darle al desarrollador una oportunidad de luchar.

Estoy atascado decidiendo cómo manejar excepciones en mi aplicación.

Mucho si mis problemas con las excepciones provienen de 1) acceder a los datos a través de un servicio remoto o 2) deserializar un objeto JSON. Lamentablemente, no puedo garantizar el éxito de ninguna de estas tareas (corte la conexión de red, objeto JSON malformado que está fuera de mi control).

Como resultado, si encuentro una excepción simplemente la atrapo dentro de la función y devuelvo FALSO a la persona que llama. Mi lógica es que lo único que le importa a la persona que llama es si la tarea fue exitosa, no por qué no fue exitosa.

Aquí hay un código de muestra (en JAVA) de un método típico)

public boolean doSomething(Object p_somthingToDoOn) { boolean result = false; try{ // if dirty object then clean doactualStuffOnObject(p_jsonObject); //assume success (no exception thrown) result = true; } catch(Exception Ex) { //don''t care about exceptions Ex.printStackTrace(); } return result; }

Creo que este enfoque está bien, pero tengo mucha curiosidad por saber cuáles son las mejores prácticas para gestionar excepciones (¿debería realmente hacer una excepción en una pila de llamadas?).

En resumen de preguntas clave:

  1. ¿Está bien simplemente capturar excepciones pero no hacerlas saltar o notificar formalmente al sistema (ya sea a través de un registro o una notificación al usuario)?
  2. ¿Qué mejores prácticas existen para excepciones que no resultan en que todo requiera un bloque try / catch?

Seguimiento / Edición

Gracias por todos los comentarios, encontré algunas fuentes excelentes sobre gestión de excepciones en línea:

Parece que la gestión de excepciones es una de esas cosas que varían según el contexto. Pero lo más importante, uno debe ser coherente en la forma en que manejan las excepciones dentro de un sistema.

Además, tenga cuidado con el colapso del código a través de intentos / capturas excesivas o sin respetar su respeto (una excepción es advertir al sistema, ¿qué más debe ser advertido?).

Además, este es un bonito comentario de elección de m3rLinEz .

Tiendo a estar de acuerdo con Anders Hejlsberg y usted en que a la mayoría de los que llaman solo les importa si la operación es exitosa o no.

De este comentario surge algunas preguntas para pensar cuando se trata de excepciones:

  • ¿Cuál es el objetivo de esta excepción?
  • ¿Cómo tiene sentido manejarlo?
  • ¿A la persona que llama realmente le importa la excepción o simplemente le importa si la llamada fue exitosa?
  • Está obligando a una persona que llama a gestionar una posible excepción elegante?
  • ¿Estás siendo respetuoso con los idoms del lenguaje?
    • ¿Realmente necesita devolver una bandera de éxito como boolean? La devolución de boolean (o una int) tiene más una mentalidad C que una Java (en Java, simplemente manejarías la excepción).
    • Siga las construcciones de gestión de errores asociadas con el lenguaje :)!

Después de pensar un poco y mirar tu código, me parece que simplemente estás volviendo a lanzar la excepción como un booleano. Podrías dejar que el método pase esta excepción (ni siquiera tienes que atraparlo) y lidiar con eso en la persona que llama, ya que ese es el lugar donde importa. Si la excepción hará que la persona que llama vuelva a intentar esta función, la persona que llama debería ser la que capte la excepción.

A veces puede ocurrir que la excepción que encuentre no tenga sentido para la persona que llama (es decir, es una excepción de red), en cuyo caso debe envolverla en una excepción específica del dominio.

Si, por otro lado, la excepción indica un error irrecuperable en su programa (es decir, el resultado final de esta excepción será la terminación del programa), personalmente me gusta hacer que esto sea explícito al capturarlo y lanzar una excepción de tiempo de ejecución.


Esto depende de la aplicación y la situación. Si está creando un componente de biblioteca, debe crear excepciones, aunque deben estar envueltos para que sean contextuales con su componente. Por ejemplo, si está creando una Base de datos Xml y digamos que está utilizando el sistema de archivos para almacenar sus datos, y está usando los permisos del sistema de archivos para proteger los datos. No querrá crear una excepción FileIOAccessDenied ya que eso filtra su implementación. En cambio, envolvería la excepción y arrojaría un error AccessDenied. Esto es especialmente cierto si distribuye el componente a terceros.

En cuanto a si está bien tragar excepciones. Eso depende de tu sistema. Si su aplicación puede manejar los casos de falla y no hay beneficio de notificar al usuario por qué falló, entonces continúe, aunque le recomiendo encarecidamente que registre el error. Siempre me pareció frustrante que me llamaran para ayudar a solucionar un problema y descubrí que se estaban tragando la excepción (o reemplazándola y lanzando una nueva sin establecer la excepción interna).

En general, uso las siguientes reglas:

  1. En mis componentes y bibliotecas solo capto una excepción si pretendo manejarlo o hacer algo basado en él. O si deseo proporcionar información contextual adicional en una excepción.
  2. Utilizo una captura de prueba general en el punto de entrada de la aplicación, o el nivel más alto posible. Si llega una excepción, solo la registro y dejo que falle. Lo ideal es que las excepciones nunca lleguen aquí.

Encuentro que el siguiente código es un olor:

try { //do something } catch(Exception) { throw; }

Código como este no tiene sentido y no debe incluirse.


Las excepciones controladas son un tema controvertido en general, y en Java en particular (más adelante trataré de encontrar algunos ejemplos para aquellos a favor y en contra de ellos).

Como reglas generales, el manejo de excepciones debe ser algo alrededor de estas pautas, sin ningún orden en particular:

  • Por motivos de mantenimiento, siempre registre excepciones para que cuando comience a ver errores, el registro lo ayude a indicarle el lugar donde probablemente comenzó su error. Nunca dejes printStackTrace() o cosas por el estilo, es probable que uno de tus usuarios obtenga uno de esos rastreos de pila con el tiempo y no tenga exactamente ningún conocimiento sobre qué hacer con él.
  • Las excepciones de captura que puedes manejar, y solo esas, y manejarlas , no solo las arrojan a la pila.
  • Siempre atrapa una clase de excepción específica, y generalmente nunca debes atrapar Exception tipo, es muy probable que tragues excepciones que de otro modo serían importantes.
  • Nunca (nunca) atrape el Error s !! , es decir: Nunca atrape los Throwable s ya que los Error s son subclases de estos últimos. Error son problemas que probablemente nunca puedas manejar (por ejemplo, OutOfMemory u otros problemas de JVM)

Con respecto a su caso específico, asegúrese de que cualquier cliente que llame a su método reciba el valor de retorno adecuado. Si algo falla, un método boolean-return podría devolver false, pero asegúrese de que los lugares que llama ese método puedan manejar eso.


Las excepciones son errores que no forman parte de la ejecución normal del programa. Dependiendo de lo que haga su programa y sus usos (es decir, un procesador de textos frente a un monitor cardíaco), tendrá que hacer cosas diferentes cuando se encuentre con una excepción. He trabajado con código que usa excepciones como parte de la ejecución normal y definitivamente es un olor a código.

Ex.

try { sendMessage(); if(message == success) { doStuff(); } else if(message == failed) { throw; } } catch(Exception) { logAndRecover(); }

Este código me hace barf. OMI no debe recuperarse de las excepciones a menos que sea un programa crítico. Si lanzas excepciones, entonces cosas malas están sucediendo.


Me gustaría recomendar otra buena fuente sobre el tema. Es una entrevista con los inventores de C # y Java, Anders Hejlsberg y James Gosling, respectivamente, sobre el tema de la Excepción Controlada de Java.

Fracaso y Excepciones

También hay excelentes recursos en la parte inferior de la página.

Tiendo a estar de acuerdo con Anders Hejlsberg y usted en que a la mayoría de los que llaman solo les importa si la operación es exitosa o no.

Bill Venners : mencionó las preocupaciones de escalabilidad y control de versiones con respecto a las excepciones marcadas. ¿Podría aclarar qué quiere decir con esos dos problemas?

Anders Hejlsberg : Comencemos con el control de versiones, porque los problemas son bastante fáciles de ver allí. Digamos que creo un método foo que declara que arroja las excepciones A, B y C. En la versión dos de foo, quiero agregar un montón de características, y ahora foo podría lanzar la excepción D. Es un cambio radical para mí agregue D a la cláusula throws de ese método, porque la persona que llama de ese método seguramente no manejará esa excepción.

Agregar una nueva excepción a una cláusula throws en una nueva versión rompe el código del cliente. Es como agregar un método a una interfaz. Después de publicar una interfaz, es inmutable para todos los propósitos prácticos, ya que cualquier implementación de la misma podría tener los métodos que desea agregar en la próxima versión. Entonces, debes crear una nueva interfaz. De manera similar con excepciones, tendría que crear un método completamente nuevo llamado foo2 que arroje más excepciones, o tendría que atrapar la excepción D en el nuevo foo, y transformar el D en un A, B o C.

Bill Venners : ¿Pero no estás rompiendo su código en ese caso de todos modos, incluso en un idioma sin excepciones marcadas? Si la nueva versión de foo lanzará una nueva excepción que los clientes deberían considerar, ¿no se ha roto su código simplemente por el hecho de que no esperaban esa excepción cuando escribieron el código?

Anders Hejlsberg : No, porque en muchos casos, a las personas no les importa. No van a manejar ninguna de estas excepciones. Hay un manejador de excepciones de nivel inferior alrededor de su ciclo de mensajes. Ese controlador solo mostrará un diálogo que diga qué salió mal y continuará. Los programadores protegen su código escribiendo "try finally" en todas partes, por lo que retrocederán correctamente si ocurre una excepción, pero en realidad no están interesados ​​en manejar las excepciones.

La cláusula throws, al menos la forma en que se implementa en Java, no necesariamente lo obliga a manejar las excepciones, pero si no las maneja, lo obliga a reconocer con precisión qué excepciones podrían pasar. Requiere que captures las excepciones declaradas o las pongas en tu propia cláusula throws. Para evitar este requisito, la gente hace cosas ridículas. Por ejemplo, decoran todos los métodos con "throws Exception". Eso solo derrota por completo la función, y acabas de hacer que el programador escriba más gilipollas. Eso no ayuda a nadie.

EDITAR: Se agregaron más detalles sobre la convergencia


Me parece extraño que quiera detectar excepciones y convertirlas en códigos de error. ¿Por qué crees que la persona que llama preferiría códigos de error sobre excepciones cuando este último es el predeterminado tanto en Java como en C #?

En cuanto a tus preguntas:

  1. Solo debe capturar las excepciones que realmente puede manejar. Simplemente capturar excepciones no es lo correcto en la mayoría de los casos. Hay algunas excepciones (por ejemplo, registro y clasificación de excepciones entre subprocesos), pero incluso para esos casos, generalmente debe volver a lanzar las excepciones.
  2. Definitivamente no deberías tener muchas declaraciones try / catch en tu código. Una vez más, la idea es capturar solo las excepciones que pueda manejar. Puede incluir un controlador de excepción superior para convertir cualquier excepción no controlada en algo útil para el usuario final, pero, de lo contrario, no debería tratar de detectar todas y cada una de las excepciones en todos los lugares posibles.

Mi estrategia

Si la función original volvió vacía , la cambio para devolver bool . Si se produjo una excepción / error, devuelva false , si todo estaba bien, devuelva true .

Si la función debe devolver algo, cuando se produzca una excepción / error, devuelva nulo ; de lo contrario, el artículo retornable.

En lugar de bool, se podría devolver una cadena que contenga la descripción del error.

En todos los casos, antes de devolver algo, registre el error.


Puede que llegue un poco tarde con la respuesta, pero el manejo de errores es algo que siempre podemos cambiar y evolucionar a lo largo del tiempo. Si quieres leer algo más sobre este tema, escribí una publicación en mi nuevo blog al respecto. http://taoofdevelopment.wordpress.com

Feliz codificación.


Si va a atrapar una excepción y devuelve falso, debería ser una excepción muy específica. No estás haciendo eso, los estás atrapando a todos y devolviendo falsa. Si obtengo una MyCarIsOnFireException, ¡quiero saberlo de inmediato! El resto de las Excepciones podría no importarme. Por lo tanto, debe tener una pila de manejadores de excepciones que digan "whoa whoa algo está mal aquí" para algunas excepciones (volver a lanzar, o atrapar y volver a lanzar una nueva excepción que explique mejor lo sucedido) y simplemente devolver falso para otros.

Si este es un producto que va a lanzar, debe registrar esas excepciones en algún lugar, lo ayudará a ajustar las cosas en el futuro.

Editar: En cuanto a la cuestión de envolver todo en un try / catch, creo que la respuesta es sí. Las excepciones deben ser tan raras en su código que el código en el bloque catch se ejecuta tan raramente que no afecta el rendimiento en absoluto. Una excepción debería ser un estado en el que su máquina de estado se rompió y no sabe qué hacer. Al menos vuelva a lanzar una excepción que explique lo que estaba sucediendo en ese momento y tenga la excepción atrapada dentro de ella. "La excepción en el método doSomeStuff ()" no es muy útil para cualquiera que tenga que descubrir por qué se rompió mientras está de vacaciones (o en un nuevo trabajo).


Si vas a utilizar el patrón de código en tu ejemplo, llámalo TryDoSomething y capta solo excepciones específicas.

También considere usar un Filtro de excepciones al registrar excepciones con fines de diagnóstico. VB tiene soporte de idioma para los filtros de excepción. El enlace al blog de Greggm tiene una implementación que se puede usar desde C #. Los filtros de excepción tienen mejores propiedades para la depuración que para la captura y el nuevo lanzamiento. Específicamente, puede registrar el problema en el filtro y dejar que la excepción continúe propagándose. Ese método permite adjuntar un depurador JIT (Just in Time) para tener la pila original completa. Un nuevo lanzamiento corta la pila en el punto en que fue derribada.

Los casos en los que TryXXXX tiene sentido son cuando está envolviendo una función de un tercero que arroja casos que no son realmente excepcionales o que son difíciles de probar sin llamar a la función. Un ejemplo sería algo así como:

// throws NumberNotHexidecimalException int ParseHexidecimal(string numberToParse); bool TryParseHexidecimal(string numberToParse, out int parsedInt) { try { parsedInt = ParseHexidecimal(numberToParse); return true; } catch(NumberNotHexidecimalException ex) { parsedInt = 0; return false; } catch(Exception ex) { // Implement the error policy for unexpected exceptions: // log a callstack, assert if a debugger is attached etc. LogRetailAssert(ex); // rethrow the exception // The downside is that a JIT debugger will have the next // line as the place that threw the exception, rather than // the original location further down the stack. throw; // A better practice is to use an exception filter here. // see the link to Exception Filter Inject above // http://code.msdn.microsoft.com/ExceptionFilterInjct } }

Si usas un patrón como TryXXX o no, es más una cuestión de estilo. La cuestión de atrapar todas las excepciones y tragarlas no es un problema de estilo. ¡Asegúrate de que las excepciones inesperadas se propaguen!


Solo deberías atrapar las excepciones con las que puedes lidiar. Por ejemplo, si está tratando de leer en una red y la conexión se agota y obtiene una excepción, puede volver a intentarlo. Sin embargo, si está leyendo a través de una red y obtiene una excepción IndexOutOfBounds, realmente no puede manejar eso porque no (bueno, en este caso no lo sabrá) sabe qué lo causó. Si va a devolver falso o -1 o nulo, asegúrese de que sea para excepciones específicas. No quiero que una biblioteca que estoy usando devuelva un mensaje falso en una lectura de red cuando la excepción arrojada es que el montón está sin memoria.


Sugiero tomar sus pistas de la biblioteca estándar para el idioma que está utilizando. No puedo hablar por C #, pero echemos un vistazo a Java.

Por ejemplo, java.lang.reflect.Array tiene un método de set estático:

static void set(Object array, int index, Object value);

La forma C sería

static int set(Object array, int index, Object value);

... con el valor de retorno siendo un indicador de éxito. Pero ya no estás en el mundo C.

Una vez que acepte las excepciones, descubrirá que hace que su código sea más simple y claro, alejando su código de manejo de errores de su lógica central. Intenta tener muchas declaraciones en un solo bloque de try .

Como otros han señalado, debe ser lo más específico posible en el tipo de excepción que capte.


Todo lo anterior parece razonable y, a menudo, su lugar de trabajo puede tener una política. En nuestro lugar, hemos definido los tipos de Excepción: SystemException (desmarcada) y ApplicationException (marcada).

Hemos acordado que es poco probable que SystemException sea ​​recuperable y se manejará una vez en la parte superior. Para proporcionar un contexto adicional, nuestras SystemException están diseñadas para indicar dónde ocurrieron, por ejemplo, RepositoryException , ServiceEception , etc.

ApplicationException puede tener un significado comercial como InsufficientFundsException y debe ser manejado por el código del cliente.

Witoh es un ejemplo concreto, es difícil comentar sobre su implementación, pero nunca usaría códigos de retorno, son un problema de mantenimiento. Puede tragarse una excepción, pero debe decidir por qué y siempre registrar el evento y stacktrace. Por último, como su método no tiene otro procesamiento, es bastante redundante (a excepción de la encapsulación?), doactualStuffOnObject(p_jsonObject); podría devolver un booleano!


try / catch blocks forma un segundo conjunto de lógica incrustado sobre el primer conjunto (principal), por lo que son una excelente manera de obtener código de espagueti difícil de depurar e ilegible.

Aún así, se usan de forma razonable y hacen maravillas con la legibilidad, pero solo debes seguir dos reglas simples:

  • úselos (con moderación) en el nivel bajo para detectar problemas de manejo de la biblioteca y transmitirlos nuevamente al flujo lógico principal. La mayor parte del manejo de errores que deseamos debe provenir del código en sí, como parte de los datos en sí. ¿Por qué hacer condiciones especiales, si la devolución de datos no es especial?

  • utilice un controlador grande en el nivel superior para administrar cualquiera o todas las condiciones extrañas que surgen en el código y que no están atrapadas en un nivel bajo. Haga algo útil con los errores (registros, reinicios, recuperaciones, etc.).

Aparte de estos dos tipos de manejo de errores, todo el resto del código en el medio debe estar libre y libre de códigos de prueba / captura y objetos de error. De esta forma, funciona de manera sencilla y como se espera, sin importar dónde lo use o qué haga con él.

Pablo.