¿Qué define el código robusto?

40

Mi profesor sigue refiriéndose a este ejemplo de Java cuando habla de un 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 tal cosa como un error: todas las situaciones son manejadas por el código y resultan en un estado válido, de ahí que aparezca "else".

Sin embargo, estoy dudoso. 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 nada como un error" parece ridículo también; incluso las aplicaciones de Google muestran errores directamente al usuario en lugar de tragarlos en silencio o de alguna manera considerarlos como un estado válido. Y es bueno, me gusta saber cuándo algo sale mal. Y parece bastante bien decir que una aplicación nunca tendría errores.

Entonces, ¿cuál es la definición actual de "código robusto"?

    
pregunta Lotus Notes 27.08.2011 - 00:17

10 respuestas

33
  

¿cuál es el punto de verificar un tercer estado cuando un tercer estado es   lógicamente imposible?

¿Qué pasa con un Boolean? que permite un estado NULL que no es 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 era Boolean e inicializar los datos actuales a NULL inicialmente? Sé que lo he visto.

Aquí hay algunos enlaces que analizan lo que significa ser robusto en términos de software:

Si cree que aquí hay una definición de "robusta" acordada universalmente, buena suerte. Puede haber algunos sinónimos como prueba de bomba o prueba de idiota. El programador de cinta de ducto sería un ejemplo de alguien que normalmente escribe un código robusto al menos a mi entender de los términos.

    
respondido por el JB King 27.08.2011 - 00:33
11

Por el bien de mi discusión, un Bool puede tener 2 estados, Verdadero o Falso. Cualquier otra cosa no es conforme con las especificaciones de programación langugae. Si la cadena de su herramienta no es conforme con su especificación, usted será elegido sin importar lo que haga. Si un desarrollador creó un tipo de Bool que tenía más de 2 estados, es lo último que haría en mi código base.

Opción A.

if (var == true) {
    ...
} else if (var == false) {
    ...
} else {
    ...
}

Opción B

if (var == true) {
    ...
} else {
    ...
}

Afirmo que la Opción B es más robusta .....

Cualquier twit puede decirte que manejes errores inesperados. Usualmente son fáciles de detectar una vez que piensas en ellos. El ejemplo que ha dado su profesor no es algo que pueda ocurrir, por lo que es un ejemplo muy malo.

A es imposible de probar sin arneses de prueba complicados. Si no puedes crearlo, ¿cómo lo vas a probar? Si no has probado el código, ¿cómo sabes que funciona? Si no sabe que funciona, entonces no está escribiendo software robusto. Creo que todavía lo llaman un Catch22 (gran película, verlo en algún momento).

La opción B es trivial de probar.

Próximo problema, pregúntale al profesor esta pregunta "¿Qué quieres que haga al respecto si un booleano no es Verdadero ni Falso?" Eso debería llevar a una discusión muy interesante ...

En la mayoría de los casos, un volcado de memoria es adecuado, en el peor de los casos, molesta al usuario o cuesta mucho dinero. ¿Qué pasa si, por ejemplo, el módulo es el sistema de cálculo de reingreso en tiempo real del transbordador espacial? Cualquier respuesta, no importa cuán inexacta, no puede ser peor que abortar, lo que matará a los usuarios. Entonces, qué hacer, si sabe que la respuesta podría estar equivocada, vaya por el 50/50, o cancele y vaya por la falla del 100%. Si yo fuera un miembro de la tripulación, me llevaría el 50/50.

La opción A me mata La opción B me da una oportunidad uniforme de supervivencia.

Pero espera, es una simulación de la reentrada del transbordador espacial, ¿y luego qué? Abortar para que lo sepas. ¿Suena como una buena idea? - NO - porque necesita probar el código que planea enviar.

La opción A es mejor para la simulación, pero no se puede implementar. Es inutil La opción B es el código desplegado, por lo que la simulación se realiza de la misma manera 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.

if (var != true || var != false) {
    errorReport("Hell just froze over, var must be true or false")
}
......
if (var == true){
 .... 
} else {
 .... 
}

Lecturas futuras : máquina Therac-25 Xray, falla del Ariane 5 Rocket y otros (El enlace tiene muchos enlaces rotos pero suficiente información que Google ayudará)

    
respondido por el mattnz 27.08.2011 - 10:34
9

En realidad, su código no es más robusto sino MENOS robusto. El último else es simplemente el código muerto que no puedes probar.

En software crítico, como en naves espaciales, se prohíbe el código muerto y, en general, el código no probado: si un rayo cósmico produce un único evento molesto que a su vez hace que se active su código muerto, todo es posible. Si la SEU activa una parte del código robusto, el comportamiento (inesperado) permanece bajo control.

    
respondido por el mouviciel 27.08.2011 - 14:11
7

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 un manejo de excepciones o pruebas rigurosas de estado de retorno).

Estoy de acuerdo en que el ejemplo del código del profesor es tonto, pero no tan tonto como el mío.

// Assign 3 to x
var x = 3;
x = 3;   // again, just for sure
while (x < 3 or x > 3) { x = 3; }  // being robust
if (x != 3) { ... }  // this got to be an error!
    
respondido por el David Andersson 27.08.2011 - 03:00
5

No hay 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:

  • En Haskell, un Boolean puede ser True o False , no hay una tercera opción
  • En C ++, un bool puede ser true , false , o (desafortunadamente) puede provenir 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 aconseja oscurece el código al introducir una lógica extraña para los eventos de no debería suceder en el centro del programa central, por lo que le indicaré, en cambio, hacia Programación Defensiva .

En el caso de la universidad, incluso podría aumentarlo adoptando una estrategia de diseño por contrato:

  • Establezca invariantes para las clases (por ejemplo, size es el número de elementos en la lista data )
  • Establezca condiciones previas y condiciones posteriores para cada función (por ejemplo, esta función solo puede invocarse con a siendo menor que 10 )
  • Pruebe cada uno de los puntos de entrada y salida de cada una de sus funciones

Ejemplo:

class List:
  def __init__(self, items):
    self.__size = len(items)
    self.__data = items

  def __invariant(self):
    assert self.__size == len(self.__data)

  def size(self):
    self.__invariant()

    return self.__size

  def at(self, index):
    """index should be in [0,size)"""
    self.__invariant()
    assert index >= 0 and index < self.__size

    return self.__data[index]

  def pushback(self, item):
    """the subsequent list is one item longer
       the item can be retrieved by self.at(self.size()-1)"""
    self.__invariant()

    self.__data.append(item)
    self.__size += 1

    self.__invariant()
    assert self.at(self.size()-1) == item
    
respondido por el Matthieu M. 27.08.2011 - 14:28
2

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 debería cubrir cada entrada posible. Y el código debe escribirse de modo que se garantice que su comportamiento coincida con la especificación. En el ejemplo, escribiría una especificación bastante simple como esta:

Spec: If var is false then the function does "this", otherwise it does "that". 

Luego escribes la función:

if (var == false) dothis; else dothat; 

y el código cumple con la especificación. Entonces tu profesor dice: ¿Y si var == 42? Mira la especificación: Dice que la función debería hacer "eso". Mira el código: La función hace "eso". La función cumple con la especificación.

Donde el código de su profesor hace que las cosas sean totalmente desconcertantes es el hecho de que con su enfoque, cuando var no es ni verdadero ni falso, ejecutará un código que nunca antes se había llamado y que no se ha probado completamente, con resultados totalmente impredecibles.

    
respondido por el gnasher729 16.05.2015 - 21:45
1

Estoy de acuerdo con la declaración de @gnasher729: El enfoque de su profesor es totalmente erróneo.

Robusto significa que es resistente a la rotura / falla porque hace pocas suposiciones y está desacoplado: es autónomo, se define y es 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 el llamante y el uso de interfaces públicas para los consumidores (métodos abstractos, envoltorios, direccionamiento indirecto, interfaces de estilo COM, etc.) en lugar de funciones que contienen un código de implementación concreto. .

    
respondido por el Vector 18.09.2011 - 22:35
0

El código robusto es simplemente un código que maneja bien los fallos. No más, 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 maneja estos bien.

    
respondido por el Sparky 27.08.2011 - 15:27
0

Consideraría el código que dio como un ejemplo de programación defensiva (al menos como uso el término). Parte de la programación defensiva es hacer elecciones que minimicen las suposiciones sobre el comportamiento del resto del sistema. Por ejemplo, cuál de estos es mejor:

for (int i = 0; i != sequence.length(); ++i) {
    // do something with sequence[i]
}

O:

for (int i = 0; i < sequence.length(); ++i) {
    // do something with sequence[i]
}

(En caso de que tenga problemas para ver la diferencia, verifique la prueba de bucle: la primera usa != , la segunda usa < ).

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 != ) asume que i se incrementará solo una vez por iteración. Si omite el valor sequence.length() , el bucle podría continuar más allá de los límites de la secuencia y provocar un error.

Por lo tanto, puede presentar un argumento de que la segunda implementación es más sólida: no depende de suposiciones sobre si el cuerpo del bucle cambia i (nota: en realidad aún se supone que i nunca es negativo).

Para motivarte por qué no quieres hacer esa suposición, imagina que el bucle está escaneando una cadena y procesando el texto. Usted escribe 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 manera que si detecta un carácter de escape (por ejemplo, barra diagonal inversa), incrementa i para omitir el carácter que sigue inmediatamente a escapar. Ahora el primer bucle tiene un error porque si el último carácter del texto es barra diagonal inversa, el cuerpo del bucle incrementará i y el bucle continuará más allá del final de la secuencia.

    
respondido por el John Bartholomew 27.08.2011 - 20:58
-1

Personalmente describo un código como 'robusto', que tiene uno de estos atributos importantes:

  1. Si mi madre se sienta frente a ella y trabaja con ella, no puede romper el sistema

Ahora, con ruptura me refiero a poner el sistema en un estado inestable, o causar una excepción NO HANDLED . Ya sabes, a veces por un concepto simple, puedes hacer una definición y explicación complejas. Pero prefiero 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.

    
respondido por el Saeed Neamati 27.08.2011 - 12:54

Lea otras preguntas en las etiquetas

Comentarios Recientes

Es lo que hace que su aplicación produzca código confiable. El código es limpio, consistente y el estado cambia muy poco, como el estado cambia cuando los archivos se cargan en el sistema de archivos y las vistas frontales aparecen sin errores. No tiene sentido romper ningún código, siempre. No tiene sentido romper ningún código, siempre. Malos hábitos. Tener un código pobre y fragmentado hace que sea difícil para los usuarios comprender y comprender las medidas de seguridad y garantiza el mantenimiento continuo... Lee mas