2009-01-07 20 views
20

Solía ​​trabajar para una empresa donde algunos de los principales arquitectos/desarrolladores habían ordenado en varios proyectos que las afirmaciones no se utilizaran, y que rutinariamente se eliminarían del código y se reemplazarían con excepciones.¿Las aserciones siempre son malas?

Creo que son extremadamente importantes para escribir el código correcto. ¿Alguien puede sugerir cómo se justifica ese mandato? Si es así, ¿qué pasa con las afirmaciones?

+0

No me gusta cómo se hace la pregunta como la veo, él dice "Lo sé mejor, si no lo haces te perseguiré" –

+0

Bueno, es claramente subjetivo. En mi opinión, también es dudoso argumentativo, pero esperaría y vería qué debate se desarrolla. – EBGreen

+1

Me complace editarlo ... Realmente me gustaría escuchar un buen razonamiento. No estoy fuera para crear una pelea. Lo siento si suena agresivo. probablemente reprimió los sentimientos de haber sido forzados a trabajar de esa manera. –

Respuesta

20

Utilizamos una versión modificada de assert, según el comentario de JaredPar, que actúa como un contrato. Esta versión está compilada en el código de liberación, por lo que hay una sobrecarga de pequeño tamaño, pero está deshabilitada a menos que se establezca un interruptor de diagnóstico, de manera que se minimice la sobrecarga de rendimiento. Nuestro manejador de afirmaciones en esta instancia puede configurarse como deshabilitado, modo silencioso (por ejemplo, registro a archivo) o modo ruidoso (por ejemplo, mostrar en pantalla con cancelar/ignorar, donde abortar arroja una excepción).

Utilizamos pruebas de regresión automática como parte de nuestras pruebas previas a la publicación, y las afirmaciones son muy importantes aquí ya que nos permiten encontrar posibles errores internos que no se pueden recoger a nivel de GUI, y pueden no ser inicialmente fatales en un nivel de usuario. Con la automatización, podemos ejecutar las pruebas con y sin diagnósticos, con poca carga adicional a la del tiempo de ejecución, por lo que también podemos determinar si las afirmaciones tienen algún otro efecto secundario.

Una cosa de la que hay que tener cuidado es que tiene sus efectos secundarios. Por ejemplo, puede ver algo como assert (MyDatabasesIsOk()), que corrige errores inadvertidamente en la base de datos. Este es un error, ya que nunca debe cambiar el estado de la aplicación en ejecución.

+2

Esto suena como una muy buena estrategia. Es divertido cuando buscas personas que piensan que las afirmaciones son malas, nunca escuchas de ellos. –

+2

+1 para evitar los efectos secundarios. He visto personas escribir código en el que creen que 'afirmar' significa 'hacerlo válido' en lugar de '' es válido ''. ¡Obviamente, el código falla si se compila la afirmación! –

1

¿Es cierto que existe una aserción en la compilación de depuración, pero no en la versión de lanzamiento?

Si desea verificar/afirmar algo, ¿no desea hacer eso en la compilación de lanzamiento, así como en la compilación de depuración?

+0

Bueno, eso es una convención. Sin embargo, es bastante fácil hacer que aparezcan en la versión Release. Y creo que a menudo es una buena idea. Sin embargo, puede ser útil tener aserciones de solo depuración que consuman mucho tiempo, como verificar que una lista sea válida cada vez que se produce una operación de lista. –

+0

Me gusta lanzar la versión del software que los desarrolladores realmente probaron; así que tiendo a eliminar la compilación 'debug' del project/makefile, de modo que solo hay una versión que se puede construir (y probar, depurar y liberar). – ChrisW

+0

Las pruebas unitarias deben ser automáticas y ejecutarse en compilaciones tanto de depuración como de versión. Las pruebas realizadas por un equipo de prueba se deben hacer utilizando la versión de lanzamiento. –

5

aserciones y excepciones se utilizan para dos cosas diferentes.

Las afirmaciones se utilizan para los estados que nunca deberían ocurrir. Por ejemplo, un puntero signalton nunca debe ser nulo y este error debe ser recogido durante el desarrollo usando una afirmación. Manejarlo con una excepción es mucho más trabajo para nada.

Por otro lado, se usan excepciones para estados raros que podrían ocurrir en el funcionamiento normal de una aplicación. Por ejemplo, usando fopen y devuelve un puntero nulo. Podría suceder, pero la mayoría de las veces devolverá un puntero válido.

El uso de aserciones es incorrecto o incorrecto, pero se reduce a preferencias personales ya que al final del día es una herramienta para facilitar la programación y puede ser reemplazada por otras herramientas.

+1

Sé que se usan para dos cosas diferentes, ¡por favor lea la pregunta otra vez! –

6

Lo único realmente negativo que puedo decir sobre las afirmaciones es que no se ejecutan en el código minorista. En nuestro equipo, tendemos a evitar afirmaciones debido a esto. En su lugar, utilizamos contratos, que son afirmaciones que se ejecutan en minoristas y en depuración.

La única vez que usamos aserciones ahora es si uno de los siguientes es verdadero.

  1. El código afirmación tiene un notable impacto en el rendimiento
  2. La condición particular no es fatal
  3. De vez en cuando hay una pieza de código que pueden o no estar muerto. Añadiremos una afirmación que básicamente dice "cómo llegaste aquí". No disparar no significa que el código esté realmente muerto, pero si QA me envía un correo electrónico y me dice "¿qué significa esta afirmación?", Ahora tenemos una reproducción para acceder a un fragmento de código en particular (está documentado inmediatamente, por supuesto).
+0

Exactamente mi manera de pensar ... vea mi comentario en la respuesta de Chris –

+0

Sobre este punto, vea esta respuesta y mi actualización al final apuntando a una pregunta relacionada: http://stackoverflow.com/questions/117171/design-by- contract-tests-by-assert-or-by-exception # 397873 –

+1

El diseño por contrato y el uso de aserciones se trata de demostrar que su estado es correcto en todo momento de una manera matemática precisa. Una vez comprobado que es correcto, no necesita probarlo todo el tiempo en el tiempo de ejecución, lo que puede ralentizar el programa. Esto puede ser algo bueno (tm) –

1

La única suposición es que debido a que una excepción a menudo no es fatal, crea una base de código que no muere en un estado extraño. El contrapunto es que la fatalidad de una afirmación indica dónde está el problema, por lo tanto, fácil de depurar.

Personalmente, prefiero correr el riesgo de una afirmación ya que creo que conduce a un código más predecible que es más fácil de depurar.

0

Las aserciones se pueden dejar simplemente al no definir NDEBUG, por lo que no es realmente un problema.

El problema real es que las aserciones llaman a abort(), lo que detiene el programa al instante. Esto puede causar problemas si hay una limpieza crítica que su programa debe hacer antes de que se cierre. Las excepciones tienen la ventaja de que los destructores se llaman correctamente, incluso si la excepción nunca se detecta.

Como resultado, en un caso donde la limpieza realmente importa, las excepciones son más apropiadas. De lo contrario, las aserciones están bien.

+0

Las afirmaciones normalmente no se dejan para compilaciones de lanzamiento, y los programas de prueba normalmente no tienen una limpieza crítica. –

3

Depende del criticidad de su sistema: afirmaciones son una estrategia de recuperación rápida , mientras que las excepciones se pueden utilizar cuando el sistema puede realizar algún tipo de recuperación.

Por ejemplo, no usaré aserciones en una aplicación de banca o en un sistema de telecomunicaciones: lanzaría una excepción, que quedaría atrapada en la parte superior de la pila de llamadas. Allí, los recursos se pueden limpiar, y la próxima llamada/transacción se puede procesar; solo uno se perderá.

+1

Se plantea la cuestión de si los datos incorrectos surgieron del usuario/programador que proporciona valores incorrectos (recuperables) o de la memoria de eliminación de datos maliciosos (irrecuperable). En este último caso, el tren está fuera de la pista. Las excepciones simplemente lo alejan del camino. Algunas veces, fallar y reiniciar es lo mejor. –

+0

De acuerdo, sin embargo, además de los punteros NULL y mal alineados, y la comprobación de vallas no hay una forma definitiva de detectar un puntero dañado. – philant

3

Las aserciones son una cosa excelente, pero no deben confundirse con la comprobación del parámetro/valor de retorno. Los usa en situaciones que no cree que ocurran, no en situaciones que espera que ocurran.

Mi lugar favorito para usarlos es en bloques de código que realmente no debe ser alcanzado - como un caso default en switch -statement más de una enumeración que tiene un case para cada valor de enumeración sea posible.

Es relativamente común que pueda extender la enumeración con nuevos valores, pero no actualiza todas las declaraciones switch-que implican la enumeración, lo querrá saber tan pronto como sea posible. Fallar fuerte y rápido es lo mejor que puede desear en tales circunstancias.

Concedido, en esos lugares, normalmente también querrá algo que se rompa en las construcciones de producción. Pero el principio de abort() ing en tales condiciones es muy recomendable. Un buen seguimiento de la pila en el depurador le proporciona la información para corregir su error más rápido que adivinar.

0

Una razón para vetar assert() es que es posible escribir código que funciona correctamente cuando se define NDEBUG, pero falla cuando NDEBUG no está definido. O viceversa.

Es una trampa que buenos programadores no deben caerse muy a menudo, pero a veces las causas pueden ser muy sutiles.Por ejemplo, el código en el assert() podría empujar las asignaciones de memoria o las posiciones de código en el ejecutable de forma tal que una falla de segmentación que sucedería, no (o viceversa).

Según el nivel de habilidad de su equipo, puede ser una buena idea alejarlos de las áreas de riesgo.

+0

Si el código es tan quisquilloso, es incluso más probable que funcione o no dependiendo de si se trata de una versión depurada o optimizada, o si está trabajando en una prueba o en un conjunto de datos realista. Las afirmaciones están muy abajo en la lista aquí. –

+0

+1 para evitar cualquier diferencia innecesaria entre compilaciones minoristas y de depuración. Vea mi respuesta anterior sobre cómo evitar esta potencial caída de fosa. –

1

Utilizamos aserciones a suposiciones de documentos.

Aseguramos en la revisión de código que no se realiza lógica de aplicación en los asertos, por lo que es bastante seguro desactivarlos poco antes de la publicación.

0

Nota: lanzar una excepción en un destructor es un comportamiento indefinido.

Cuestiones relacionadas