El enfoque de esta pregunta: algunos programas realizan un "trabajo adicional" para aumentar las posibilidades de un resultado "eventualmente exitoso / satisfactorio", a pesar de uno o más errores internos en el software, que requieren un tiempo de ejecución más prolongado cuando ocurren esos errores. Todo esto sucede sin el conocimiento del usuario si el resultado fue exitoso.
Definición de software complejo:
- Contiene código escrito por (contribuido por) más de 10 desarrolladores durante su vida útil, y no escrito en el mismo período de tiempo
- Depende de más de 10 bibliotecas externas, cada una con advertencias
- Una tarea de software típica (para generar un resultado deseado por el usuario) requiere 10 o más parámetros de entrada, donde la mayoría de ellos tienen valores predeterminados pero son configurables si el usuario necesita control.
- Lo más importante es que el software tiene la complejidad adecuada en relación con la tarea que se realiza, es decir, no es innecesariamente complicado .
Editado: ¿Qué es complejo? Consulte Hay una gran diferencia entre complejo y complicado . (enlace directo)
Definición de redundancia / robustez dentro de esta pregunta :
(robustez agregada basada en comentarios)
- Si una tarea de software falló cuando se usó el conjunto de parámetros actual, pruebe con diferentes parámetros.
- Obviamente, debe haber conocimiento interno de que esos parámetros "diferentes" usan una ruta de código diferente, posiblemente dando como resultado un resultado diferente (con suerte mejor).
- A veces, estas diferentes rutas de código se eligen en función de las observaciones de las bibliotecas externas.
- Al final, si la tarea real realizada es ligeramente diferente de la especificación del usuario, el usuario recibirá un informe que detalla la discrepancia.
- Finalmente, al igual que los más de 10 parámetros configurables, la redundancia y los informes también son configurables.
Ejemplo de dicho software:
- Migración de base de datos
- Base de datos de negocios
- Base de datos de control de fuente, etc.
- Conversión por lotes entre un documento de Word y un documento de OpenOffice, PowerPoint y OpenOffice Draw, etc.
- Traducción automática de un sitio web completo
- Análisis automático del paquete de software, como Doxygen, pero donde el análisis debe ser más confiable (es decir, no solo una herramienta de documentación)
- Comunicación de red, donde se pueden perder paquetes y se esperan varios reintentos
Esta pregunta se inspiró originalmente en ¿Cómo lidias con un código intencionalmente malo?
pero ahora se centra en solo una de las causas de la acumulación de software. Esta pregunta no aborda ninguna otra causa de la acumulación de software, como la adición de nuevas funciones.
Posiblemente relacionado:
Respuestas:
Esta es una pregunta comercial, no técnica.
A veces estoy codificando con investigadores o en un prototipo, así que construiremos algo con muy baja robustez. Si se rompe, lo arreglamos. No tiene sentido invertir en magia extra si vamos a tirar el código pronto.
Pero si los usuarios de su sistema necesitan que sea robusto, debe construirlo de esa manera. Y debe hacerlo robusto específicamente en las formas en que usted y ellos necesitan maximizar el éxito a largo plazo, mientras ignoran los tipos de redundancia / robustez que no necesitan.
En general, empiezo en bruto y luego agrego robustez con el tiempo. Con frecuencia hago preguntas como esta parte del proceso normal de planificación. Generalmente trabajo en el estilo de Programación Extrema, donde hacemos una larga lista de características deseadas, y también incluyo características de robustez. Por ejemplo, "El sistema sobrevive al fracaso de cualquier casilla", se mezcla con cosas como "El usuario puede unirse usando las credenciales de Facebook". Cualquiera que ocurra primero, yo construyo primero.
fuente
El software complejo generalmente es redundante como probablemente sepa, pero obviamente no porque esa sea la mejor manera de hacerlo, sino porque los desarrolladores tienden a "agregar" código existente en lugar de intentar comprender con gran detalle cómo funciona el software.
Sin embargo, si me preguntaran cuánta redundancia debería ser aceptable, diría que ninguno. La redundancia es uno de los muchos efectos secundarios de la complejidad, la archienemigo de la simplicidad. Podría decirse que la simplicidad debería quedar en segundo plano si el tiempo es de mayor importancia, aunque enfatizo que aquellos que argumentan que el tiempo es esencial rara vez son aquellos que realmente se preocupan por desarrollar software. Por lo general, es su gerente de proyecto el que le pide que haga el trabajo lo antes posible para que pueda volver a los problemas más urgentes, sin embargo, es su deber como programador saber cuándo se hace el trabajo. Creo que el trabajo no está terminado hasta que lo hayas integrado con éxito en el programa como debe ser. Quizás el programa sea complicado,
Sin embargo, debe decirse que al hacerlo, es posible que deba generar código redundante. Si el proyecto ya es muy redundante, en realidad puede ser más simple continuar el patrón, suponiendo, por supuesto, que su jefe no tenga un par de semanas para matar, lo que le permite reestructurar todo el proyecto.
Editar: a la luz de la reformulación de la pregunta, agregaré un poco sobre robustez. En mi opinión, la verificación de parámetros debe realizarse solo si A) acepta un formato muy específico, como un valor de fecha como una cadena o B) varios parámetros pueden entrar en conflicto entre sí o son mutuamente excluyentes.
Con A), los requisitos de que los parámetros coincidan con un formato específico suelen ser críticos para la necesidad del método (como una conversión a una fecha desde una cadena). Técnicamente, podría suceder en su programa sin que sea una necesidad, pero le recomiendo encarecidamente que elimine estas posibilidades y que acepte solo los parámetros que sabe que representan el tipo de datos que está buscando (acepte una fecha en lugar de una cadena si el el punto no es convertir, por ejemplo. Si la conversión también debe hacerse, use un método de utilidad para convertir la cadena antes de pasarla al método).
En cuanto a B), los parámetros mutuamente excluyentes representan una mala estructura. Debería haber dos clases, una que maneja un caso y otra que lo maneja de otra manera. Todas las operaciones comunes se pueden realizar en una sola clase base para evitar la redundancia.
En situaciones en las que el número de parámetros de un método llega a ser 10+, empiezo a considerar un archivo de propiedades que contiene todos estos parámetros que probablemente no cambien con frecuencia. Si cambian, puede guardar el valor predeterminado en el archivo de propiedades y agregar un método "setPropertyName ()" que le permite anular el valor predeterminado en tiempo de ejecución.
fuente
El software debe ser indulgente con los errores del usuario y completamente intolerante con los errores del programador.
Es decir, el software debe ser muy robusto y permitir una recuperación sin problemas para errores de entrada del usuario y errores de configuración del sistema. Como mínimo, un mensaje de error amigable que indique dónde se produjo el error (cuadro de entrada, archivo de configuración, argumento de línea de comando, etc.) y qué restricción se violó ("debe tener menos de X caracteres", "las opciones válidas son [X , Y, Z] ", etc. ...) Para una robustez adicional, el software puede sugerir una alternativa o utilizar un valor predeterminado razonable (pero siempre debe indicar que no está utilizando exactamente lo que especificó el usuario).
No puedo pensar en muchas situaciones en las que se justifique un reintento automático con diferentes valores predeterminados, pero hay algunas (el reintento automático para establecer un enlace de comunicaciones parece razonable). Estoy de acuerdo con @William en que este nivel de 'redundancia' es una decisión de negocios.
Por otro lado, no debe haber robustez en tiempo de ejecución contra el error del programador. Si hay condiciones previas para los parámetros de una función, deben verificarse con afirmaciones, no verificaciones en tiempo de ejecución. Es una gran molestia mía ver la comprobación de errores redundantes e informar sobre el mismo parámetro tres o cuatro niveles en la pila de llamadas:
Esto es solo una complejidad adicional innecesaria. No debe pasar el tiempo averiguando cómo una función debe manejar un error introducido por mal uso de otra. Si este es el tipo de "robustez" a la que se refiere, no lo necesita. Reemplácelo con afirmaciones y pruebas de integración exhaustivas.
fuente
Es una cosa de requisitos.
¿Existe un requisito de robustez?
"Cuando falla el enlace de comunicaciones, se descartan los paquetes erróneos" "Cuando el enlace reanuda la operación, no se procesa ninguna transacción dos veces"
debería haber casos de uso para la recuperación de errores (de lo contrario, ¿cómo sabe cómo sucederá?)
Dejar que los programadores inventen robustez a medida que avanzan (si es necesario) da como resultado sistemas "mágicos".
Todos los sistemas mágicos se convierten en magia horrible con el tiempo. La corrección de errores en el fondo oculta la aparición de fallas, por lo que las fallas no se corregirán, por lo que el sistema eventualmente se degradará a un estado de mayor entropía; y corre como basura, ya que corrige los errores todo el tiempo. Debe tener un límite para evitar que el sistema entre en un estado permanentemente degradado.
fuente
Algunas operaciones probablemente justifiquen un enfoque de "intentar nuevamente", especialmente si dependen de recursos externos como una base de datos. Por ejemplo, si una base de datos no se puede conectar o una consulta falla, la operación se puede volver a intentar un cierto número de veces antes de darse por vencido y lanzar un error a un nivel superior. Sin embargo, en cierta lógica, intentar lo mismo varias veces es a menudo un síntoma de mal código y pensamiento mágico que oculta problemas reales.
fuente