java - scorecard - perspectiva financiera ejemplos
Qué excepción lanzar para una entrada no válida que sea válida desde la perspectiva del cliente (5)
¿La pregunta es si lanzar una excepción de argumento ilegal es lo correcto?
Depende de cómo desee / necesite "enmarcar" esta condición; es decir, ¿es un error, un error de entrada del usuario o algo con lo que el programa debe poder lidiar?
Si el caso de dos líneas que no se intersecan es inequívocamente un "error", entonces
IllegalArgumentException
está bien. Para esto está diseñada la excepción. (Tenga en cuenta que es una excepción sin marcar, por lo que la expectativa es que no se capturará / recuperará).Si este es un caso en el que espera que el programa pueda recuperarse por sí solo, entonces una excepción personalizada es la mejor idea. De esa manera, reduce la posibilidad de que su código se confunda (por ejemplo) mediante un método de biblioteca que
IllegalArgumentException
(por ejemplo) unaIllegalArgumentException
... lo que significa algo distinto de "dos líneas entrecruzadas".Si este caso es algo que espera informar al usuario final como parte de la validación de entrada, entonces una excepción genérica de "error de validación" podría ser más apropiada que una excepción personalizada específica. Sin embargo, este método no parece estar diseñado para ser utilizado (únicamente) para la validación de la entrada del usuario.
Estoy escribiendo código para encontrar e intersección de 2 líneas. Cuando las pendientes de las líneas son iguales, no se intersecan. Pero, por otro lado, una entrada con pendientes de igual valor es completamente válida.
public static Point calculateIntersection(Line line1, Line line2) {
if (line1 == null || line2 == null) {
throw new NullPointerException(" some message ");
}
if (line1.getConstant() == line2.getConstant()) {
return new Point(0, line1.getConstant());
}
if (line1.getSlope() == line2.getSlope()) {
throw new IllegalArgumentException("slopes are same, the lines do not intersect.");
}
int x = (line2.getConstant() - line1.getConstant()) / (line1.getSlope() - line2.getSlope());
int y = line1.getSlope() * x + line1.getConstant();
return new Point(x, y);
}
¿La pregunta es lanzar una excepción ilegal de argumentos lo que se debe hacer? Dado que la entrada es válida, no me convence completamente.
¿Es la excepción personalizada lo correcto? Suena como una buena opción, pero una opinión adicional ayudaría.
Gracias
Como dicen @ Andy-Lowry y @KamikazeCZ, esto no debería ser una excepción.
Este método no debe preocuparse por si el cliente espera que las líneas siempre se intersecten o no; solo debería molestarse en encontrar la intersección de dos líneas, algo que inherentemente podría no suceder.
Si la persona que llama obtiene un resultado que indica que no hay intersección, entonces ESE código puede decidir si se trata de una entrada no válida porque el usuario final recibió la debida advertencia, o algo que pueda manejar (tal vez mediante una nueva solicitud), o lanzar una excepción personalizada.
Entonces, volviendo a lo que debería devolver este método? Algún tipo de valor centinela, del mismo modo que indexOf
devuelve -1 en la biblioteca de colecciones. Volviendo null
es un centinela razonable. En Java 8, puede devolver un Optional<Point>
, para recordarle a la persona que llama que es posible que no haya un Point
adecuado.
También tiene un problema adicional: ¿qué pide alguien para la intersección de una línea consigo misma? (Matemáticamente, la intersección de dos líneas es 0 puntos, 1 punto o un número infinito de puntos). Es posible que deba ser capaz de devolver dos valores de centinela, que son más complicados, en Java. Este método podría salir de la situación esta vez, diciendo "en el caso de respuestas múltiples, este método puede devolver cualquiera de ellas", o (lo que probablemente haría) "... devuelve el Punto más cercano al origen" .
Por cierto, este pensamiento se debe en gran parte a una mentalidad de prueba de unidad: comience por definir la respuesta correcta para una variedad de entradas de casos de esquina, antes de iniciar el código y comprometerse un poco a un cierto tipo de retorno, etc.
Finalmente: al comparar los resultados de getSlope()
utilizando ==
, tenga cuidado con los errores de redondeo de punto flotante. Puede que sea lo mejor que se pueda hacer aquí, pero sigue siendo problemático. Sin embargo, la forma en que asume (o redondea) la intersección con int
s, sugiere que podría tener restricciones / suposiciones muy especiales en su problema.
Es casi seguro que esto no debería lanzar una excepción, porque tiene mucho sentido invocar un método como este con cualquiera de los dos valores de Line
. Ya has manejado adecuadamente los valores nulos.
También, muy razonablemente, ha definido el comportamiento de su clase en una de las situaciones de entrada mal definidas, es decir, dos líneas "constantes" (horizontales) coincidentes, donde devuelve el punto en x=0
en esa línea. También debe seleccionar valores de retorno para los otros casos de entradas mal definidas: líneas verticales coincidentes, líneas coincidentes que no son horizontales ni verticales, y líneas paralelas no coincidentes.
En mi opinión, el resultado más natural para el último caso, las líneas paralelas no coincidentes, sería null
, reflejando el hecho de que no hay un punto de intersección.
Entonces, dependería del cliente decidir si una intersección nula justifica una excepción, un mensaje de error o lo que sea. Por ejemplo, un shell interactivo que solicita al usuario que las líneas se crucen probablemente imprimirá un mensaje de error y le pedirá al usuario que intente nuevamente. Algunos cálculos más complicados, por ejemplo, un optimizador lineal que intenta definir límites para su búsqueda, podrían querer lanzar IllegalArgumentException
si las restricciones que dan lugar a las líneas paralelas se contradicen entre sí.
Por supuesto, los valores de retorno en todos estos casos (líneas coincidentes o líneas paralelas no coincidentes) deben documentarse con precisión en el javadoc del método.
Se deben utilizar excepciones para detectar errores en el flujo del programa ("lo que sucede dentro"), no para validación de entrada. No lanzaría una excepción en absoluto. Piénselo, esto no es lo que significa "excepción", ya que es completamente normal que el usuario ingrese dos líneas con pendientes iguales.
Yo diría que haces lo correcto: te contagias la condición temprano. Es eso o la gente se quejará de que "su programa tiene errores, mire estos datos de entrada, división por 0".
Dado que no habrá tal error en más del 99% de las situaciones, esta es una condición excepcional y no permite declarar una excepción marcada, por lo que una excepción no seleccionada parece ser la opción correcta.
Ahora, en cuanto a si IllegalArgumentException
es la "buena", es al menos la excepción más cercana que describe este caso ... Puede, si cree que tiene un nombre mejor, siempre crear su propia excepción IllegalArgumentException
RuntimeException
.
Si , por otra parte, esta situación no es tan infrecuente, entonces tal vez la lógica para alcanzar esa función debería revisarse para que nunca llegue a esta condición en primer lugar.