Pregunta

He tratado con instancias donde tiraba/rethrow una excepción a sabiendas de que el código que lo rodea se captura la excepción específica.Pero es allí cualquier momento usted quiere lanzar una excepción, sabiendo que no iba a ser atrapado?

O al menos, NO se captura una excepción?

Excepciones detener inmediatamente la solicitud, a menos que sus manejado derecho?Así que creo que me estoy preguntando si usted quiere con el propósito de permitir su aplicación a morir?

¿Fue útil?

Solución

Si la aplicación va principalmente para ser utilizado por otros clientes y no es independiente, por lo general, tiene sentido para lanzar excepciones si una condición surge que no se sabe cómo (o no quiere) manipular, y no hay manera sensata para que pueda recuperarse de ella. Los clientes deben ser capaces de decidir cómo quieren manejar cualquier excepción que pueda lanzar.

Por otro lado, si la aplicación es el punto final, una excepción se convierte esencialmente en un mecanismo de notificación para alertar a la gente de que algo ha ido terriblemente mal. En tales casos, es necesario tener en cuenta algunas cosas:

  • ¿Qué tan importante es la continua ejecución de la aplicación? ¿Es realmente este error irrecuperable? Lanzar una excepción y que termina su programa no es algo que quieres hacer en el transbordador espacial.

  • ¿Está utilizando excepciones como un proxy para el registro real Hay casi nunca es una razón para hacer esto?; considerar un mecanismo de registro real en lugar. Detectar la excepción y tiene el registrador de averiguar qué sucedió.

  • ¿Qué estás tratando de transmitir al lanzar la excepción ti mismo? Pregúntese cuál es el valor en el lanzamiento de una nueva excepción es, y considerar cuidadosamente si no hay una forma mejor de hacer lo que quiere.

  • No detectar una excepción puede dejar los recursos en mal estado. Si no sale de gracia, las cosas en general no se limpiaron para usted. Asegúrese de que entiende lo que está haciendo si es necesario hacerlo -. Y si no vas a cogerlo, al menos consideran un bloque try-finally para que pueda hacer un poco de poner en orden

Otros consejos

Hay una muy buena regla que me encontré hace un tiempo:

una excepción cuando un método no puede hacer lo que su nombre dice que lo hace.

La idea es que una excepción indica que algo ha ido mal. Cuando se está implementando un método, que no es su responsabilidad estar al tanto de si se va a utilizar correctamente o no. Si el código usando el método de captura la excepción o no, no es su responsabilidad, pero la responsabilidad de la persona que utiliza el método.

Otra regla a seguir es:

No capturar una excepción a menos que sepa lo que quiere hacer con él.

Obviamente, debe incluir el código de limpieza en un bloque try ... finally, pero nunca se debe simplemente capturar una excepción sólo por el bien de la captura de él. Y nunca se debe tragar excepciones en silencio. Si bien hay ocasiones en las que es posible que desee capturar todas las excepciones (por ejemplo, al hacer catch (Exception ex) en C #), estos son muy poco comunes y generalmente tienen una razón técnica muy específica. Por ejemplo, cuando se utiliza hilos en .NET 2.0 o posterior, si una excepción se escapa de su hilo, que hará que todo el dominio de la aplicación para descargar. En estos casos, sin embargo, en el mínimo que debe registrar los detalles de la excepción como un error y dar una explicación en los comentarios.

En general, y sin duda en iteraciones tempranas de su aplicación, No detectar la excepción. Más a menudo que no, la recuperación de una excepción requerirá una regla de negocio de algún tipo, y, más a menudo que no, esas reglas de negocio no están definidos para ti. Si "manejar" la excepción en lugar de dejar que la aplicación morir entonces lo más probable es que sea la invención de reglas de negocio para su cliente. No es bueno.

El patrón general de la captura de toda excepción sólo por el bien de la captura de él me ha causado más dolores de cabeza que puedo contar. Suele ocurrir que alguien pone una especie de código de control de excepciones genéricas en toda la aplicación, que es inevitable que se esconde un fallo, o la creación de un comportamiento no deseado. (Dicho sea de paso, la captura y luego no Regeneración de que es aún peor.)

Por lo tanto, me gustaría sugerir que le pida a su lugar: "? ¿Cuándo debo capturar una excepción"

Claro. Por ejemplo, si usted está tratando de cargar algunos bytes en una cadena en Java:

try {
  String myString = new String(byteArray, "UTF-8");
} catch (UnsupportedEncodingException e) {
  // Platform doesn't support UTF-8?  What is this, 1991?
  throw new RuntimeExceptione(e);
}

En este caso, no hay degradación elegante, la plataforma, simplemente no puede apoyar la operación deseada. Puede comprobar si esta condición en la inicialización todo lo que quiera, pero el constructor de cadena todavía lanza esta excepción, y usted tiene que tratar con él. O eso, o utilizar Charset.forName ():)

Aquí está la cosa ... se trata de "capas" o "encapsulado", o "bajo acoplamiento". En algún lugar en su base de código, que está escribiendo un método para hacer algo. Digamos que es un método público. Por lo tanto, no debería suponer mucho o nada acerca de la persona que llama ... sino que debe limitarse a hacer el trabajo que se supone que debe hacer, independientemente de quién está llamando y qué contexto la persona que llama está en.

Y si, por alguna razón, no puede completar su trabajo, entonces tiene que decirle a la persona que llama "Lo siento, yo no podía hacer eso, y aquí está el porqué". Las excepciones son un excelente mecanismo para dejar que se dice que la persona que llama (no es el único mecanismo, pero el mejor mecanismo que he visto en la mayoría de los casos).

Por lo tanto, cuando se lanza la excepción, no tiene idea de si va a ser atrapado o no ... porque estás exponiendo un método público y no tiene idea de quién podría optar por llamar y por qué.

La captura de la excepción es el trabajo del "contexto". Por ejemplo, digamos que usted está escribiendo una biblioteca con métodos públicos que pudieran arrojar excepciones. Entonces, digamos que está utilizando la biblioteca de una aplicación de Windows Forms. La aplicación de Windows Forms puede capturar las excepciones y mostrar un cuadro de mensaje al usuario.

Pero más tarde, es posible utilizar la misma biblioteca de un servicio de Windows. El servicio sería más probable que detectar la excepción, registrarla, devolver un error a la llamada original, pero sigue corriendo por lo que puede procesar más solicitudes.

Así que la excepción es como un acuerdo contractual entre la persona que llama y el proveedor. El proveedor dice: "Voy a hacer bien el trabajo o decirle por qué no puedo. Lo que se hace a partir de ahí es su propio negocio." Y la persona que llama dice: "Está bien, si no se puede hacer el trabajo, sólo dime por qué, y voy a decidir qué hacer en ese caso."

  

Pero es allí en cualquier momento que se desea lanzar una excepción, sabiendo que no sería atrapado?

Yo diría que si estás tirando manualmente una excepción, la mayoría de las veces no saben si será capturado. Si se sabía que sería capturado sólo podía manejar por sí mismo en lugar de tirar la excepción en el primer lugar.

Para ser justos, supongo que eso depende en parte del tipo de programación que está haciendo, y en ocasiones el mismo programador termina la construcción de la biblioteca y el código que consume dicha biblioteca.

  

¿Alguna vez NO capturar una excepción?

Si usted no esperaba / no eran conscientes de una excepción, pueden salir proyectados. Pero dejando eso de lado y asumiendo que son conscientes de la excepción, a veces se sabe sobre él en un nivel pero conoce el siguiente nivel hacia arriba es el lugar más apropiado para manejar la situación.

Depende del tipo de aplicación. Las aplicaciones web pueden continuar funcionando incluso después de excepciones han burbujear hasta el contexto de ejecución.

Es una práctica común a 'tiro / volver a lanzar' una excepción si se captura la excepción a un nivel donde no pueda ser tratado. Sin embargo, casi siempre se debería añadir contexto de la cuestión, por lo menos, añadir un poco de registro en el nivel más alto que decir que ha sido capturado y relanza.

por ejemplo

A llama a B llama C (lanza excepción)

capturas B / relanzamientos

A capturas.

En este caso, usted quiere B a añadir un poco de registro para que pueda diferenciar entre generadora B y lanzando un error, y la generación de C y lanzando un error. Eso le permitirá una mayor capacidad para depurar y solucionar problemas más adelante.

En general es casi nunca quiere una excepción a matar a su programa. Lo más recomendable es coger la excepción y salir con gracia. Esto le permite guardar cualquier información que actualmente se abren y liberan los recursos que se están utilizando para que no se corrompan. Si tiene intención de salir, puede crear su propio informe de la información 'núcleo-dump' que incluye las cosas que estaba haciendo cuando usted cogió la excepción grave.

Si deja que la excepción matar a su proceso está eliminando su oportunidad de obtener información de bloqueo de aduana adaptados, y también se está saltando la parte donde se proporciona al usuario con un mensaje de error descriptivo y luego salir.

Por lo tanto, siempre recomendamos la captura de excepciones, y nunca voluntariamente dejarlos fuera de control en su programa.

Editar

Si usted está escribiendo una biblioteca, usted tiene que elegir de antemano si su función será una excepción, o sea salvo una excepción. En estos casos, a veces va a lanzar una excepción y no tienen idea de si la persona que llama lo cogerá. Pero en ese caso, la captura no es su responsabilidad, siempre y cuando el api declara que la función podría lanzar excepciones. (Estoy buscando una palabra que significa 'podría posiblemente excepción tiro' ... Alguien sabe lo que es? Se va a fastidiarme todo el día.)

En primer lugar, hay absolutamente son situaciones en las que es mejor no coger una excepción.

A veces, una excepción a veces puede decirle que su programa está en un estado desconocido.Hay una serie de excepciones en las que esto es bastante intrínsecamente cierto teniendo en cuenta el tipo de excepción.Un NullReferenceException esencialmente dice que "no es un error".Y por la captura de una excepción, puede ocultar el error, que suena bien en el corto plazo, pero a largo plazo te gustaría más para solucionarlo.El producto no puede bloquearse, pero que sin duda no tienen el comportamiento esperado.

Pero esto también es válido para los tipos de excepción que inventamos para nosotros mismos.A veces, el hecho de que la excepción ha sido lanzado debe ser "imposible" - y, sin embargo, ha sucedido, por lo que hay un error.

También, algo muy importante sucede cuando se captura una excepción:el finally bloques para toda la pila de llamadas dentro del bloque try (y cualquier cosa que se llama) será ejecutado.¿Qué hacen los bloques finally hacer?Bueno, cualquier cosa.Y si el programa está en un estado desconocido, yo realmente significan nada.Se podría borrar valiosos datos de los clientes desde el disco.Podían lanzar más excepciones.Se podría corromper los datos en la memoria, haciendo que el error imposible de diagnosticar.

Así que, cuando una excepción indica un estado desconocido, usted no desea ejecutar más de código, hagas lo que hagas, no se captura la excepción.Deja volar pasado, y el programa va a terminar sin problemas, y el informe de Errores de Windows será capaz de capturar el estado del programa como lo fue cuando el problema fue detectado originalmente.Si la captura de la excepción, usted hará más código a ejecutar, que se atornille el estado del programa aún más.

En segundo lugar, debe lanzar una excepción a sabiendas de no ser atrapado?Creo que esa pregunta no entiende la naturaleza de la reutilizables métodos.La idea de un método es que tiene un "contrato" que es de la siguiente manera:se acepta ciertos parámetros y devuelve un valor determinado, además de que también arroja algunas excepciones en determinadas condiciones.Ese es el contrato a la persona que llama lo que hacen con ella.Para algunas personas que llaman, Una excepción podría indicar un recuperable condición.Para otras personas, podría indicar un error.Y de lo que he dicho anteriormente, es claro que si una excepción indica un error, no debe ser capturado.

Y si te estás preguntando qué significa esto para los Microsoft Enterprise Library Excepción del Bloque de control de:sí, es bastante roto.Dicen que catch (Exception x) y, a continuación, decidir si para volver a iniciar basado en su política;demasiado tarde - la finally los bloques ya han ejecutado por ese punto.No hagas eso.

Usted probablemente no desea una excepción no capturada en cualquier lugar donde los usuarios finales pueden verlo, pero a menudo es aceptable para permitir que los clientes de su API (otros programadores) decidir cómo manejar excepciones.

Por ejemplo, supongamos que se está diseñando una biblioteca de clases de Java. Se expone un método público que se lleva en una cadena. En su solicitud, un valor de entrada nula causaría un error. En vez de manejar el error mismo, sería aceptable para comprobar si hay un valor nulo, luego tirar una IllegalArgumentException.

Usted debe, por supuesto, documento que el método lanza esta excepción en esta circunstancia. Este comportamiento se convierte en parte del contrato de su método.

Depende de lo que entendemos por 'ser atrapado'. Algo, en algún lugar finalmente captura la excepción ya sea el sistema operativo subyacente o algo más.

Tenemos un sistema de flujo de trabajo que ejecuta los planes de trabajo integrados por los trabajos individuales. Cada tarea se ejecuta una unidad de código. Para algunas de las excepciones, que no queremos para manejarlos en el código, pero tirarlo arriba en la pila de modo que el sistema de flujo de trabajo externo atrapa (que pasa completamente fuera del proceso del lanzador).

Si va a escribir toda la aplicación, a continuación, sus razones son el suyo propio. Puedo pensar en algunas situaciones en las que podría quiere tirar la excepción y dejar que la aplicación mueren, la mayoría de ellos no son muy buenas razones sin embargo.

La mejor razón es por lo general cuando la depuración. Con frecuencia desactivo excepciones durante la depuración para permitir que sepa mejor que algo está fallando. También se puede simplemente activar la excepción que se rompe en el depurador si se está ejecutando en una máquina con el depurador.

Otra posible razón es al continuar después se produce una excepción que no tiene sentido o daría lugar a una posible corrupción de datos irrecuperable o peor (piensa robots con rayos láser, pero entonces debe estar absolutamente seguro de sus ofertas applicaiton con estas situaciones de la OMI , chocando el programa es sólo la manera perezosa).

Si estás escribiendo código de la API, o el código de Marco que no usará a ti mismo, entonces usted no tiene idea de si alguien va a coger sus excepciones.

Sí, es mi única oportunidad para golpear el desarrollador consumo del servicio / objeto de decirles "Ur dO1n mal !!!!".

Eso y deshacerse de posibilidades de que usted no desea permitir o son aparentemente "imposible". Aplicaciones que capturan todas las excepciones y que siguen son sólo un jardín rodeado de caos.

Si necesito un moderadamente grande sistema que de alguna manera está procesando datos en lo que yo creo que es una manera consistente.

y

En algún lugar a lo largo de la línea, detecto que el estado de la aplicación se ha convertido en inconsistente.

y

El sistema no (todavía) no saben cómo solucionar la inconsistencia y recupera correctamente

Entonces, sí, me gustaría lanzar una excepción con tanto detalle como sea posible y hacer que la aplicación a morir tan pronto como sea posible, para evitar hacer cualquier daño adicional a los datos. Si se puede recuperar, sería importante no agravar el problema al tratar débilmente para cubrir el desorden.

Más tarde, a lo largo de la línea, una vez que la cadena de acontecimientos que condujo a la inconsistencia se entiende mejor, lo más alto de recursos puede coger esa excepción, reparar el estado, y continuar con una interrupción mínima.

Una biblioteca a menudo lanzar excepciones basadas en las pruebas de programación defensivas, debe surgir una condición que no debería haber permitido que surjan por el código de la aplicación. código de aplicaciones a menudo se puede escribir de tal manera que la mayoría de esas condiciones no válidas no se levantarán, y nunca será arrojada por tanto, las excepciones, por lo que no hay razón para la captura de ellos.

En función de la lengua (estoy pensando sobre todo en términos de C ++ en lugar de C #, y no es tan claro cuáles son las diferencias) el efecto de una excepción no capturada en realidad ser lanzado es probablemente el mismo que lo que se hacía en el se inventaron días antes de excepciones. Una política común para la programación defensiva en bibliotecas de C, por ejemplo, era para terminar el programa inmediatamente con un mensaje de error.

La diferencia es que si el tiro excepción hace llegar a ser posible (esperemos que esto se descubre a través de la unidad de pruebas), a menudo es relativamente fácil de añadir un manejador de excepciones que pueden recuperarse del problema de una manera más constructiva. Usted no tiene que volver a escribir la biblioteca, o añadir controles complejos en código de la aplicación para asegurarse de que la condición no puede surgir antes de que se hizo la llamada excepción de lanzar.

Tengo un buen número lanza una excepción que nunca son atrapados. Todos ellos son con fines defensivos, y al mismo tiempo ser no detectada es malo para una excepción que hace pasar, esto sólo sucede cada vez durante el desarrollo y las pruebas, las condiciones de error que no tuvo en cuenta en el código de la aplicación hasta el momento. Y cuando esto sucede, no es habitual que el arreglo sea incómoda - no hay necesidad de una refactorización a gran escala, sin necesidad de que el código de las aplicaciones a ser masivamente complicado, con la condición de error cheques, sólo una cláusula catch con una recuperación relativamente simple o " lo siento, Dave, me temo que no puedo hacer eso ". sin faltar a cabo toda la aplicación.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top