277 votos

El caso en contra de las excepciones comprobadas

Para un número de años, ahora he sido incapaz de recibir una buena respuesta a la siguiente pregunta: ¿por qué algunos desarrolladores tan en contra de excepciones comprobadas? He tenido numerosas conversaciones, leer cosas sobre los blogs, leer lo que Bruce Eckel tenía que decir (la primer persona que me vio hablar en contra de ellos).

Actualmente estoy escribiendo algo de código y el pago de una atención muy cuidadosa a cómo trato con excepciones. Estoy tratando de ver el punto de vista de la "no nos gusta excepciones comprobadas" multitud y yo todavía no la veo.

Todas las conversaciones que tengo termina con la misma pregunta respuesta... me deja ponerlo:

En general (de cómo Java fue diseñado),

  • El Error es de las cosas que nunca deben ser capturados (VM tiene una alergia al maní y a alguien dejó caer un frasco de cacahuetes)
  • RuntimeException es para las cosas que el programador que hizo mal (programador se marchó al final de la matriz)
  • Excepción (excepción RuntimeException) es para las cosas que están fuera de la del programador de control (disco se llena, mientras que la escritura al sistema de archivos, el archivo de límite de control para que el proceso ha sido alcanzado y no se pueden abrir los archivos más)
  • Arrojar simplemente es el padre de todos los tipos de excepción.

Un argumento común que escucho es que si una excepción ocurre, entonces todo el desarrollador va a hacer es salir del programa.

Otro argumento común que he oído es que se comprueba excepciones hacer más difícil para refactorizar el código.

Para el "todo lo que voy a hacer es salir del" argumento puedo decir que incluso si usted está saliendo necesita mostrar un razonable mensaje de error. Si se acaba de batea en el manejo de los errores de los usuarios no será demasiado feliz cuando se sale del programa sin una indicación clara de por qué.

Para el "hace que sea más difícil para refactorizar" la multitud, lo que indica que el nivel adecuado de abstracción no fue elegido. En lugar de declarar un método lanza una IOException, el IOException debe ser transformado en una excepción que es más adecuado para lo que está pasando.

No tengo un problema con envoltura Principal con catch(Exception) (o en algunos casos de captura(Arrojar) para asegurar que el programa puede salir con gracia -, pero siempre me captura las excepciones específicas que necesito. Haciendo que me permita, al menos, mostrar un mensaje de error apropiado.

La pregunta que la gente nunca respondas a esto:

Si usted lanza RuntimeException subclases lugar de Excepción subclases entonces, ¿cómo sabes lo que se supone que para coger?

Si la respuesta es la captura de la Excepción, a continuación, que también están lidiando con programador de errores de la misma manera como el sistema de excepciones. Que parece mal a mí.

Si la captura de Arrojadiza, a continuación, usted está tratando sistema de excepciones y VM errores (y similares) de la misma manera. Que parece mal a mí.

Si la respuesta es que la captura de sólo las excepciones que se sabe que son lanzadas entonces, ¿cómo saber cuáles son lanzados? ¿Qué sucede cuando programador X lanza una nueva excepción y se olvidó de coger? Eso me parece muy peligroso para mí.

Yo diría que un programa que muestra una traza de la pila está mal. ¿Las personas que no les gusta excepciones comprobadas no se sienten de esa manera?

Así que, si no te gusta excepciones comprobadas puede usted explicar por qué no, Y responder a la pregunta que no sean respondidas por favor?

Edit: yo no estoy en busca de consejos sobre cuándo utilizar uno u otro modelo, lo que estoy buscando es ¿por qué la gente se extienden desde RuntimeException porque no les gusta que se extiende desde la Excepción, y/o por qué se captura una excepción y, a continuación, rethrow RuntimeException en lugar de añadir lanza a su método. Quiero entender la motivación para tener aversión excepciones comprobadas.

127voto

bobince Puntos 270740

La cosa acerca de la comprobada es que las excepciones no son realmente excepciones por la costumbre de entender el concepto. En cambio, ellos son de la API alternativa de valores.

La idea de las excepciones es que un error tirado en algún lugar camino hacia abajo de la cadena de llamadas puede burbuja y ser manejados por el código en algún lugar más arriba, sin la intervención de código tenga que preocuparse por ello. Excepciones comprobadas, por otro lado, se requiere cada nivel de código entre el lanzador y el receptor para declarar que saben sobre todas las formas de excepción que puede ir a través de ellos. Esto es realmente poco diferente, en la práctica, si se revisan las excepciones eran simplemente especial de devolución de los valores que la llamada tenía que comprobar. por ejemplo.[pseudocódigo]:

public [int or IOException] writeToStream(OutputStream stream) {
    [void or IOException] a= stream.write(mybytes);
    if (a instanceof IOException)
        return a;
    return mybytes.length;
}

Ya que Java no puede hacer alternativos valores de retorno, o simple inline tuplas como valores de retorno, excepciones comprobadas son una respuesta razonable.

El problema es que un montón de código, incluyendo grandes extensiones de la biblioteca estándar, mal uso excepciones comprobadas por real excepcionales condiciones que usted puede muy bien desear la captura de varios niveles. ¿Por qué es IOException no RuntimeException? En cualquier otro idioma, yo puedo dejar una excepción de e / s a suceder, y si yo no hago nada para manejar, mi solicitud va a parar y voy a conseguir un práctico sistema de seguimiento de la pila para mirar. Esta es la mejor cosa que puede suceder.

Tal vez dos métodos desde el ejemplo quieres coger todos los IOExceptions de toda la escritura-a-flujo de proceso, de anular el proceso y el salto en el informe de errores de código; en Java no se puede hacer eso sin añadir 'throws IOException " en cada llamada, incluso a niveles que no IO. Estos métodos no se necesita saber acerca de el manejo de excepciones; tener que agregar excepciones a sus firmas:

  1. aumenta innecesariamente el acoplamiento;
  2. hace que la interfaz de firmas muy frágiles a los cambios;
  3. hace que el código sea más legible;
  4. es tan molesto que el común programador de reacción es derrotar al sistema haciendo algo horrible como 'tira de Excepción', 'catch (Exception e) {}', o envolver todo en un RuntimeException (lo que hace más difícil la depuración).

Y entonces hay un montón de ridículo biblioteca excepciones como:

try {
    httpconn.setRequestMethod("POST");
} catch (ProtocolException e) {
    throw CanNeverHappenException("oh dear!");
}

Cuando usted tiene para el desorden de su código con el absurdo crud como este, no es de extrañar excepciones comprobadas recibir un montón de odio, aunque en realidad se trata de simples pobre diseño de la API.

Otro particular mal efecto en la Inversión de Control, donde Un componente de suministros de una devolución de llamada de componente genérico B. Componente de Una quiere ser capaz de permitir una excepción a tiro de su devolución de llamada de vuelta al lugar donde se llama el componente B, pero no puede debido a que iba a cambiar la interfaz de callback que se fija por B. Un solo podemos hacerlo mediante un ajuste de la excepción en una RuntimeException, lo que es aún más excepción-manejo repetitivo de escribir.

Excepciones comprobadas, como el implementado en Java y su biblioteca estándar de la media de repetitivo, repetitivo, repetitivo. En un detallado el lenguaje, esta no es una victoria.

55voto

cletus Puntos 276888

En lugar de refrito de todos los (muchos) motivos en contra de excepciones comprobadas, voy a escoger sólo uno. He perdido la cuenta del número de veces que he escrito este bloque de código:

try {
  // do stuff
} catch (AnnoyingcheckedException e) {
  throw new RuntimeException(e);
}

el 99% del tiempo que yo no puedo hacer nada al respecto. Finalmente, los bloques de hacer la limpieza necesaria (o al menos deberían).

También he perdido la cuenta del número de veces que he visto este:

try {
  // do stuff
} catch (AnnoyingCheckedException e) {
  // do nothing
}

¿Por qué? Porque alguien tenía que tratar con él y era perezoso. Fue mal? Seguro. A qué se debe? Absolutamente. Lo que si esta fuera una desactivada excepción en su lugar? La aplicación ha muerto (lo cual es preferible a tragar una excepción).

Y luego tenemos exasperante código que utiliza excepciones como una forma de control de flujo, como java.text.Format . Bzzzt. Equivocado. Un usuario pone "abc" en un número de campo de un formulario no es una excepción.

Ok, supongo que fue por tres razones.

35voto

Richard Levasseur Puntos 5428

Bien, no se trata de mostrar un stacktrace o, en silencio de estrellarse. Se trata de ser capaz de comunicarse de los errores entre las capas.

El problema con excepciones comprobadas se animan a la gente a tragar detalles importantes (es decir, la clase de excepción). Si usted elige no tragar ese detalle, entonces usted tiene que seguir sumando lanza declaraciones en toda su aplicación. Esto significa 1) que un nuevo tipo de excepción afectará a un montón de firmas de función, y 2) usted puede perder una instancia específica de la excepción que realmente quiero para pescar (dicen que abra un archivo secundario para una función que escribe datos a un archivo. El archivo secundario es opcional, así que usted puede pasar por alto sus errores, sino porque la firma throws IOException, es fácil pasar por alto este).

Estoy realmente tratar con esta situación ahora en una aplicación. Nos reenvasado casi excepciones como AppSpecificException. Esto hizo que las firmas muy limpio y no tiene que preocuparse acerca de la explosión throws en las firmas.

Por supuesto, ahora tenemos que se especializan en el manejo de errores en los niveles superiores, la aplicación de la lógica de reintento y tal. Todo es AppSpecificException, aunque, por lo que no podemos decir que "Si se produce una excepción IOException, reintentar" o "Si ClassNotFound se produce, anular por completo". No tenemos una forma segura de llegar a la verdadera excepción, porque las cosas se vuelven a empaquetar de nuevo y otra vez a medida que pasan entre nuestro código y el código de terceros.

Esta es la razón por la que soy un gran fan de el manejo de excepciones en python. Usted puede coger sólo las cosas que quieres y/o puedes manejar. Todo lo demás burbujas como si rethrew a ti mismo (que se han hecho de todos modos).

Me he encontrado, una y otra vez, y todo el proyecto que he mencionado, que el manejo de excepciones cae en 3 categorías:

  1. Capturar y manejar un específico excepción. Este es implementar la lógica de reintento, por ejemplo.
  2. Captura y rethrow otras excepciones. Todo lo que sucede aquí es generalmente de registro, y su general, un trivial de mensajes como "no se puede abrir $nombre_archivo". Estos son los errores que no puedes hacer nada; sólo un niveles más altos sabe lo suficiente para manejarlo.
  3. Captura todo y mostrar un mensaje de error. Este normalmente es en la raíz de un despachador, y todo lo que hace es asegurarse de que se puede comunicar el error a la persona que llama a través de un no-mecanismo de Excepción (diálogo emergente, el cálculo de referencias de un Error RPC objeto, etc.).

18voto

Le Dude Puntos 294

Artima publicó una entrevista con uno de los arquitectos de .NET Anders Hejlsberg, que de forma aguda cubre los argumentos en contra de excepciones comprobadas. Un corto catador:

La cláusula throws, al menos en la forma en que está implementado en Java, no necesariamente a la fuerza para controlar las excepciones, pero si no se manejan ellos, que nos fuerza a reconocer con precisión las excepciones que podría pasar. Se requiere que la captura declarada excepciones o ponerlos en su propia cláusula throws. Para evitar este requisito, las personas hacer el ridículo de las cosas. Por ejemplo, que decoran cada método, "se lanza una Excepción". Que sólo destruye por completo la función, y que acaba de hacer el programador escribir más gobbledy la suciedad. Que no ayuda a nadie.

Iteramos.com

Iteramos es una comunidad de desarrolladores que busca expandir el conocimiento de la programación mas allá del inglés.
Tenemos una gran cantidad de contenido, y también puedes hacer tus propias preguntas o resolver las de los demás.

Powered by:

X