2010-01-22 11 views
19

Esta es más una pregunta de programación de propósito general que un lenguaje específico. He visto varios appraoches para probar y atrapar.Prueba de captura de bloques dentro o fuera de funciones y entrega de errores

Una es hacer cualquier preprocesamiento en los datos que necesita, llamar a una función con los argumentos apropiados y envolverla en un bloque try/catch.

La otra es simplemente llamar a una función para pasar los datos y confiar en capturas de prueba dentro de la función, con la función que devuelve una bandera de verdadero/falso si se producen errores.

La tercera es una combinación con una captura de prueba fuera de la función y dentro. Sin embargo, si las funciones intentan capturar captura algo, arroja otra excepción para atrapar el bloque try catch fuera de la función.

¿Alguna idea sobre los pros/contras de estos métodos para el control de errores o si hay un estándar aceptado? Mis habilidades de ninja en Google me han fallado al encontrar datos precisos sobre esto.

Respuesta

15

En general, una excepción solo debe detectarse si realmente se puede manejar.

No tiene sentido capturar una excepción sin otro propósito que registrarla. La excepción es que las excepciones deben capturarse en el "nivel superior" para que pueda registrarse. El resto del código debe permitir que las excepciones se propaguen al código que las registrará.

+1

+1: Y, una excepción solo se puede manejar cuando una función contiene estrategias alternativas para hacer algo. –

+1

Creo que capturar una excepción para producir un registro útil, con más contexto que el lanzamiento inicial, puede ser útil a veces. Después de eso, vuelva a lanzarlo si no puede manejar la excepción. – extraneon

+1

"con más información" es la clave. Simplemente el registro, sin información adicional, debe esperar al nivel superior. –

2

Cada "módulo" en una aplicación es responsable de manejar sus propios parámetros de entrada. Normalmente, debe encontrar problemas lo antes posible y no entregar basura a otra parte de la aplicación y confiar en que sean correctos. Sin embargo, hay excepciones. A veces, la validación de un parámetro de entrada básicamente necesita volver a implementar lo que el destinatario debe hacer (por ejemplo, analizar un número entero) en la persona que llama. En este caso, generalmente es apropiado probar la operación y ver si funciona o no. Además, hay algunas operaciones que no pueden predecir su éxito sin hacerlas. Por ejemplo, no puede verificar de manera confiable si puede escribir en un archivo antes de escribir en él: otro proceso puede bloquear inmediatamente el archivo después de su verificación.

+0

Esto no parece responder a la pregunta. Parece más como una revisión de cómo pueden surgir excepciones. –

+0

@S.Lott: Entendí la pregunta como si el OP quisiera saber si debería confiar en otro módulo para manejar los errores y devolver los valores booleanos de éxito/falla o dejar que arroje excepciones y atraparlos más arriba en la pila de llamadas ... Tal vez lo malentendí . Es bastante largo, y supongo que aborda una parte, al menos. –

0

Por lo general, considero que, como persona que llama del método, puedo usar una excepción de alguna manera (como, recuperarme adoptando un enfoque diferente) o si no hace ninguna diferencia y me sale mal si ocurre la excepción. Entonces, en el primer caso, declararé el método para lanzar la excepción, mientras que en el segundo lo atraparé dentro del método y no molestaré a la persona que llama con él.

0

La única pregunta sobre la captura de excepciones es "¿hay múltiples estrategias para hacer algo?"

Algunas funciones pueden atrapar ciertas excepciones de manera significativa y probar estrategias alternativas en el caso de esas excepciones conocidas.

Se arrojarán todas las demás excepciones.

Si no hay estrategias alternativas, la excepción será simplemente arrojada.

Raramente desea que una función capte (y silencie) las excepciones. Una excepción significa que algo está mal. La aplicación, como un todo, debe tener en cuenta las excepciones no controladas. Al menos debería registrarlos, y tal vez hacer aún más: apagar o tal vez reiniciar.

4

Creo que la mejor manera de pensar en esto es en términos de estado del programa. No desea que una operación fallida dañe el estado del programa. This paper describe el concepto de "Seguridad de excepciones".

En general, primero debe decidir qué nivel de seguridad de excepción necesita una función para garantizar. Los niveles son

  • básico Guarnantee
  • fuerte garantía
  • nothrow Garantizar

la garantía básica simplemente significa que en la cara de una excepción o cualquier otro error, no hay recursos se filtró, la fuerte la garantía dice que el estado del programa se revierte a antes de la excepción, y los métodos de nothrow nunca arrojan excepciones.

Personalmente uso excepciones cuando se produce una falla imprevista en el tiempo de ejecución. Inesperado significa para mí que tal falla no debería ocurrir en el curso normal de las operaciones. Tiempo de ejecución significa que el error se debe al estado de algún componente externo fuera de mi control, en lugar de a errores lógicos de mi parte. Uso ASSERT() para detectar errores de lógica, y utilizo los valores de retorno booleanos para los errores esperados.

¿Por qué? ASSERT no está compilado en el código de publicación, por lo que no agobío a mis usuarios con la comprobación de errores de mis propios fallos. Para eso están las pruebas unitarias y ASSERTS. Booleanos porque lanzar una excepción puede dar el mensaje incorrecto. Las excepciones también pueden ser costosas. Si lanzo excepciones en el curso normal de la ejecución de la aplicación, no puedo usar la excelente excepción de "Catch on throw" del depurador de MS Visual Studio, donde puedo hacer que el depurador rompa un programa en el punto en que es. lanzado, en lugar de la opción predeterminada de solo detenerse en excepciones no controladas (bloqueadas).

Para ver una técnica de C++ para la Garantía básica, google "RAII" (Adquisición de recursos es inicialización). Es una técnica donde envuelve un recurso en un objeto cuyo constructor asigna el recurso y cuyo destructor libera el recurso. Como las excepciones de C++ desenrollan la pila, garantiza que los recursos se liberen frente a las excepciones. Puede usar esta técnica para revertir el estado del programa frente a una excepción. Simplemente agregue un método "Commit" a un objeto, y si un objeto no se compromete antes de que se destruya, ejecute la operación "Rollback" que restablece el estado del programa en el destructor.

+0

¿Qué es una garantía de NoThrow? ¿Esto es algo de C++? En Java y Python hay numerosos errores que no puedes (y no debes) intentar atrapar. –

+0

NoThrow es una garantía absolutamente necesaria para que el resto de las garantías sea posible. Los destructores y desinicializadores (como C's 'Free()') deben ser NoThrow, lo que significa que nunca lanzarán una excepción. Las funciones de RollBack() nunca deberían lanzarse también. Si no puede limpiar el estado del programa sin generar nuevas excepciones, significa que no puede garantizar que el estado del programa no se dañe. Hay tres formas de crear operaciones NoThrow. Compóngalos de operaciones de solo nothrow: lógicamente garantice que no pueden tirar, o poner un try-catch que trague las excepciones. –

+0

Dicho esto, hay tres excepciones de las que soy consciente y que simplemente no puedes evitar todo el tiempo. Son excepciones de ThreadAbort (así se llaman en los lenguajes .NET, puede haber otros equivalentes en otros idiomas), excepciones de falta de memoria y excepciones de desbordamiento de pila. Las 3 son violaciones del concepto abstracto de un programa con tiempo ilimitado, memoria y recursión de llamadas disponibles para él. No hay mucho que puedas hacer sobre ninguno de ellos. Afortunadamente, generalmente puede diseñar un programa para no ser golpeado por aquellos en la gran mayoría de los casos. –

1

No existen reglas reales y rápidas sobre el manejo de excepciones que he encontrado, sin embargo, tengo una serie de reglas generales que me gusta aplicar.

Incluso si se manejan algunas excepciones en la capa inferior de su sistema, asegúrese de que hay un controlador catch all exception en el punto de entrada de su sistema (por ejemplo, cuando implementa un Thread nuevo (es decir Runnable), Servlet, MessasgeDrivenBean, toma de servidor, etc.). Este es a menudo el mejor lugar para tomar la decisión final de cómo debe continuar su sistema (registrar y reintentar, salir con error, revertir la transacción)

Nunca arroje una excepción dentro de un bloque finally, perderá la excepción original y enmascarar el problema real con un error sin importancia.

Aparte de eso, depende de la función que esté implementando. ¿Estás en un bucle? ¿Debería volver a intentar el resto de los ítems o abortar toda la lista?

Si vuelve a generar una excepción, evite el inicio de sesión, ya que solo agregará ruido a sus registros.

Cuestiones relacionadas