Pregunta

Descargo de responsabilidad: esta pregunta es subjetiva, pero preferiría obtener respuestas respaldadas por hechos y/o reflexiones

Creo que todos saben sobre el Principio de robustez, generalmente resumido por la ley de Postel:

Sea conservador en lo que envía; Sea liberal en lo que aceptas.

Estoy de acuerdo en que para el diseño de un protocolo de comunicación generalizado, esto puede tener sentido (con el objetivo de permitir una extensión fácil), sin embargo, siempre he pensado que su aplicación a HTML / CSS fue una falla total, cada navegador implementando su propio ajuste silencioso Detección / comportamiento, lo que hace que sea casi imposible obtener una representación consistente en múltiples navegadores.

Sin embargo, noto que el RFC del Protocolo TCP considera aceptable la "falla silenciosa" a menos que se especifique lo contrario ... que es un comportamiento interesante, por decir lo menos.

Hay otros ejemplos de la aplicación de este principio a lo largo del comercio de software que aparecen regularmente porque han mordido los desarrolladores, desde la parte superior de mi cabeza:

  • Inserción de semi-colon de JavaScript
  • C (silencio) Conversiones construidas (que no serían tan malas si no truncara ...)

Y hay herramientas para ayudar a implementar el comportamiento "inteligente":

Sin embargo, encuentro que este enfoque, si bien puede ser útil cuando se trata de usuarios no técnicos o para ayudar a los usuarios en el proceso de recuperación de errores, tiene algunos inconvenientes cuando se aplica al diseño de la interfaz de biblioteca/clases:

  • Es algo subjetivo si el algoritmo adivina "correcto", y por lo tanto puede ir en contra del Principio de menor asombro
  • Hace que la implementación sea más difícil, por lo tanto, más posibilidades de introducir errores (violación de Yagni ?)
  • Hace que el comportamiento sea más susceptible al cambio, ya que cualquier modificación de la rutina de "adivinar" puede romper los programas antiguos, casi excluyendo las posibilidades de refactorización ... ¡desde el principio!

Y esto es lo que me llevó a la siguiente pregunta:

Al diseñar una interfaz (biblioteca, clase, mensaje), ¿se inclina hacia el principio de robustez o no?

Yo mismo tiendo a ser bastante estricto, usando una validación de entrada extensa en mis interfaces, y me preguntaba si quizás era demasiado estricto.

¿Fue útil?

Solución

yo diría robustez cuando no introduce ambigüedades.

Por ejemplo: cuando analiza una lista separada por comas, ya sea que haya un espacio antes/después de la coma no cambia el significado semántico.

Al analizar un guía de cadena, debe aceptar cualquier número de formatos comunes (con o sin guiones, con o sin aparatos ortopédicos rizados).

La mayoría de los lenguajes de programación son robustos con el uso de espacios en blanco. Específicamente en todas partes que no afecta el significado del código. Incluso en Python, donde Whitespace es relevante, sigue siendo flexible cuando estás dentro de una lista o declaración de diccionario.

Definitivamente estoy de acuerdo en que si algo se puede interpretar múltiples formas o si no está 100% claro lo que se significaba, entonces demasiada robustez puede terminar siendo un dolor, pero hay mucho espacio para la robustez sin ser ambiguo.

Otros consejos

Definitivamente no. Técnicas como programación defensiva oscuro Bugs, lo que hace que su apariencia sea menos probable y más aleatoria, lo que hace que su detección sea más difícil, lo que dificulta el aislarlos.

El enormemente subestimado Escribir código sólido fue tremendo al enfatizar repetidamente la necesidad y las técnicas de hacer que los errores fueran difíciles de introducir u ocultar. A través de la aplicación de sus principios, como "eliminar el comportamiento aleatorio. Forzar a los errores a ser reproducibles". Y, "Siempre busque y elimine, fallas en sus interfaces". Los desarrolladores mejorarán enormemente la calidad de su software al eliminar la ambigüedad y los efectos secundarios no controlados que es responsable de una gran cantidad de errores.

La aplicación excesiva de la robustez te lleva a adivinar lo que el usuario quería, lo cual está bien hasta que te equivocas. También requiere la fe completamente equivocada de que sus clientes no abusen de su confianza y creen galimatías aleatorias que simplemente funcionan, pero que no podrá admitir en la versión 2.

La aplicación excesiva de la corrección lo lleva a negar a sus clientes el derecho de cometer errores menores, lo cual está bien hasta que se quejan de que sus cosas funcionan bien en el producto de su competidor, y le diga qué puede hacer con su estándar de 5,000 páginas que tiene la palabra El "borrador" todavía garabateó en la portada en Crayon, y al menos 3 expertos afirman que es fundamentalmente defectuoso, y 200 expertos más honestos dicen que no entienden completamente.

Mi solución personal siempre ha sido la deprecación. Los apoya, pero les diga que están haciendo mal y (si es posible) el camino más fácil hacia la corrección. De esa manera, cuando apaga la característica de insectos 10 años, al menos tienes el rastro de papel para decir que "te advertimos que esto podría suceder".

Desafortunadamente, el llamado "principio de robustez" no conduce a la robustez. Tome HTML como ejemplo. Se podrían evitar muchos problemas, lágrimas, pérdida de tiempo y energía si los navegadores hubieran analizado estrictamente HTML desde el principio en lugar de tratar de adivinar el significado del contenido malformado.

El navegador simplemente debería haber mostrado un mensaje de error en lugar de intentar solucionarlo debajo de las cubiertas. Eso habría obligado a todos los Bunglers a arreglar su desastre.

Divido las interfaces en varios grupos (agregue más si lo desea):

  1. Los que están bajo su control deben ser estrictos (las clases típicamente)
  2. API de la biblioteca, que también deberían estar en el lado estricto, pero se recomienda una validación adicional
  3. Interfaces públicas que deben manejar todo tipo de abuso que viene (típicamente protocolos, entradas de los usuarios, etc.). Aquí la robustez sobre la entrada realmente vale la pena, no puede esperar que todos arreglen sus cosas. Y recuerde para el usuario que será su culpa si la aplicación no funciona, no la parte que envió una basura mal formatada.

La salida siempre debe ser estricta.

Creo que HTML y la World Wide Web han proporcionado una prueba en el mundo real a gran escala del principio de robustez y han demostrado que es un fracaso masivo. Es directamente responsable del desorden confuso de los casi estándares de HTML competidores que hace que la vida sea miserable para los desarrolladores web (y sus usuarios) y empeora con cada nuevo lanzamiento de Internet Explorer.

Hemos sabido desde la década de 1950 cómo validar el código correctamente. Ejecutarlo a través de un analizador estricto y si algo no es sintácticamente correcto, arroje un error y aborte. No pases, ir, no recoger $ 200, y por el amor de todo lo que es binario ¡No permita que algún programa de computadora intente leer la mente del codificador si cometió un error!

HTML y JavaScript nos han mostrado exactamente lo que sucede cuando se ignoran esos principios. El mejor curso de acción es aprender de sus errores y no repetirlos.

Como contrapunto al ejemplo de Mason, mi experiencia con el protocolo de Iniciacion de Sesion era que si bien diferentes pilas interpretarían los RFC relevantes de manera diferente (y sospecho que esto sucede con cada estándar siempre escrito), ser (moderadamente) liberal en lo que acepta significa que realmente puede hacer llamadas entre dos dispositivos. Debido a que estos dispositivos son cosas físicas habituales en oposición a piezas de software en un escritorio, simplemente debe ser liberal en lo que acepta, o su teléfono no puede llamar a otro teléfono de una marca en particular. ¡Eso no hace que tu teléfono se vea bien!

Pero si está escribiendo una biblioteca, probablemente no tenga el problema de que múltiples partes interpreten un estándar común de maneras mutuamente incompatibles. En ese caso, diría que sea estricto en lo que aceptas, porque elimina las ambigüedades.

El archivo de jerga también tiene un historia de horror en "adivinar" la intención de un usuario.

Tienes razón, la regla se aplica a los protocolos y no a la programación. Si realiza un error tipográfico mientras se programa, obtendrá un error tan pronto como compile (o se ejecute, si es uno de esos tipos dinámicos). No hay nada que ganar dejando que la computadora adivine por ti. A diferencia de la gente común, somos ingenieros y somos capaces de decir exactamente lo que quiero decir. ;)

Entonces, al diseñar una API, diría no Sigue el principio de robustez. Si el desarrollador comete un error, debe averiguarlo de inmediato. Por supuesto, si su API usa datos de una fuente externa, como un archivo, debe ser indulgente. El usuario de su biblioteca debe averiguar sus propios errores, pero no los de nadie más.

Como aparte, supongo que se permite el "fallo silencioso" en el protocolo TCP porque de lo contrario, si las personas le arrojaran paquetes malformados, serían bombardeados con mensajes de error. Esa es una simple protección de DOS allí mismo.

En mi opinión, la robustez es un lado de una compensación de diseño, no es un principio de "preferir". Como muchos han señalado, nada apesta como soplar cuatro horas tratando de averiguar dónde se equivocó su JS solo para descubrir que el verdadero problema fue que solo un navegador hizo lo correcto con XHTML estricto. Dejó que la página se pusiera en pedazos cuando alguna parte del HTML servido fue un desastre completo.

Por otro lado, ¿quién quiere buscar la documentación para un método que toma 20 argumentos e insiste en que estén exactamente en el mismo orden con los titulares de lugar vacíos o nulos para los que desea omitir? La forma igualmente horrible de lidiar con ese método sería verificar cada arg e intentar adivinar cuál era para lo que se basaba en posiciones y tipos relativos y luego fallar en silencio o tratar de "hacerlo" con args sin sentido.

O puede hornear la flexibilidad en el proceso pasando una lista de pares literal/diccionario/valor clave de objetos y manejar la existencia de cada argumento a medida que lo llega. Para la compensación de perforación muy menor, eso es un pastel y comélo también.

La sobrecarga de ARG de manera inteligente y consistente con la interfaz es una forma inteligente de ser robusta sobre las cosas. También lo es la redundancia de hornear en un sistema donde se supone que la entrega de paquetes no se entregará regularmente en una red masivamente complicada propiedad y administrada por todos en un campo emergente de tecnología con una amplia variedad de medios potenciales para la transmisión.

Sin embargo, tolerar una falla abyecta, especialmente dentro de un sistema que controla, nunca es una buena compensación. Por ejemplo, tuve que tomar un respiro para evitar lanzar un ajuste de symer en otra pregunta sobre poner a JS en la parte superior o inferior de la página. Varias personas insistieron en que era mejor poner JS en la parte superior porque si la página no se cargó por completo, aún podría potencialmente alguna funcionalidad. Las páginas de medio trabajo son peores que los bustos completos. En el mejor de los casos, dan como resultado más visitantes en su sitio, suponiendo que sea incompetente antes de descubrirlo que si la página rota simplemente se rebota en una página de error al no fallar su propia verificación de validación seguida de un correo electrónico automatizado a Alguien que pueda hacer algo al respecto. ¿Se sentiría cómodo entregando la información de su tarjeta de crédito a un sitio a medias todo el tiempo?

Intentar entregar la funcionalidad de 2010 en un navegador de 1999 cuando podría entregar una página de baja tecnología es otro ejemplo de una compensación de diseño insensible. Las oportunidades explotaron y el dinero que he visto en el tiempo del desarrollador dedicado a las soluciones de los bugas solo para obtener esquinas redondeadas en un elemento que se cierne sobre un fondo de gradiente!@#$ Ing, por ejemplo, me han volado por completo. ¿Y para qué? Para entregar páginas tecnológicas más altas que funcionen mal a los tecnófobos probados al tiempo que limitan sus opciones en los navegadores de gama alta.

Para que sea la elección correcta, la elección de manejar la entrada de manera robusta siempre debe facilitar la vida en ambos lados del problema, en la OMI a corto y largo plazo.

Nunca fallas en silencio. Aparte de eso, tratar de adivinar lo que el usuario de una API/biblioteca quería no suena como una mala idea. Aunque no lo seguiría; Tener un requisito estricto puede exponer errores en el código de llamadas y/o interpretaciones erróneas sobre su API/biblioteca.

Además, como ya se ha señalado, depende de lo difícil que sea adivinar lo que esperaba el usuario. Si es muy fácil, entonces tiene dos casos:

  1. Su biblioteca debe diseñarse de manera un poco diferente (cambie el nombre de alguna función o divídela en dos), para que el usuario pueda esperar lo que realmente proporciona.
  2. Si cree que su biblioteca está diseñada correctamente, lo que significa nombres claros / directos, entonces puede intentar inferir lo que el usuario pretendía.

En cualquier caso que no sea 100% obvio y determinista, que una entrada debe convertirse a otra, no debe hacer las conversiones, por varias razones ya mencionadas (la compatibilidad de la refactorización en la refactorización, el menos asombro de los usuarios).

Cuando se trata de un usuario final, tratar de solucionar su entrada/suposición es muy bienvenido. Él es esperado para ingresar información no válida; Este caso es completamente excepcional. Sin embargo, otro desarrollador no es un usuario no técnico simple. Tiene la experiencia para comprender un error, y el error puede tener importancia/ser beneficioso para él. Por lo tanto, estoy de acuerdo con usted en el diseño de API estrictas, mientras que, por supuesto, la estricción está acompañada de claridad y simplicidad.

Recomendaría que leas esta pregunta mía, de un caso similar.

Licenciado bajo: CC-BY-SA con atribución
scroll top