He visto este tema surgir a veces en el pasado, pero incluso después de buscar en Google about it, todavía no puedo entender cuál sería una buena y elegante forma de manejarlo, así que aquí va.Múltiples capturas específicas o una captura todas?
Decir que tengo un código que lanza varias excepciones ...
try {
/* some code that throws these exceptions */
} catch (NoSuchAuthorityCodeException e) {
throw new MyAPIException("Something went wrong", e);
} catch (FactoryException e) {
throw new MyAPIException("Something went wrong", e);
} catch (MismatchedDimensionException e) {
throw new MyAPIException("Something went wrong", e);
} catch (TransformException e) {
throw new MyAPIException("Something went wrong", e);
}
... y como podemos ver, acabo de envolver estas excepciones y lanzar uno nuevo decir que algo ha ido mal dentro de mi API .
Esto me parece un código excesivamente repetitivo, por lo que uno simplemente cogerá un tipo de excepción y manejará wrap y lanzará uno nuevo.
try {
/* some code that throws these exceptions */
} catch (Exception e) {
throw new MyAPIException("Something went wrong", e);
}
En este caso, sigue siendo mucho más simple, pero la cuestión es que también captaríamos todas las RuntimeException. Teniendo esto en cuenta, podríamos atrapar y volver a lanzar la RuntimeException para poder evitar esto.
try {
/* some code that throws some exceptions */
} catch (RuntimeException e) {
throw e;
} catch (Exception e) {
throw new MyAPIException("Something went wrong", e);
}
Es un poco abultado pero funciona. Ahora hay otro pequeño problema sobre la captura (Excepción e), que si mi API interna arroja otra MyAPIException también sería atrapada, envuelta y lanzada dentro de otra MyAPIException. En este caso particular, también podríamos capturar MyAPIException y volver a lanzarlo.
try {
/* some code that throws some exceptions */
} catch (RuntimeException e) {
throw e;
} catch (MyAPIException e) {
throw e;
} catch (Exception e) {
throw new MyAPIException("Something went wrong", e);
}
Bueno, es ensuciarse MyAPIException de nuevo, pero en este caso evitar el ajuste y simplemente volver a lanzarla. Pero, también hay otro problema con el bloque catch (Exception e) que es si la API interna cambia y comienza a lanzar otro tipo de excepción (alguna que no sea la mencionada anteriormente 4), el compilador no diría nada al respecto y nosotros no lo haríamos. Tienes una pista. No es que esto sea un problema importante, ya que probablemente lo trataría de la misma manera.
Con este escenario, creo que la pregunta es, ¿cuál es mejor y hay mejores opciones?
La cosa es que si simplemente empezar a tirar todas las demás excepciones, otra persona tendría que hacer frente a todas esas excepciones y yo no creo que es muy bueno tener un método que lanza tipos montón de excepciones. Además, si tuviera que tener un tipo de excepción para cada excepción envuelta, sería simplemente una tontería ... ¿por qué no simplemente tirarla? (y ahora tenemos una recursión) –
@Pablo Cabrera: ver mi respuesta editada – bragboy
Bueno, en este caso, solo quiero mostrarle al usuario de esta API que algo salió mal y que no pudo completarse para que pueda lidiar con esto en un simple bloque catch (catch (MyAPIException e)) en lugar de atrapar múltiples tipos de excepciones o tener que lidiar con este mismo problema de captura presentado aquí. En caso de que el usuario quisiera saber la razón por la cual falló, (s) él todavía puede ver la causa dentro de la excepción. Creo que algo como esto sería una API mucho más ordenada, pero como dijiste, podría ser una decisión crítica. ¿Alguna idea? –