¿Debe un servidor "ser indulgente" en lo que acepta y "descartar silenciosamente la entrada defectuosa"?

27

Tenía la impresión de que ahora todos están de acuerdo en que esta máxima fue un error. Pero recientemente vi esta respuesta que tiene un comentario de "ser indulgente" votado 137 veces (a partir de hoy).

En mi opinión, la indulgencia en lo que aceptan los navegadores fue la causa directa del desorden total que HTML y algunos otros estándares web fueron hace unos años, y solo recientemente han comenzado a cristalizarse adecuadamente de ese desorden. La forma en que lo veo, siendo indulgentes en lo que acepta se llevará a esto.

La segunda parte de la máxima es "descartar silenciosamente la entrada defectuosa, sin devolver un mensaje de error a menos que así lo requiera la especificación" , y esto se siente ofensivo. Cualquier programador que se haya golpeado la cabeza contra la pared cuando algo falla en silencio sabrá a qué me refiero.

Entonces, ¿estoy completamente equivocado sobre esto? ¿Debería mi programa ser indulgente en lo que acepta y tragar errores en silencio? ¿O estoy interpretando mal lo que se supone que significa esto?


La pregunta original decía "programa", y tomo el punto de vista de todos sobre eso. Puede tener sentido que los programas sean indulgentes. Sin embargo, lo que realmente quise decir es API: interfaces expuestas a otros programas , en lugar de personas. HTTP es un ejemplo. El protocolo es una interfaz que solo usan otros programas. La gente nunca proporciona directamente las fechas que van en los encabezados como "If-Modified-Since".

Entonces, la pregunta es: ¿el servidor que implementa un estándar debe ser indulgente y permitir fechas en varios otros formatos, además del que realmente exige el estándar? Creo que se supone que "ser indulgente" se aplica a esta situación, en lugar de las interfaces humanas.

Si el servidor es indulgente, puede parecer una mejora general, pero creo que en la práctica solo conduce a implementaciones del cliente que terminan dependiendo de la indulgencia y, por lo tanto, no funcionan con otro servidor que es indulgente de maneras ligeramente diferentes.

Entonces, ¿un servidor que exponga alguna API sea indulgente o es una muy mala idea?


Ahora en el manejo indulgente de la entrada del usuario. Considere YouTrack (un software de seguimiento de errores). Utiliza un idioma para la entrada de texto que recuerda a Markdown. Excepto que es "indulgente". Por ejemplo, escribiendo

- foo
- bar
- baz

no es una forma documentada de crear una lista con viñetas y, sin embargo, funcionó. En consecuencia, terminó siendo utilizado mucho en todo nuestro rastreador de errores interno. La próxima versión sale, y esta característica indulgente comienza a funcionar de manera ligeramente diferente, rompiendo un montón de listas que (mal) usaron esta (no) característica. La forma documentada de crear listas con viñetas todavía funciona, por supuesto.

Entonces, ¿mi software debería ser indulgente con las entradas de usuario que acepta?

Roman Starkov
fuente
44
Con respecto a "descartar silenciosamente la entrada defectuosa", pediría para cada caso lo que debería considerarse como entrada defectuosa. Si le hace una pregunta a un usuario y espera "sí" o "no", ¿la entrada "SÍ" es defectuosa? ¿Qué tal "y"? ¿Qué tal "oui"? En general, no tenga miedo de decirle al usuario que su entrada no es lo que espera. Sin embargo, asegúrese de haber sido lo más inclusivo posible; en mi opinión, eso es lo que significa "ser indulgente".
3
Si está hablando de la entrada del usuario final, que se relaciona con las líneas de amistad de los usuarios de su aplicación, entonces debe estar atento; para la entrada automatizada generada por máquina (desde una API), debe ser detallado (estricto)
Burhan Khalid
2
En realidad, la indulgencia de HTML fue la razón por la que se hizo tan popular (y la rigurosidad de XHTML por qué se eliminó).
Oliver Weiler
1
Creo que la clave es que si se trata de un escenario en el que puede permitir que falle correctamente, es que al menos registre el evento.
Plataforma
2
@OliverWeiler Siento que el fracaso de XHTML tuvo algo que ver con el hecho de que era completamente innecesario. HTML ya estaba allí y funcionaba un poco. Además, aunque HTML es inmensamente popular, es un poco triste que llamemos a esta tecnología un éxito. Satisface la demanda, pero lo hace tan bien como Symbian satisfizo la demanda de teléfonos inteligentes.
Roman Starkov

Respuestas:

9

Por supuesto que tienes toda la razón. Los programas nunca deben ser "indulgentes" ya que hacerlo solo sirve para enmascarar problemas. Los problemas deben ser resaltados, no barridos debajo de la alfombra. Un mensaje de error informativo es imprescindible para que un programa sea útil para el usuario.

La mayoría de las veces cuando se proporcionan datos incorrectos / inválidos, el proveedor de esos datos (ya sea un usuario o la salida de algún otro programa) probablemente no sabía que eran inválidos. Tragar el error los mantendrá en la creencia de que es (o podría ser) válido, lo que prolifera datos no válidos.

La única forma para que los sistemas interoperen es que esa interoperación se defina de manera completa e inequívoca. Un programa que acepta datos fuera de la especificación hace que los datos sean aceptados de facto incluso si no son válidos por la especificación, lo que no solo hace que la compatibilidad sea una carga enorme más difícil, sino que también significa que ya no se define formalmente. El programa en sí es ahora el estándar de facto . Por lo tanto, los programas indulgentes son imposibles de desarrollar o reemplazar porque no se puede hacer el más mínimo cambio en su funcionamiento.

Timwi
fuente
25

Creo que todo depende de quién sea su objetivo demográfico. Si son programadores, entonces absolutamente no. Su programa debería fallar mucho y gritar asesinato sangriento. Sin embargo, si su público objetivo no son programadores, entonces su programa debe ser indulgente donde pueda manejar las excepciones con gracia, de lo contrario, susurre un dulce asesinato sangriento.

Como estudio de caso, tome el reproductor NPAPI Flash. Hay una versión de "lanzamiento" para aquellos que realmente no se preocupan por el 99% de los errores que pueden ocurrir, pero también hay una versión de "depuración" que puede usarse que grita asesinato sangriento cuando algo sale mal. Cada uno admite reproducir contenido Flash obviamente, pero están dirigidos a dos grupos demográficos completamente diferentes.

Al final, creo que lo importante es: ¿Qué les importa a sus usuarios?

Demian Brecht
fuente
44
Sin embargo, la gran mayoría de las herramientas de línea de comandos de Unixy que afirman tener un público objetivo fuera de los programadores son inútiles para los usuarios que cometen errores. Incluso si no es un programador, generalmente es mejor que un programa explique un problema que hacer algo sin sentido o sin intención.
Timwi
2
@romkyns: No del todo, estoy diciendo que su aplicación debe manejar los errores de manera que tengan sentido para sus usuarios objetivo.
Demian Brecht
@Timwi: en cuyo caso, esas herramientas de línea de comandos de Unixy están mal diseñadas;)
Demian Brecht
3
@romkyns: creo que un buen ejemplo sería: en modo de depuración, desea que un programa detenga cualquier problema y le diga qué salió mal. En el modo de producción, desea que su programa continúe funcionando tan bien como sea posible, y registre cualquier problema que pueda manejar. De esta manera, los programadores pueden ver lo que hicieron mal y arreglarlo, pero los usuarios no se molestarán con cosas que no pueden arreglar. Obviamente, algunos problemas no se pueden solucionar, pero un buen ejemplo son las reglas de estilo CSS, donde aún puede representar un sitio, incluso si no comprende una de las reglas de estilo.
Restablece a Monica el
1
El comentario de @ BrendanLong casi golpea el clavo en la cabeza, a veces producir resultados es más importante que ser correcto. Algunos errores (o advertencias) pueden recuperarse con gracia, sin intervención del usuario; depende de usted decidir qué desea que haga su aplicación en estos casos.
Daniel B
7

Hay dos tipos de "indulgente": uno es aceptar entradas incorrectas y tratar de darle sentido, y el otro es aceptar diferentes tipos de entradas.

En general, siempre quieres el segundo cuando sea factible. La primera es cuando mueres rápido y duro. Un ejemplo: fechas.

Aquí hay algunas entradas de ejemplo, incluidas las válidas, inválidas y ambiguas.

  • 2011-01-02
  • 01/02/2011
  • Jan 2, 2011
  • 2-Jan-2011
  • Green

Sólo hay una entrada no válida aquí: Green. Ni siquiera intentes aceptarlo como una cita. Como Greenobviamente no es una fecha, este es un caso en el que la falla silenciosa es aceptable.

01/02/2011Es válido, pero ambiguo. No necesariamente sabe si se ingresó o no como una fecha de EE. UU. (2 de enero) o no (1 de febrero). Aquí, probablemente sea mejor fallar en voz alta y pedirle al usuario una fecha inequívoca.

2011-01-02generalmente se considera inequívoco, por lo que a menudo está bien seguir adelante y asumir que es el formato "AAAA-MM-DD", y solo fallar más adelante. Sin embargo, es un poco una decisión de juicio cuando se trata de la entrada del usuario.

Jan 2, 2011y 2-Jan-2011son válidos e inequívocos, deben ser aceptados. Sin embargo, tambiénThe Second of January of the year 2011 es válido e inequívoco, pero llegar tan lejos por clemencia es excesivo. Adelante y fallarlo en silencio, como .Green

En resumen , la respuesta es "depende". Eche un vistazo a lo que se puede ingresar y asegúrese de que nunca acepte tipos de entrada en conflicto (como DD/MM/YYYYvs MM/DD/YYYY).

En el contexto de la pregunta / comentario vinculado , ese es un caso de 2011-01-02. La entrada se parece a JSON y se validará como JSON incluso si el tipo MIME es incorrecto; siga adelante e intente usarlo incluso si falla en algún momento más adelante.

Izkata
fuente
1
Hay una cosa que no estás considerando aquí. Si el usuario escribió esa cadena, sí, debería aceptar varios formatos, de eso no hay duda. Pero estamos hablando de API. Los clientes de las API son otros programas. Si es indulgente en su formato de fecha, cada servidor futuro que exponga esta API tendrá que ser indulgente exactamente de la misma manera o arriesgarse a incompatibilidad. La clemencia termina siendo perjudicial en lugar de útil, ¿no te parece?
Roman Starkov
1
@romkyns Creo que no entiendes dónde está la indulgencia. La API debe ser indulgentes en lo que se acepta (debe comprender todos 2011-01-02, Jan 2, 2011y 2-Jan-2011, si no es demasiado difícil de implementar), no en lo que se da salida . Los futuros clientes de esa API ni siquiera necesitan saber acerca de ninguno, siempre y cuando estén ingresando correctamente uno de ellos. Idealmente, la capa API convertiría todo esto en la misma representación interna que usa el código antes de pasarlo.
Izkata
@romkyns Output podría, por ejemplo, estar siempre en 2011-01-02formato, y ese es el que pondría en su documentación. No veo ningún efecto perjudicial en absoluto.
Izkata
44
@ Izkata: No entendiste bien. Imagine que hubiera un programa antiguo que solo está disponible como binario. Debe escribir un nuevo programa que acepte las mismas entradas que el anterior. Si el programa anterior estaba bien definido en lo que acepta, su trabajo está bien definido. Si es indulgente, entonces su trabajo es imposible.
Timwi
1
Un muy en desacuerdo. a menos que sea una entrada ingresada por el usuario, siempre sea estricto en la entrada y salida. ¿Qué sucede cuando su servicio necesita ser re-implementado? ¿Documentó todos los formatos de fecha posibles? Deberá implementarlos todos, ya que no desea que los clientes antiguos se rompan. Utilice ISO 8601 para todas las instancias y períodos de fechas generadas por la máquina: está bien especificado y está ampliamente disponible en las bibliotecas. Por cierto, ¿qué significa realmente 2011-01-02? ¿El período de tiempo desde las 00:00 del día 2 hasta las 00:00 del día 3? ¿En qué zona horaria?
Dibbeke
6

Fallar en silencio es lo peor que podrías hacer, nunca. ¿Has intentado depurar una API con falla silenciosa? Es imposible .

Hay "Haz tu mejor esfuerzo para recuperarte pero envía un error detallado" y hay "Falla silenciosa".

DeadMG
fuente
3

Me parece que la Ley de Postel: "Sea conservador en lo que hace, sea liberal en lo que acepta de los demás" es lo que se está discutiendo para un servicio JSON. Esto generalmente se aplica a los servicios web y no a la interfaz de usuario.

Para UI, la retroalimentación constructiva del usuario y la contracción de la entrada del usuario es la regla general que utilizamos.

MarcLawrence
fuente
Pero si mira las respuestas aquí, todos parecen estar de acuerdo en que solo tiene sentido para las IU, es decir, lo contrario de la ley original.
Roman Starkov
Veo lo que dices y estoy de acuerdo con los carteles de que un objetivo / servicio limpio y estricto es el objetivo, pero para bien o para mal sé que he agregado 'robustez' de una forma u otra a mis servicios. Por lo general, una traducción de valor o dos en la frontera. Siempre y cuando el significado sea claro, la aplicación sabe cómo procesar el mensaje y no se violan las reglas comerciales, por lo que agregar solidez ayudará a la interoperabilidad.
MarcLawrence
Hasta que alguien más vaya e implemente su especificación, solo para descubrir que la "robustez", en la que cientos de clientes han llegado a confiar, no estaba realmente en la especificación y debe ser modificada ...
Roman Starkov
3

Creo que esto está bien cubierto en el capítulo 1, sección 6 de TAOUP. Específicamente, la regla de reparación , que establece que un programa debe hacer lo que puede con una entrada, pasar los datos correctos hacia adelante y, si la respuesta correcta es un error, hágalo lo antes posible.

Un concepto similar es la programación defensiva . Usted no sabe qué tipo de entrada que recibirá, pero su programa debe ser lo suficientemente robusta como para cubrir todos los casos. Esto significa que debe programarse en casos de recuperación para problemas conocidos, como la entrada destrozada, y un caso general para manejar incógnitas.

Por lo tanto, descartar silenciosamente la entrada defectuosa está bien, siempre que esté manejando esa entrada. Nunca deberías dejarlo caer al suelo, por así decirlo.


Para una API, creo que ser indulgente es lo mismo que para un programa. La entrada sigue siendo incorrecta , pero está intentando reparar tanto como sea posible. La diferencia es lo que se considera reparación válida . Como usted señala, una API indulgente puede causar problemas ya que las personas usan "características" que no existen.

Por supuesto, una API es solo una versión de nivel inferior de la regla de composición . Como tal, está cubierto por la regla de la menor sorpresa , ya que es una interfaz.

Como señala la cita de Spencer, evite la similitud superficial, que puede discutirse sobre las entradas "difusas". En estas condiciones, normalmente argumentaría que todo apunta a que el programa no puede repararse, porque no sabrá lo que se desea, y es menos sorprendente para la base de usuarios.

Sin embargo, se trata de fechas que tienen muchos "estándares". A veces, estos incluso se mezclan en un solo programa (cadena). Como sabe que se espera una fecha, intentar reconocerla es un buen diseño. Especialmente si la fecha proviene de algún programa externo y se pasa sin modificar a través de un segundo en camino hacia usted.

Spencer Rathbun
fuente
2

Se supone que los programas que se implementan en el servidor, la mayoría de las veces, reciben miles de solicitudes cada minuto, o a veces cada segundo. Si un programa de servidor acepta y corrige la entrada defectuosa de los clientes, me temo que tendrá 2 desventajas:

  1. Pérdida del valioso tiempo del servidor. Con más de 1000 solicitudes por segundo, la verificación de fallas en cada solicitud puede reflejarse en una respuesta lenta para cada cliente.
  2. Injusto para el cliente / programas de cliente que proporcionan información correcta. Aparte de eso, cuando un programador del lado del servidor se sienta en el código del servidor, él / ella tiene que pensar en los diversos casos de qué entradas defectuosas pueden ser. ¿Quién decidirá eso?

Los programas del servidor no deben aceptar entradas defectuosas, pero los servidores deben devolver un mensaje de error al cliente, si hay una entrada defectuosa.

Abhishek Oza
fuente
2

El comportamiento ideal, conceptualmente, es hacer lo que se puede hacer de manera segura, al tiempo que se garantiza que alguien que pueda solucionar cualquier problema sea notificado de alguna manera. En la práctica, por supuesto, la última restricción a menudo es imposible de cumplir directamente, por lo que la pregunta es mejor tratar con entradas dudosas.

Una cosa que puede ser muy útil en el diseño de un protocolo, especificaciones de formato o "lenguaje" es tener un medio para distinguir cuatro categorías de elementos potenciales no comprendidos:

  1. Cosas que deberían filtrarse si no se comprenden.
  2. Cosas que deben ignorarse si no se comprenden, pero que se deben retener si es necesario transmitir los datos (tal vez en algún tipo de contenedor para indicar que han pasado por al menos una etapa que no los entendió)
  3. Las cosas que deberían generar una advertencia si no se comprenden, pero que no deberían impedir un intento de recuperación de datos (por ejemplo, dentro de una página web, un objeto cuyo tipo es desconocido, pero cuyo final dentro del archivo está bien definido, puede mostrarse en rojo "X" sin evitar que se represente el resto de la página).
  4. Cosas que indicarían que cualquier cosa que no pueda entenderlas puede tener problemas graves e irrecuperables en otros lugares (por ejemplo, un indicador de que los datos restantes están comprimidos y cualquier cosa que pueda ser entendida por cualquier cosa que pueda realizar la descompresión requerida).

Tener una convención bien definida mediante la cual las aplicaciones que pueden leer cualquier versión de un formato de datos podrán reconocer qué categoría es apropiada para cualquier cosa generada en cumplimiento con versiones posteriores es un enfoque mucho mejor que intentar encajar medidas de compatibilidad ad-hoc mas tarde. Por ejemplo, si un formato de archivo tiene líneas de la forma "Etiqueta: Valor", se podría especificar que el primer carácter de cualquier etiqueta indicará la categoría a la que pertenece; para las etiquetas de las categorías de ignorar en silencio, uno podría tener el primer carácter que también indique la versión del estándar para el cual se espera que la etiqueta sea válida (de modo que si una etiqueta de "ignorar en silencio" dice estar presente en la versión 3 de el estándar, un analizador para la versión lo ignoraría silenciosamente, pero un analizador para la versión 3 o posterior graznaría si no pudiera analizarlo).

Lo más importante en cualquier caso es evitar convertir datos ambiguos o malentendidos en datos erróneos. En algunos casos, puede ser mejor negarse a propagar datos ambiguos, aunque en otros casos puede ser mejor propagarlos exactamente como se recibieron en caso de que el destinatario lo considere inequívoco. Lo que es realmente peligroso si no es totalmente malo es la conversión de datos utilizando suposiciones variables, por ejemplo, convertir una lista de fechas como:

01/12/12
13/12/12
99/12/12

en una lista de fechas como

2012-01-12
2012-12-13
1999-12-12

Incluso si uno tuviera una lista con algunas fechas ingresadas erróneamente, puede ser posible que un humano reciba una lista en el formato original para determinar qué formato era correcto y marcar valores dudosos para futuras investigaciones (verificación de otros registros, etc. ) Sin embargo, la representación de las fechas en el último formato los empañaría irremediablemente y sin remedio.

Super gato
fuente
Bien dicho. Me gusta cómo tu respuesta es un poco más profunda. Estoy tentado a aceptar esto, pero dado el interés general que ha recibido esta pregunta, creo que lo dejaré por un tiempo.
Roman Starkov
1

Mi experiencia de UI proviene principalmente de sistemas de escritorio. Los sitios web son diferentes, aunque he visto algunos sitios que podrían desafiar un sistema de escritorio. Pero por lo que vale:

Descubrí que los mensajes de error deberían ser el último recurso; un sistema ideal no los tendría en absoluto. Lo mejor que puede hacer es no permitir entradas malas en primer lugar: el usuario no puede ingresar "verde" si está seleccionando de una lista desplegable de meses. No puede presionar un botón gris.

La siguiente mejor opción es aceptar los datos incorrectos. Digamos que está mostrando un histograma de ventas diarias durante un mes. Después de la entrada del usuario, el gráfico cubre un siglo y la barra de un siglo es 10 veces mayor que los demás. El usuario ahora sabe que hizo algo mal y, además, sabe mucho más sobre lo que hizo mal de lo que cualquier mensaje podría decirle. Cuando la entrada es gráfica, arrastrando un mouse, por ejemplo, este tipo de retroalimentación aún funciona y es invaluable. Algunas de las entradas pueden no ser válidas, pero al usar este método, el usuario obtiene comentarios instantáneos y detallados sobre los resultados de cada posición del mouse.

Dicho todo esto, a veces el usuario necesita saber por qué el botón está atenuado para que no pueda presionarlo. Entonces no hay ayuda para ello (si es así , hágamelo saber), pero para desgranar el botón y, cuando hace clic en él, darle una buena explicación de por qué el botón no funciona en este momento.

RalphChapin
fuente
0

La declaración trata sobre el envío de información a través de Internet. Una de las cosas con el envío de información a través de Internet es que no siempre llegará al objetivo o se fragmentará.

Pieter B
fuente
0

Algo que parece perderse aquí: ¿cuáles son las consecuencias del fracaso?

¿Mostrar una página web? Debe hacer todo lo posible para tolerar la entrada incorrecta. Sus opciones son mostrar lo que puede o arrojar un error. El último curso no le da nada al usuario y, por lo tanto, solo debería ser un último recurso, ya que le da al usuario un resultado completamente inútil, sería bastante difícil que un error sea peor que esto.

Por otro lado, si está pidiendo el objetivo de un Minuteman III, rechaza "Moscú" como entrada, ya que es potencialmente ambiguo.

Loren Pechtel
fuente
Entonces, incluso si eres un programador y escribiste un código estúpido, ¿el sistema debería seguir adelante y hacer todo lo posible para mostrar algo, en lugar de solo detenerte y gritar "oi, te equivocaste aquí (número de línea)"? ¿No crees que eso es exactamente lo que conduce a un código increíblemente malo?
Roman Starkov
@romkyns: tiene modos de depuración para ese tipo de cosas que son estrictas sobre los graznidos sobre errores.
Loren Pechtel