c++ - songs - tag de las 20 canciones preguntas
¿Las aserciones siempre son malas? (11)
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.
Siento 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?
¿Es cierto que existe una afirmació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?
Depende de la criticidad de su sistema : las afirmaciones son una estrategia sin fallas , mientras que las excepciones se pueden usar 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á.
La única cosa realmente negativa 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.
- El código de aserción tiene un impacto notable en el rendimiento
- La condición particular no es fatal
- Ocasionalmente hay un fragmento de código que puede estar muerto o no. 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).
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.
Las afirmaciones se pueden dejar simplemente al no definir el NDEBUG, por lo que no es realmente un problema.
El verdadero problema 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.
Las afirmaciones son excelentes, pero no deben confundirse con la comprobación de parámetros / valores devueltos. 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 deberían alcanzarse, como un caso default
en la declaración de switch
sobre una enumeración que tiene un case
para cada valor de enumeración posible.
Es relativamente común que pueda extender la enumeración con nuevos valores, pero no actualice todas las declaraciones de switch
involucren la enumeración, querrá saberlo lo antes posible. Fallar fuerte y rápido es lo mejor que puede desear en tales circunstancias.
Por supuesto, en esos lugares, generalmente también quieres algo que se rompa en las construcciones de producción. Pero el principio de abort()
bajo tales condiciones es altamente recomendado. Un buen seguimiento de la pila en el depurador le proporciona la información para corregir su error más rápido que adivinar.
Tenga en cuenta que lanzar una excepción en un destructor es un comportamiento indefinido.
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 en la que los buenos programadores no deberían caer muy a menudo, pero a veces las causas pueden ser muy sutiles. Por ejemplo, el código en 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).
Dependiendo del nivel de habilidad de su equipo, puede ser una buena idea alejarlos de las áreas de riesgo.
Usamos aserciones para documentar suposiciones .
Nos aseguramos en la revisión del código de que no se realice ninguna lógica de aplicación en las afirmaciones, por lo que es bastante seguro desactivarlas poco antes de la publicación.
Usamos 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 este caso 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 que pueden no ser inicialmente fatales a 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 a tener cuidado con afirma es los efectos secundarios. Por ejemplo, es posible que vea algo como assert (MyDatabasesIsOk ()) , que inadvertidamente corrige errores en la base de datos. Este es un error, ya que nunca debe cambiar el estado de la aplicación en ejecución.
las aserciones y excepciones se usan para dos cosas diferentes.
Las afirmaciones se usan para estados que nunca deberían suceder. 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, las excepciones se usan 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.