defensive-programming

defensive programming - Casos de prueba Y declaraciones de afirmación



defensive-programming (9)

El código en esta pregunta me hizo pensar

assert(value>0); //Precondition if (value>0) { //Doit }

Nunca escribo el enunciado if. Afirmar es suficiente / todo lo que puedes hacer. "Accidente temprano, bloqueo a menudo"

Estados CodeComplete :

  • La instrucción assert hace que la aplicación sea correcta
  • La prueba if hace que la aplicación sea robusta

No creo que haya hecho una aplicación más robusta corrigiendo valores de entrada no válidos, o salteando código:

assert(value >= 0 ); //Precondition assert(value <= 90); //Precondition if(value < 0) //Just in case value = 0; if (value > 90) //Just in case value = 90; //Doit

Estas correcciones se basan en suposiciones que hizo sobre el mundo exterior. Solo la persona que llama sabe qué "valor de entrada válido" es para su función, y debe verificar su validez antes de llamar a su función.

Para parafrasear CodeComplete : "Los programas del mundo real se vuelven demasiado complicados cuando no dependemos únicamente de afirmaciones".

Pregunta: ¿Estoy equivocado, terco, estúpido, demasiado no defensivo ...


Debería haber declarado que era consciente del hecho de que afirma (aquí) desaparece en el código de producción.

Si el enunciado if realmente corrige los datos de entrada no válidos en el código de producción, esto significa que la afirmación nunca se apagó durante la prueba en el código de depuración, esto significa que usted escribió un código que nunca ejecutó.

Para mí es una situación OR:

(cito a Andrew) "proteger contra todos los rangos de entrada inválida, no me molestaría con la afirmación en primer lugar". -> escribir una prueba if.

(cita aku) "valores de entrada incorrectos pueden ser perdonables" -> escribir una afirmación.

No puedo soportar los dos ...


El problema con confiar solo en Asserts es que pueden desactivarse en un entorno de producción. Para citar el artículo de wikipedia:

La mayoría de los idiomas permiten que las aserciones se activen o deshabiliten globalmente, y algunas veces de forma independiente. Las afirmaciones a menudo se habilitan durante el desarrollo y se inhabilitan durante las pruebas finales y en el lanzamiento al cliente. No se verificaron las aserciones, se evitó el costo de evaluar las aserciones mientras que, suponiendo que las aserciones están libres de efectos secundarios, siguen produciendo el mismo resultado en condiciones normales. En condiciones anormales, la desactivación de la verificación de afirmaciones puede significar que un programa que se hubiera abortado continuará ejecutándose. Esto a veces es preferible. Wikipedia

Entonces, si la exactitud de su código depende de que Asserts esté presente, puede encontrarse con serios problemas. Claro, si el código funcionó durante la prueba, debería funcionar durante la producción ... Ahora ingrese el segundo tipo que trabaja en el código y solo va a solucionar un pequeño problema ...


En algunos casos, las afirmaciones están deshabilitadas cuando se crea para el lanzamiento. Es posible que no tenga control sobre esto (de lo contrario, podría construir con afirmaciones), por lo que podría ser una buena idea hacerlo así.

El problema con "corregir" los valores de entrada es que la persona que llama no obtendrá lo que espera, y esto puede provocar problemas o incluso bloqueos en partes completamente diferentes del programa, haciendo que la depuración sea una pesadilla.

Normalmente lanzo una excepción en el enunciado if para encargarme del rol del assert en caso de que estén deshabilitados

assert(value>0); if(value<=0) throw new ArgumentOutOfRangeException("value"); //do stuff


Estoy en desacuerdo con esta declaración:

Solo la persona que llama sabe qué "valor de entrada válido" es para su función, y debe verificar su validez antes de llamar a su función.

La persona que llama puede pensar que él sabe que el valor de entrada es correcto. Solo el autor del método sabe cómo se supone que debe funcionar. El mejor objetivo del programador es hacer que el cliente caiga en el " pozo del éxito ". Debe decidir qué comportamiento es más apropiado en un caso dado. En algunos casos, los valores de entrada incorrectos pueden ser perdonables, en otros debe lanzar excepción / return error.

En cuanto a Asserts, repetiría otros comentaristas, assert es una verificación de tiempo de depuración para el autor del código, no clientes del código.


No olvides que la mayoría de los idiomas te permiten desactivar las afirmaciones ... Personalmente, si estuviera dispuesto a escribir si hay pruebas para protegerme contra todos los rangos de entrada no válida, no me molestaría con la afirmación en primer lugar.

Si, por otro lado, no escribe la lógica para manejar todos los casos (posiblemente porque no es sensato intentar y continuar con la entrada no válida), entonces estaría usando la declaración de afirmación y el enfoque de "falla temprana".


Para las funciones internas, aquellas que solo usará, solo usa aseveraciones . Las afirmaciones ayudarán a detectar errores durante su prueba, pero no obstaculizarán el rendimiento en la producción.

Verifique las entradas que se originan externamente con condiciones if . De forma externa, eso está fuera del código que usted / su equipo controlan y prueban.

Opcionalmente, puede tener ambos . Esto sería para funciones externas donde las pruebas de integración se realizarán antes de la producción.


Si recuerdo correctamente de CS-class

Las condiciones previas definen en qué condiciones se define la salida de su función. Si hace que su función maneje las condiciones de error, su función se define para esas condiciones y no necesita la declaración assert.

Así que estoy de acuerdo. Usualmente no necesitas ambos.

Como Rik comentó, esto puede causar problemas si eliminas las afirmaciones en el código publicado. Por lo general, no hago eso, excepto en lugares críticos para el rendimiento.


Un problema con las aserciones es que pueden (y normalmente lo harán) compilarse fuera del código, por lo que debe agregar ambas paredes en caso de que el compilador lo descarte.


Use aserciones para validar la entrada que controla: métodos privados y tal.

Use las declaraciones if para validar datos que no controla: interfaces públicas diseñadas para el consumo por el usuario, pruebas de entrada del usuario, etc.

Pruebe su aplicación con aserciones integradas. Luego impleméntela sin las aserciones.