Extensi贸n de macro Assert () para implementar un manejo m铆nimo de errores

"Se帽or, se me ocurri贸 una defensa del drag贸n". 隆Ya no nos tiene miedo! Se activa por el aleteo de las alas de un drag贸n y enciende una sirena ruidosa para que todos puedan escuchar al drag贸n acercarse.
"驴Esta defensa hace algo m谩s?"
"No, 驴por qu茅?" 隆Seremos advertidos!
"S铆 ... Comido por las sirenas aullando ... Y sin embargo ... 驴recordarnos cu谩ndo hemos planeado interrupciones? ...

Descripci贸n del problema


Este m茅todo no pretende el concepto de manejo de errores en proyectos complejos y complejos. M谩s bien, es un ejemplo de lo que se puede hacer con medios m铆nimos.

Una buena norma es suponer que no se debe activar ninguna aserci贸n () durante la ejecuci贸n del programa. Y si al menos una afirmaci贸n () funcion贸 al probar la aplicaci贸n, entonces debe enviar este error al desarrollador. Pero, 驴qu茅 pasa si la aplicaci贸n no se prueba completamente? 驴Y afirmar () funcionar谩 para el cliente? 驴Enviar error al desarrollador? 驴Abortar un programa? En realidad, esta ser谩 la versi贸n de lanzamiento de la aplicaci贸n y la aserci贸n est谩ndar () simplemente estar谩 deshabilitada. La pregunta tambi茅n surge con la contradicci贸n interna del sistema: deber铆a haber una gran cantidad de afirmaci贸n () para facilitar la detecci贸n de errores, pero deber铆a haber menos afirmaci贸n () para interrumpir menos al usuario y su trabajo con la aplicaci贸n. Especialmente no me gustar铆a "caer" si cu谩ntas personas usan la aplicaci贸n dependen de la estabilidad del trabajo y si afirmar () es esencialmente insignificante (requiere correcci贸n, pero permite, por ejemplo, continuar trabajando con bastante 茅xito).

Tales consideraciones conducen a la necesidad de refinar afirmar () c / c ++. Y defina sus propias macros que ampl铆en la funcionalidad del aserci贸n est谩ndar (), pero agregando un manejo m铆nimo de errores. Que tales macros sean.

VERIFY_EXIT (condici贸n);
VERIFY_RETURN (condici贸n, valor de retorno);
VERIFY_THROW (condici贸n, excepci贸n);
VERIFY_DO (condici贸n) {/ * fail block * /};

(Estas macros tambi茅n se pueden llamar de manera diferente. Por ejemplo, VERIFY_OR_EXIT (), VERIFY_OR_RETURN (), VERIFY_OR_THROW (), VERIFY_OR_DO (). O viceversa en una versi贸n m谩s corta).

Estas macros, en primer lugar, tienen una implementaci贸n tanto para la versi贸n de depuraci贸n de la compilaci贸n como para la versi贸n de lanzamiento. Eso les permite tener un comportamiento en la versi贸n de lanzamiento del programa. Es decir realizar acciones no solo durante las pruebas, sino tambi茅n con el usuario.

Descripci贸n macro


(La descripci贸n de las macros es aproximada, su otro dise帽o tambi茅n es posible).

1) VERIFY_EXIT (condici贸n);

Comprueba la condici贸n de condici贸n y, si es falsa, llama a la aserci贸n est谩ndar () (versi贸n de depuraci贸n) y tambi茅n sale de la funci贸n actual (versiones de depuraci贸n y liberaci贸n).

2) VERIFY_RETURN (condici贸n, valor de retorno);

Comprueba la condici贸n de condici贸n y, si es falsa, llama a la aserci贸n est谩ndar () (versi贸n de depuraci贸n), y tambi茅n sale de la funci贸n actual devolviendo ReturnValue (versiones de depuraci贸n y liberaci贸n).

3) VERIFY_THROW (condici贸n, excepci贸n);

Comprueba la condici贸n de condici贸n y, si es falsa, llama a la aserci贸n est谩ndar () (versi贸n de depuraci贸n) y tambi茅n genera una excepci贸n (versiones de depuraci贸n y liberaci贸n).

4) VERIFY_DO (condici贸n) {/ * fail block * /};

Comprueba la condici贸n de condici贸n y, si es falsa, llama a la aserci贸n est谩ndar () (versi贸n de depuraci贸n), y tambi茅n realiza un bloqueo fallido o una operaci贸n que sigue inmediatamente a la macro (versiones de depuraci贸n y liberaci贸n).

Para todas las macros es importante:

  • En todos los casos, la Condici贸n debe ser verdadera para "pasar" la macro y falsa para activar la ruta de manejo m铆nimo de errores.
  • Cada una de las macros implementa alg煤n m茅todo m铆nimo de manejo de errores. Esto es necesario para implementar el comportamiento en caso de errores que no se detectaron durante la prueba, pero ocurrieron en el usuario. Dependiendo de la implementaci贸n, puede informar al desarrollador sobre un error que ocurri贸 en el cliente, pero tambi茅n cada implementaci贸n proporciona una forma m铆nima de recuperarse de un error.

Patrones de uso macro


Por supuesto, lo m谩s interesante es que los superhombres entrop铆a (h茅roes de la reducci贸n de errores en los programas) son el uso de estas macros.

1) Condiciones previas y posteriores.

El primer caso de uso es pre y post condiciones. Perm铆tame recordarle que las condiciones previas verifican el estado del programa (argumentos de entrada, estado del objeto, variables utilizadas) para cumplir con los requisitos necesarios del fragmento de c贸digo ejecutado. Las condiciones de publicaci贸n (son menos comunes en los programas) est谩n destinadas a verificar que hemos logrado el resultado deseado y que el estado de los objetos sigue siendo v谩lido para el fragmento de c贸digo actual.

El uso de las macros propuestas es sencillo: asignamos cada verificaci贸n en una macro separada. Seleccionamos macros en funci贸n del manejo de errores que necesitamos. (VERIFY_EXIT () - error al procesar con la salida de esta funci贸n, VERIFY_RETURN () - error al procesar con la devoluci贸n de un valor, VERRIFY_THROW () - error al procesar con una excepci贸n, etc.)

Tambi茅n puede agregar o usar la macro VERIFICAR (), que no har谩 ning煤n manejo de errores. Esto puede ser 煤til, por ejemplo, en condiciones de publicaci贸n al final de una funci贸n.

Estas macros son completamente autosuficientes si utiliza los principios del c贸digo puro y asigna suficientes funciones para implementar acciones at贸micas. Cada funci贸n puede verificar el estado de un objeto, argumentos de entrada, etc. para llevar a cabo su acci贸n at贸mica.

2) Sem谩ntica de una transacci贸n.

Adem谩s, estas macros se pueden usar para implementar c贸digo con sem谩ntica de transacciones. Dicha sem谩ntica se entiende como: 1) preparaci贸n gradual para una operaci贸n con verificaci贸n de los resultados de cada una de las etapas de preparaci贸n; 2) la ejecuci贸n de la acci贸n solo si todas las etapas de preparaci贸n fueron exitosas; 3) negativa a cumplir, si no se cumplen algunas condiciones en la etapa de preparaci贸n (con un posible retroceso del cumplimiento).

3) Dise帽o del c贸digo, teniendo en cuenta una posible extensi贸n.

Esto es especialmente cierto para las bibliotecas y el c贸digo general, que inicialmente pueden desarrollarse dentro del contexto de una sola condici贸n de ejecuci贸n, y luego pueden comenzar a usarse con otras condiciones (comenzar a usarse de manera diferente). En este caso, estas macros pueden describir los "l铆mites" de la funcionalidad del c贸digo. Determine qu茅 fue visto inicialmente como un error y qu茅 fue exitoso. (Este enfoque est谩 cerca de las condiciones pre post post cl谩sicas). Por supuesto, escribo los "bordes" entre comillas, porque estos l铆mites pueden revisarse, pero es importante determinar (o m谩s bien transmitir a los futuros desarrolladores) el conocimiento de los l铆mites aceptables del dise帽o del c贸digo.

Implementaci贸n macro


Supongo que la mayor铆a de los desarrolladores de nivel medio no tendr谩n problemas para implementar estas macros. Pero si necesita informaci贸n, dedicar茅 algunos puntos importantes.

Las macros deben ser representables como una sola declaraci贸n. 驴Qu茅 se puede hacer con do {} while (false) construcciones o similares. Por ejemplo, as铆:

#define VERFY_EXIT(cond) \ do{bool _= (bool)(cond); assert(_); if(!_) {return;}} while(false) \ /*end macro VERIFY_EXIT()*/ 

Entonces puedes escribir el siguiente c贸digo:

 if(a > 0) VERIFY_EXIT(a%2==0); 

Por supuesto, esta es solo una de las posibilidades de implementaci贸n. Puede implementar macros de otras maneras.

PD: 隆Batalla exitosa con entrop铆a, superhombres!

Source: https://habr.com/ru/post/439172/


All Articles