Mi profesor sigue refiriéndose a este ejemplo de Java cuando habla de código "robusto":
if (var == true) {
...
} else if (var == false) {
...
} else {
...
}
Afirma que "código robusto" significa que su programa tiene en cuenta todas las posibilidades, y que no existe un error: el código maneja todas las situaciones y da como resultado un estado válido, de ahí el "otro".
Sin embargo, tengo dudas. Si la variable es booleana, ¿cuál es el punto de verificar un tercer estado cuando un tercer estado es lógicamente imposible?
"No tener tal cosa como un error" parece ridículo también; incluso las aplicaciones de Google muestran errores directamente al usuario en lugar de tragárselos en silencio o de alguna manera los consideran como estado válido. Y es bueno: me gusta saber cuándo algo sale mal. Y parece bastante afirmativo decir que una aplicación nunca tendría ningún error.
Entonces, ¿cuál es la definición real de "código robusto"?
fuente
Respuestas:
¿Qué pasa con un
Boolean?
que permite unNULL
estado que no es ni verdadero ni falso? ¿Ahora qué debe hacer el software? Algunos programas tienen que ser altamente resistentes a los choques como los marcapasos. ¿Alguna vez has visto a alguien agregar una columna a una base de datos que eraBoolean
e inicializar los datos actualesNULL
inicialmente? Sé que lo he visto.Aquí hay algunos enlaces que discuten lo que significa ser robusto en términos de software:
Si cree que hay una definición universalmente acordada de "robusto" aquí, buena suerte. Puede haber algunos sinónimos como a prueba de bombas o a prueba de idiotas. El programador de cinta adhesiva sería un ejemplo de alguien que generalmente escribe código robusto al menos en mi comprensión de los términos.
fuente
Por el bien de mi discusión, un Bool puede tener 2 estados, verdadero o falso. Cualquier otra cosa es la no conformidad con la especificación langugae de programación. Si su cadena de herramientas no es conforme a su especificación, se le aplicará una manguera sin importar lo que haga. Si un desarrollador crea un tipo de Bool que tiene más de 2 estados, es lo último que haría en mi base de código.
Opcion A.
Opcion B
Afirmo que la opción B es más robusta .....
Cualquier imbécil puede decirte que manejes errores inesperados. Por lo general, son muy fáciles de detectar una vez que piensas en ellos. El ejemplo que ha dado su profesor no es algo que pueda suceder, por lo que es un ejemplo muy pobre.
A es imposible de probar sin arneses de prueba complicados. Si no puede crearlo, ¿cómo lo va a probar? Si no ha probado el código, ¿cómo sabe que funciona? Si no sabe que funciona, entonces no está escribiendo un software robusto. Creo que todavía lo llaman Catch22 (Gran película, mírala alguna vez).
La opción B es trivial para probar.
Siguiente problema, pregúntele al profesor esta pregunta "¿Qué quiere que haga si un booleano no es verdadero ni falso?" Eso debería conducir a una discusión muy interesante .....
En la mayoría de los casos, un volcado de núcleo es apropiado, en el peor de los casos molesta al usuario o cuesta mucho dinero. ¿Qué sucede si, por ejemplo, el módulo es el sistema de cálculo de reentrada en tiempo real del transbordador espacial? Cualquier respuesta, por inexacta que sea, no puede ser peor que abortar, lo que matará a los usuarios. Entonces, qué hacer, si sabe que la respuesta puede ser incorrecta, elija 50/50, o aborte y vaya al 100% de falla. Si fuera un miembro de la tripulación, tomaría el 50/50.
La opción A me mata La opción B me da una posibilidad de supervivencia.
Pero espera, es una simulación de la reentrada del transbordador espacial, ¿entonces qué? Abortar para que lo sepas. ¿Suena como una buena idea? - NO - porque necesita probar con el código que planea enviar.
La opción A es mejor para la simulación, pero no se puede implementar. Es inútil La opción B es el código implementado, por lo que la simulación funciona igual que los sistemas en vivo.
Digamos que esto era una preocupación válida. La mejor solución sería aislar el manejo de errores de la lógica de la aplicación.
Lectura adicional : máquina de rayos X Therac-25, falla del cohete Ariane 5 y otros (Link tiene muchos enlaces rotos pero suficiente información que Google ayudará)
fuente
if (var != true || var != false) {
debería ser un&&
lugar.En realidad, su código no es más robusto sino MENOS robusto. El final
else
es simplemente un código muerto que no puedes probar.En el software crítico, como en las naves espaciales, está prohibido el código muerto y, en general, el código no probado: si un rayo cósmico produce un solo evento molesto que a su vez hace que se active su código muerto, todo es posible. Si el SEU activa una porción de código robusto, el comportamiento (inesperado) permanece bajo control.
fuente
Creo que el profesor podría estar confundiendo "error" y "error". El código robusto debería tener pocos / ningún error. El código robusto puede, y en un entorno hostil, debe tener una buena gestión de errores (ya sea manejo de excepciones o rigurosas pruebas de estado de retorno).
Estoy de acuerdo en que el código de ejemplo del profesor es tonto, pero no tan tonto como el mío.
fuente
boolean x = something(); if (x) { x = True // make sure it's really true, ... }
No existe una definición acordada de Código Robusto , ya que para muchas cosas en la programación es más o menos subjetivo ...
El ejemplo que da tu profesor depende del idioma:
Boolean
puede ser cualquieraTrue
oFalse
no hay una tercera opciónbool
puede sertrue
,false
o (desafortunadamente) venir de un elenco dudoso que lo puso en un caso desconocido ... Esto no debería suceder, pero puede, como resultado de un error anterior.Sin embargo, lo que su profesor está aconsejando oscurece el código al introducir una lógica extraña para eventos que no deberían suceder en el medio del programa central, por lo que le indicaré, en cambio, hacia la Programación Defensiva .
En el caso de la universidad, incluso podría aumentarlo adoptando una estrategia de diseño por contrato:
size
es el número de elementos en ladata
lista)a
un valor menor que10
)Ejemplo:
fuente
El enfoque de tu profesor es totalmente equivocado.
Una función, o solo un poco de código, debe tener una especificación que diga lo que hace, que debe cubrir cada entrada posible. Y el código debe escribirse para garantizar que su comportamiento coincida con la especificación. En el ejemplo, escribiría la especificación bastante simple como esta:
Luego escribes la función:
y el código cumple con las especificaciones. Entonces su profesor dice: ¿Qué pasa si var == 42? Mire la especificación: dice que la función debería hacer "eso". Mire el código: la función hace "eso". La función cumple con las especificaciones.
Donde el código de su profesor hace que las cosas sean totalmente descortezadas es el hecho de que con su enfoque, cuando var no es ni verdadero ni falso, ejecutará un código que nunca se ha llamado antes y que no se ha probado por completo, con resultados completamente impredecibles.
fuente
Estoy de acuerdo con la declaración de @ gnasher729: el enfoque de su profesor es totalmente equivocado.
Robusto significa que es resistente a roturas / fallas porque hace pocas suposiciones y está desacoplado: es autónomo, autodefinible y portátil. También incluye ser adaptable a los requisitos cambiantes. En una palabra, su código es duradero .
Esto generalmente se traduce en funciones cortas que obtienen sus datos de los parámetros pasados por la persona que llama y el uso de interfaces públicas para los consumidores (métodos abstractos, envoltorios, indirección, interfaces de estilo COM, etc.) en lugar de funciones que contienen código de implementación concreto.
fuente
El código robusto es simplemente un código que maneja bien las fallas. Ni mas ni menos.
De las fallas, hay muchos tipos: código incorrecto, código incompleto, valores inesperados, estados inesperados, excepciones, agotamiento de recursos, ... El código robusto los maneja bien.
fuente
Consideraría el código que proporcionó como un ejemplo de programación defensiva (al menos mientras uso el término). Parte de la programación defensiva es tomar decisiones que minimicen los supuestos sobre el comportamiento del resto del sistema. Por ejemplo, cuál de estos es mejor:
O:
(En caso de que tenga problemas para ver la diferencia, verifique la prueba de bucle: los primeros usos
!=
, los segundos usos<
).Ahora, en la mayoría de las circunstancias, los dos bucles se comportarán exactamente de la misma manera. Sin embargo, el primero (en comparación con
!=
) supone quei
se incrementará solo una vez por iteración. Si omite el valorsequence.length()
, el ciclo podría continuar más allá de los límites de la secuencia y causar un error.Por lo tanto, puede argumentar que la segunda implementación es más robusta: no depende de suposiciones acerca de si el cuerpo del bucle cambia
i
(nota: en realidad todavía asume quei
nunca es negativo).Para motivar por qué es posible que no desee hacer esa suposición, imagine que el bucle está escaneando una cadena y procesando texto. Escribes el bucle y todo está bien. Ahora sus requisitos cambian y decide que necesita admitir caracteres de escape en la cadena de texto, por lo que cambia el cuerpo del bucle de modo que si detecta un carácter de escape (por ejemplo, barra invertida), se incrementa
i
para omitir el carácter inmediatamente después del escape. Ahora el primer bucle tiene un error porque si el último carácter del texto es una barra diagonal inversa, el cuerpo del bucle se incrementarái
y el bucle continuará más allá del final de la secuencia.fuente
Personalmente describo un código como 'robusto' que tiene este, atributos importantes:
Ahora, por descanso me refiero a poner el sistema en un estado inestable o causar una excepción NO MANEJADA . Ya sabes, a veces por un concepto simple, puedes hacer una definición y explicación compleja. Pero preferiría definiciones simples. Los usuarios son bastante buenos para encontrar aplicaciones robustas. Si el usuario de su aplicación le envía muchas solicitudes sobre errores, sobre pérdida de estado, sobre flujos de trabajo no intuitivos, etc., entonces hay algo mal con su programación.
fuente