Me preocupa que se trate de una excepción de tiempo de ejecución, por lo que probablemente debería usarse con moderación.
Caso de uso estándar:
void setPercentage(int pct) {
if( pct < 0 || pct > 100) {
throw new IllegalArgumentException("bad percent");
}
}
Pero eso parece que forzaría el siguiente diseño:
public void computeScore() throws MyPackageException {
try {
setPercentage(userInputPercent);
}
catch(IllegalArgumentException exc){
throw new MyPackageException(exc);
}
}
Para que vuelva a ser una excepción marcada.
Está bien, pero vayamos con eso. Si da una entrada incorrecta, obtendrá un error de tiempo de ejecución. Entonces, en primer lugar, esa es en realidad una política bastante difícil de implementar de manera uniforme, porque podría tener que hacer la conversión totalmente opuesta:
public void scanEmail(String emailStr, InputStream mime) {
try {
EmailAddress parsedAddress = EmailUtil.parse(emailStr);
}
catch(ParseException exc){
throw new IllegalArgumentException("bad email", exc);
}
}
Y lo que es peor: si bien 0 <= pct && pct <= 100
se puede esperar que la verificación del código del cliente se haga de forma estática, esto no es así para datos más avanzados, como una dirección de correo electrónico, o peor aún, algo que debe verificarse con una base de datos, por lo tanto, en general, el código del cliente no puede validar.
Básicamente, lo que estoy diciendo es que no veo una política coherente significativa para el uso de IllegalArgumentException
. Parece que no debería usarse y deberíamos ceñirnos a nuestras propias excepciones marcadas. ¿Cuál es un buen caso de uso para lanzar esto?
fuente
Cuando se habla de "entrada incorrecta", debe considerar de dónde proviene la entrada.
Si la entrada es ingresada por un usuario u otro sistema externo que no controla, debe esperar que la entrada no sea válida y siempre validarla. Está perfectamente bien lanzar una excepción marcada en este caso. Su aplicación debería 'recuperarse' de esta excepción proporcionando un mensaje de error al usuario.
Si la entrada se origina en su propio sistema, por ejemplo, su base de datos, o alguna otra parte de su aplicación, debería poder confiar en que será válida (debería haber sido validada antes de llegar allí). En este caso, está perfectamente bien lanzar una excepción no verificada como una IllegalArgumentException, que no debe detectarse (en general, nunca debe detectar excepciones no verificadas). Es un error del programador que el valor inválido haya llegado allí en primer lugar;) Debe corregirlo.
fuente
Because an unchecked exception is meant to be thrown as a result of a programming error
me ayudó a aclarar muchas cosas en mi cabeza, gracias :)Lanzar excepciones en tiempo de ejecución "con moderación" no es realmente una buena política - Effective Java recomienda que use excepciones marcadas cuando se pueda esperar razonablemente que la persona que llama se recupere . (El error del programador es un ejemplo específico: si un caso particular indica un error del programador, entonces debe lanzar una excepción sin marcar; desea que el programador tenga un seguimiento de la pila de dónde ocurrió el problema lógico, no para tratar de manejarlo usted mismo).
Si no hay esperanza de recuperación, no dude en utilizar excepciones no comprobadas; no tiene sentido atraparlos, así que está perfectamente bien.
Sin embargo, no está 100% claro a partir de su ejemplo en qué caso se encuentra este ejemplo en su código.
fuente
foo(data)
podría haber sucedido como parte de lafor(Data data : list) foo(data);
cual la persona que llama podría querer que la mayor cantidad posible de personas tengan éxito aunque algunos datos estén mal formados. También incluye errores programáticos, si mi aplicación falla significa que una transacción no se realizará, probablemente sea mejor, si significa que el enfriamiento nuclear se desconecta, eso es malo.StackOverflowError
y tales son los casos de los que no es razonable esperar que la persona que llama se recupere. Pero parece que se debe verificar cualquier caso de nivel lógico de aplicación o datos. ¡Eso significa que haga sus comprobaciones de puntero nulo!Como se especifica en el tutorial oficial de Oracle, establece que:
Si tengo una aplicación que interactúa con la base de datos
JDBC
, y tengo un método que toma el argumento comoint item
ydouble price
. Elprice
elemento correspondiente se lee de la tabla de la base de datos. Simplemente multiplico el número total deitem
compras por elprice
valor y devuelvo el resultado. Aunque siempre estoy seguro al final (final de la aplicación) de que el valor del campo de precio en la tabla nunca podría ser negativo. ¿Pero qué pasa si el valor del precio sale negativo ? Muestra que hay un problema grave con la base de datos. Quizás el operador haya introducido un precio incorrecto. Este es el tipo de problema que la otra parte de la aplicación que llama a ese método no puede anticipar y no puede recuperarse. EstáBUG
en su base de datos. Y entoncesIllegalArguementException()
este caso, se debería arrojar que afirmaría quethe price can't be negative
.Espero haber expresado mi punto con claridad.
fuente
Cualquier API debe verificar la validez de cada parámetro de cualquier método público antes de ejecutarlo:
Representan el 99,9% de las veces errores en la aplicación porque está pidiendo operaciones imposibles por lo que al final son bugs que deberían bloquear la aplicación (por lo que es un error no recuperable).
En este caso y siguiendo el enfoque de falla rápida, debe dejar que la aplicación finalice para evitar dañar el estado de la aplicación.
fuente
Trate
IllegalArgumentException
como una verificación de las condiciones previas y considere el principio de diseño: un método público debe conocer y documentar públicamente sus propias condiciones previas.Estoy de acuerdo en que este ejemplo es correcto:
Si EmailUtil es opaco , lo que significa que hay alguna razón por la que no se pueden describir las condiciones previas al usuario final, entonces una excepción marcada es correcta. La segunda versión, corregida para este diseño:
Si EmailUtil es transparente , por ejemplo, tal vez sea un método privado propiedad de la clase en cuestión,
IllegalArgumentException
es correcto si y solo si sus condiciones previas se pueden describir en la documentación de la función. Esta también es una versión correcta:Este diseño podría ir de cualquier manera.
ParseException
. El método de nivel superior aquí se nombra, loscanEmail
que sugiere que el usuario final tiene la intención de enviar un correo electrónico no estudiado, por lo que probablemente sea correcto.IllegalArgumentException
. Aunque no está "marcado", el "cheque" se mueve al Javadoc que documenta la función, que se espera que el cliente cumpla.IllegalArgumentException
donde el cliente no puede decir que su argumento es ilegal de antemano está mal.Una nota sobre IllegalStateException : Esto significa que "el estado interno de este objeto (variables de instancia privadas) no puede realizar esta acción". El usuario final no puede ver el estado privado, por lo que, hablando libremente, tiene prioridad
IllegalArgumentException
en el caso de que la llamada del cliente no tenga forma de saber que el estado del objeto es inconsistente. No tengo una buena explicación cuando se prefiere a las excepciones marcadas, aunque cosas como inicializar dos veces o perder una conexión de base de datos que no se recupera, son ejemplos.fuente