He escrito una estructura que representa las coordenadas de latitud / longitud. Sus valores varían de -180 a 180 para las longitudes y de 90 a -90 para las latitudes.
Si un usuario de esa estructura me da un valor fuera de ese rango, tengo 2 opciones:
- Lanzar una excepción (arg fuera de rango)
- Convertir el valor a la restricción
Debido a que una coordenada de -185 tiene significado (se puede convertir fácilmente a +175, ya que esas son coordenadas polares), podría aceptarla y convertirla.
¿Es mejor lanzar una excepción para decirle al usuario que su código me ha dado un valor que no debería tener?
Editar: También sé la diferencia entre lat / lng y coordenadas, pero quería simplificar eso para una discusión más fácil: no era la idea más brillante
c#
exceptions
validation
K. Gkinis
fuente
fuente
Respuestas:
Si el núcleo de su pregunta es esta ...
... entonces mi respuesta general sería "rechazar", porque esto ayudará a llamar la atención sobre posibles errores en el código del cliente que realmente están causando que el valor no válido aparezca en el programa y llegue a su constructor. Llamar la atención a los errores es generalmente una propiedad deseada en la mayoría de los sistemas, al menos durante el desarrollo (a menos que sea una propiedad deseada de su sistema para confundirse en caso de errores).
La pregunta es si realmente estás enfrentando ese caso .
Si su estructura de datos pretende modelar coordenadas polares en general, acepte el valor porque los ángulos fuera del rango -180 y +180 no son realmente inválidos. Son perfectamente válidos y siempre tienen un equivalente que está dentro del rango de -180 y +180 (y si desea convertirlos para apuntar a ese rango, siéntase libre: el código del cliente generalmente no necesita importarle) .
Si su estructura de datos está modelando explícitamente las coordenadas de Web Mercator (de acuerdo con la pregunta en su forma inicial), entonces es mejor seguir las disposiciones mencionadas en la especificación (que no sé, por lo que no diré nada al respecto) . Si la especificación de lo que está modelando dice que algunos valores no son válidos, rechazarlos. Si dice que pueden interpretarse como algo sensato (y, por lo tanto, en realidad son válidos), acéptelos.
El mecanismo que utiliza para indicar si los valores fueron aceptados o no depende de las características de su idioma, su filosofía general y sus requisitos de rendimiento. Por lo tanto, podría lanzar una excepción (en el constructor) o devolver una versión anulable de su estructura (a través de un método estático que invoca a un constructor privado) o devolver un booleano y pasar su estructura a la persona que llama como un
out
parámetro (nuevamente a través de un método estático que invoca un constructor privado), y así sucesivamente.fuente
Depende mucho Pero debe decidir hacer algo y documentarlo .
La única cosa definitivamente incorrecta que debe hacer su código es olvidarse de considerar que la entrada del usuario podría estar fuera del rango esperado y escribir código que accidentalmente tenga algún comportamiento. Porque entonces algunas personas harán una suposición incorrecta sobre cómo se comporta su código y causará errores, mientras que otras terminarán dependiendo del comportamiento que su código tenga accidentalmente (incluso si ese comportamiento es completamente loco) y, por lo tanto, causará más errores cuando luego arregles el problema.
En este caso puedo ver argumentos de cualquier manera. Si alguien viaja +10 grados desde 175 grados, debería terminar en -175. Si siempre normaliza la entrada del usuario y trata 185 como equivalente a -175, entonces el código del cliente no puede hacer lo incorrecto cuando agrega 10 grados; siempre tiene el efecto correcto. Si trata 185 como un error, fuerza todos los casos en los que el código del cliente agrega grados relativos para poner en la lógica de normalización (o al menos recuerde llamar a su procedimiento de normalización), en realidad provocaráerrores (aunque es de esperar que sean fáciles de atrapar y que sean rápidamente eliminados). Pero si un número de longitud es ingresado por el usuario, escrito literalmente en el programa, o calculado a través de algún procedimiento destinado a estar siempre en [-180, 180), entonces un valor fuera de ese rango es muy probable que indique un error, por lo que "útilmente "convertirlo podría ocultar problemas.
Mi ideal en este caso probablemente sería definir un tipo que represente el dominio correcto. Use un tipo abstracto (no permita que el código del cliente simplemente acceda a los números sin procesar dentro de él), y proporcione una fábrica de normalización y validación (para que el cliente pueda hacer la compensación). Pero sea cual sea el valor de este tipo, 185 debe ser indistinguible de -175 cuando se ve a través de su API pública (no importa si se convierten en la construcción o si proporciona igualdad, accesos y otras operaciones que ignoran la diferencia de alguna manera) .
fuente
Si realmente no le importa elegir una solución, puede dejar que el usuario decida.
Dado que su estructura es un objeto de valor de solo lectura y creado por un método / constructor, puede proporcionar dos sobrecargas basadas en las opciones que tiene el usuario:
Además, nunca permita que el usuario tenga una estructura inválida para pasar a sus otros métodos, haga lo correcto en la creación.
Editar: según los comentarios, supongo que está utilizando c #.
fuente
catch
sus excepciones. Como han dicho otros, es permitir que el cliente se restrinja si así lo desea. Realmente no estás eludiendo nada.Depende de si la entrada es directamente de un usuario a través de alguna interfaz de usuario o del sistema.
Entrada a través de una interfaz de usuario
Es una pregunta de experiencia del usuario cómo manejar la entrada no válida. No sé sobre su caso específico, pero en general hay algunas opciones:
La elección depende de las expectativas de sus usuarios y de la importancia de los datos. Por ejemplo, Google corrige automáticamente la ortografía en las consultas, pero esto es de bajo riesgo porque un cambio inútil no es un problema y es fácil de solucionar (e incluso en la página de resultados se aclara que la consulta se modificó). Por otro lado, si está ingresando coordenadas para un misil nuclear, es posible que desee una validación de entrada más rígida y sin soluciones silenciosas de datos no válidos. Entonces no hay una respuesta universal.
Lo más importante, debe considerar si corregir la entrada incluso tiene un beneficio para el usuario. ¿Por qué un usuario ingresaría datos no válidos? Es fácil ver cómo alguien podría cometer un error de ortografía, pero ¿por qué alguien ingresaría una longitud de -185? Si el usuario realmente quisiera decir +175, probablemente habría escrito +175. Creo que lo más probable es que una longitud inválida sea simplemente un error de escritura, y el usuario quiso decir -85 u otra cosa. En este caso, la conversión silenciosa es mala e inútil . El enfoque más fácil de usar para su aplicación probablemente sea alertar al usuario sobre el valor no válido y hacer que el usuario lo corrija por sí mismo.
Entrada a través de una API
Si la entrada es de otro sistema o subsistema, no hay duda. Deberías lanzar una excepción. Nunca debe convertir silenciosamente la entrada no válida de otro sistema, ya que podría enmascarar errores en otras partes del sistema. Si la entrada se "corrige", debería suceder en la capa de la interfaz de usuario, no más profundamente en el sistema.
fuente
Deberías lanzar una excepción.
En el ejemplo que dio, enviando 185 y convirtiendo eso a -175, entonces podría ser útil en algunos casos proporcionar esa funcionalidad. Pero, ¿y si la persona que llama envía 1 millón? ¿Realmente quieren convertir eso? Parece más probable que sea un error. Entonces, si necesita lanzar una excepción por 1,000,000 pero no por 185, entonces debe tomar una decisión sobre un umbral arbitrario para lanzar una excepción. Ese umbral lo hará tropezar en algún momento, ya que algunas aplicaciones de llamadas envían valores alrededor del umbral.
Es mejor lanzar la excepción para valores fuera del rango.
fuente
La opción más conveniente para un desarrollador sería un soporte de error de tiempo de compilación en la plataforma, para valores fuera de rango. En este caso, el rango también debe ser parte de la firma del método, al igual que el tipo de parámetros. De la misma manera que su usuario API no puede pasar una Cadena si su firma de método está definida para tomar un número entero , el usuario no debería haber podido pasar un valor sin verificar si el valor está dentro del rango dado en la firma del método. Si no está marcado, debería recibir un error de tiempo de compilación y, por lo tanto, podría evitarse el error de tiempo de ejecución.
Pero actualmente, muy pocos compiladores / plataformas admiten este tipo de comprobación de tiempo de compilación. Entonces, es un dolor de cabeza para desarrolladores. Pero, idealmente, su método debería arrojar una excepción significativa para los valores no compatibles y documentarlo claramente.
Por cierto, realmente me encanta el modelo de error propuesto por Joe Duffy aquí .
fuente
El valor predeterminado debe ser lanzar una excepción. También puede permitir una opción como
strict=false
y hacer la coerción en función de la bandera, donde, por supuesto,strict=true
está predeterminada. Esto es bastante común:DateFormat
admite indulgente .fuente
strict=false
?Para mí, la mejor práctica es nunca cambiar la entrada del usuario. El enfoque que suelo adoptar es separar la validación de la ejecución.
fuente