[Descargo de responsabilidad: esta pregunta es subjetiva, pero preferiría obtener respuestas respaldadas por hechos y / o reflexiones]
Creo que todos conocen el Principio de Robustez , generalmente resumido por la Ley de Postel:
Sea conservador en lo que envía; sé 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 un fracaso total, cada navegador implementa su propio ajuste silencioso detección / comportamiento, por lo que es casi imposible obtener una representación coherente en varios navegadores.
Sin embargo, me doy cuenta de que allí el RFC del protocolo TCP considera aceptable la "falla silenciosa" a menos que se especifique lo contrario ... lo cual es un comportamiento interesante, por decir lo menos.
Hay otros ejemplos de la aplicación de este principio en todo el comercio de software que aparecen regularmente porque han mordido a los desarrolladores, desde lo más alto de mi cabeza:
- Inserción de punto y coma de Javascript
- Conversiones incorporadas C (silenciosas) (que no serían tan malas si no se truncaran ...)
y hay herramientas para ayudar a implementar el comportamiento "inteligente":
- algoritmos fonéticos coincidentes de nombre ( Metaphone doble )
- algoritmos de distancias de cuerda ( distancia de Levenshtein )
Sin embargo, encuentro que este enfoque, aunque puede ser útil cuando se trata con 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 Menos 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 a cambios, ya que cualquier modificación de la rutina "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 extensa validación de entrada en mis interfaces, y me preguntaba si quizás era demasiado estricto.
Respuestas:
Diría robustez cuando no introduce ambigüedades .
Por ejemplo: al analizar una lista separada por comas, si hay un espacio antes / después de la coma no cambia el significado semántico.
Al analizar un guid de cadena, debe aceptar cualquier número de formatos comunes (con o sin guiones, con o sin llaves).
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 el espacio en blanco 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 de varias maneras o si no está 100% claro lo que significaba, entonces demasiada robustez puede terminar siendo un dolor, pero hay mucho espacio para la robustez sin ser ambiguo.
fuente
{"key": "value",}
como válido, IE no. A menudo me topé con este problema en particular hasta que mejoré mi proceso de compilación con JSlint.Definitivamente no. Las técnicas como la programación defensiva ocultan los errores, lo que hace que su apariencia sea menos probable y más aleatoria, lo que dificulta su detección, lo que hace que aislarlos sea más difícil.
El código sólido de escritura, ampliamente subestimado, fue tremendo al enfatizar repetidamente la necesidad y las técnicas de hacer que los errores sean tan difíciles de introducir u ocultar. Mediante la aplicación de sus principios como "Eliminar el comportamiento aleatorio. Forzar errores para que sean reproducibles". y, "Siempre busque y elimine defectos 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 son responsables de una gran cantidad de errores.
fuente
La aplicación excesiva de 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 abusarán de su confianza y crearán galimatías aleatorias que simplemente funcionan, pero que no podrá soportar en la versión 2.
La aplicación excesiva de la corrección hace que usted niegue a sus clientes el derecho a cometer errores menores, lo cual está bien hasta que se quejan de que sus cosas funcionan bien en el producto de su competencia y le dicen qué puede hacer con su estándar de 5,000 páginas que tiene la palabra "BORRADOR" todavía garabateado en la portada en crayón, 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 depreciación. Los apoyas, pero les dices que lo están haciendo mal y (si es posible) el camino más fácil hacia la corrección. De esa manera, cuando apaga la función de error 10 años más adelante, al menos tiene el rastro de papel para afirmar que "le advertimos que esto podría suceder".
fuente
Lamentablemente, el llamado "principio de robustez" no conduce a la robustez. Toma HTML como ejemplo. Se podrían haber evitado 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 con formato incorrecto.
El navegador simplemente debería haber mostrado un mensaje de error en lugar de intentar arreglarlo debajo de las cubiertas. Eso habría obligado a todos los bunglers a arreglar su desastre.
fuente
Divido las interfaces en varios grupos (agregue más si lo desea):
La salida siempre debe ser estricta.
fuente
Creo que HTML y la World Wide Web han proporcionado una prueba a gran escala del Principio de Robustez en el mundo real y han demostrado que es un fracaso masivo. Es directamente responsable del desorden confuso de los casi estándares HTML competitivos que hacen la vida miserable para los desarrolladores web (y sus usuarios) y empeora con cada nueva versión de Internet Explorer.
Hemos sabido desde la década de 1950 cómo validar el código correctamente. Ejecútelo a través de un analizador estricto y si algo no es sintácticamente correcto, arroje un error y cancele. No pase, no recolecte $ 200, y por amor a 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 qué sucede cuando se ignoran esos principios. El mejor curso de acción es aprender de sus errores y no repetirlos.
fuente
Como contrapunto al ejemplo de Mason, mi experiencia con el Protocolo de inicio de sesión fue que, si bien las diferentes pilas interpretarían los RFC relevantes de manera diferente (y sospecho que esto sucede con cada estándar jamás escrito), ser (moderadamente) liberal en lo que acepta significa que usted en realidad puede hacer llamadas entre dos dispositivos. Debido a que estos dispositivos son elementos físicos habituales en lugar de piezas de software en una computadora de 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 su teléfono se vea bien!
Pero si está escribiendo una biblioteca, probablemente no tenga el problema de que varias partes interpreten un estándar común de maneras mutuamente incompatibles. En ese caso, diría que sea estricto en lo que acepta, porque elimina las ambigüedades.
The Jargon File también tiene una historia de terror sobre "adivinar" la intención de un usuario.
fuente
Tienes razón, la regla se aplica a los protocolos y no a la programación. Si comete un error tipográfico mientras programa, recibirá un error tan pronto como compile (o ejecute, si es uno de esos tipos dinámicos). No se gana nada dejando que la computadora adivine por usted. 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, yo diría que no sigas el Principio de Robustez. Si el desarrollador comete un error, debe averiguarlo de inmediato. Por supuesto, si su API utiliza datos de una fuente externa, como un archivo, debe ser indulgente. El usuario de su biblioteca debe conocer sus propios errores, pero no los de nadie más.
Por otro lado, supongo que se permite una "falla silenciosa" en el protocolo TCP porque de lo contrario, si las personas le arrojaran paquetes malformados, sería bombardeado con mensajes de error. Eso es simple protección DoS allí mismo.
fuente
En mi opinión, la robustez es un lado de una compensación de diseño, no un principio de "preferencia". Como muchos han señalado, nada apesta como pasar cuatro horas tratando de averiguar dónde se equivocó su JS solo para descubrir que el verdadero problema era que solo un navegador hizo lo correcto con XHTML Strict. Dejó que la página se hiciera pedazos cuando una parte del HTML servido fue un completo desastre.
Por otro lado, ¿quién quiere buscar documentación para un método que toma 20 argumentos e insiste en que estén exactamente en el mismo orden con marcadores de posición de valor vacío o nulo para los que desea omitir? La manera igualmente horrible y robusta de lidiar con ese método sería verificar cada argumento y tratar de adivinar cuál era en función de las posiciones y tipos relativos y luego fallar en silencio o tratar de "compensar" con argumentos sin sentido.
O puede incorporar flexibilidad en el proceso al pasar una lista de pares de objeto / diccionario / clave-valor de objeto y manejar la existencia de cada argumento a medida que llega a él. Para la muy pequeña compensación de rendimiento, eso es un pastel y comérselo también.
La sobrecarga de argumentos de manera inteligente y coherente con la interfaz es una forma inteligente de ser robusto sobre las cosas. Entonces, la redundancia se está convirtiendo en un sistema en el que se supone que la entrega de paquetes no se entregará regularmente en una red enormemente complicada, propiedad y administrada por todos en un campo emergente de tecnología con una amplia variedad de posibles medios de transmisión.
Sin embargo, tolerar el fracaso absoluto, especialmente dentro de un sistema que controlas, nunca es una buena compensación. Por ejemplo, tuve que tomar un respiro para evitar lanzar un ataque de silbido en otra pregunta sobre cómo colocar JS en la parte superior o inferior de la página. Varias personas insistieron en que era mejor poner a JS en la parte superior porque si la página no se cargaba por completo, aún podría tener alguna funcionalidad. Las páginas de medio trabajo son peores que los bustos completos. En el mejor de los casos, generan más visitantes a su sitio con la suposición correcta de que usted es incompetente antes de que se entere que si la página rota simplemente se devuelve a una página de error al fallar su propia verificación de validación seguida de un correo electrónico automatizado para alguien que pueda hacer algo al respecto.
Intentar ofrecer la funcionalidad de 2010 en un navegador de 1999 cuando podría entregar una página de tecnología más baja es otro ejemplo de un compromiso de diseño imprudente. Las oportunidades desperdiciadas y el dinero que he visto desperdiciado en el tiempo de los desarrolladores dedicados a soluciones temporales llenas de errores solo para obtener esquinas redondeadas en un elemento que se cierne sobre un fondo degradado! @ # $ Ing, por ejemplo, me han impresionado por completo. ¿Y para qué? Para entregar páginas de alta tecnología que tengan un rendimiento deficiente a tecnófobos probados mientras limitan sus opciones en navegadores de gama alta.
Para que sea la elección correcta, la elección de manejar la entrada de manera robusta siempre debería facilitar la vida en ambos lados del problema, en el corto y largo plazo de la OMI.
fuente
Nunca falles en silencio . Aparte de eso, tratar de adivinar lo que quería el usuario de una API / biblioteca, no parece una mala idea. Sin embargo, no lo seguiría; Tener un requisito estricto, puede exponer errores en el código de llamada y / o malas interpretaciones sobre su API / biblioteca.
Además, como ya se ha señalado, depende de lo difícil que sea adivinar lo que el usuario esperaba. Si es muy fácil, entonces tienes dos casos:
En cualquier caso, no es 100% obvio y determinista, que una entrada se convierta en otra, no debe hacer las conversiones, por una serie de razones ya mencionadas (romper la compatibilidad en la refactorización, menos asombro de los usuarios).
Al tratar con un usuario final, tratar de corregir su entrada / suposición es muy bienvenido. Se espera que ingrese información no válida; Este caso es completamente excepcional. Sin embargo, otro desarrollador no es un simple usuario no técnico. 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 rigurosidad va acompañada de claridad y simplicidad.
Le recomendaría que lea esta pregunta mía , de un caso similar.
fuente