Consideremos la situación en la que tiene el código proporcionado de:
public void delete() throws IOException, SQLException { // Non-Compliant
/* ... */
}
El peligro aquí es que el código que escriba para llamar delete()
se verá así:
try {
foo.delete()
} catch (Exception e) {
/* ... */
}
Esto también es malo. Y quedará atrapado con otra regla que marca la captura de la clase de excepción base.
La clave es no escribir código que haga que quieras escribir código incorrecto en otro lugar.
La regla con la que te encuentras es bastante común. Checkstyle lo tiene en sus reglas de diseño:
Lanzamientos
Restringe las declaraciones de lanzamiento a un recuento especificado (1 por defecto).
Justificación: las excepciones forman parte de la interfaz de un método. Declarar un método para generar demasiadas excepciones con raíces diferentes hace que el manejo de excepciones sea oneroso y conduzca a prácticas de programación deficientes, como escribir código como catch (Exception ex). Esta comprobación obliga a los desarrolladores a colocar excepciones en una jerarquía de tal manera que, en el caso más simple, solo una persona que llama necesita verificar un tipo de excepción, pero cualquier subclase puede capturarse específicamente si es necesario.
Esto describe con precisión el problema y cuál es el problema y por qué no debe hacerlo. Es un estándar bien aceptado que muchas herramientas de análisis estático identificarán y marcarán.
Y si bien puede hacerlo de acuerdo con el diseño del lenguaje, y puede haber ocasiones en que sea lo correcto, es algo que debería ver e inmediatamente decir "um, ¿por qué estoy haciendo esto?" Puede ser aceptable para el código interno donde todos son lo suficientemente disciplinados como para nunca catch (Exception e) {}
, pero la mayoría de las veces he visto a personas cortar esquinas, especialmente en situaciones internas.
No hagas que las personas que usan tu clase quieran escribir códigos incorrectos.
Debo señalar que la importancia de esto se reduce con Java SE 7 y versiones posteriores porque una sola instrucción catch puede capturar múltiples excepciones ( Capturar múltiples tipos de excepciones y volver a generar excepciones con la Comprobación de tipos mejorada de Oracle).
Con Java 6 y versiones anteriores, tendría un código similar al siguiente:
public void delete() throws IOException, SQLException {
/* ... */
}
y
try {
foo.delete()
} catch (IOException ex) {
logger.log(ex);
throw ex;
} catch (SQLException ex) {
logger.log(ex);
throw ex;
}
o
try {
foo.delete()
} catch (Exception ex) {
logger.log(ex);
throw ex;
}
Ninguna de estas opciones con Java 6 es ideal. El primer enfoque viola DRY . Múltiples bloques haciendo lo mismo, una y otra vez, una vez para cada excepción. ¿Desea registrar la excepción y volver a lanzarla? Okay. Las mismas líneas de código para cada excepción.
La segunda opción es peor por varias razones. Primero, significa que está capturando todas las excepciones. El puntero nulo queda atrapado allí (y no debería). Además, está volviendo a lanzar una, lo Exception
que significa que la firma del método sería lo deleteSomething() throws Exception
que hace un desastre más arriba en la pila, ya que las personas que usan su código ahora están obligadas a hacerlo catch(Exception e)
.
Con Java 7, esto no es tan importante porque en su lugar puede hacer:
catch (IOException|SQLException ex) {
logger.log(ex);
throw ex;
}
Además, el tipo de comprobar si uno qué coger el tipo de las excepciones que es lanzado:
public void rethrowException(String exceptionName)
throws IOException, SQLException {
try {
foo.delete();
} catch (Exception e) {
throw e;
}
}
El verificador de tipos reconocerá que soloe
puede ser de tipos o . Todavía no estoy demasiado entusiasmado con el uso de este estilo, pero no está causando un código tan malo como lo era en Java 6 (donde te obligaría a que la firma del método sea la superclase que extienden las excepciones).IOException
SQLException
A pesar de todos estos cambios, muchas herramientas de análisis estático (Sonar, PMD, Checkstyle) siguen aplicando guías de estilo Java 6. No es algo malo Tiendo a estar de acuerdo con una advertencia de que estos se sigan cumpliendo, pero puede cambiar la prioridad de ellos a mayor o menor según cómo su equipo los priorice.
Si las excepciones deben ser activada o desactivada ... que es una cuestión de g r ae un t debate que uno puede encontrar fácilmente un sinnúmero de publicaciones en el blog que ocupan cada lado del argumento. Sin embargo, si está trabajando con excepciones marcadas, probablemente debería evitar lanzar varios tipos, al menos en Java 6.