¿Cómo puedo mejorar mi comprobación y manejo de errores?


13

Últimamente he estado luchando por comprender cuál es la cantidad correcta de verificación y cuáles son los métodos adecuados.

Tengo algunas preguntas al respecto:

¿Cuál es la forma correcta de verificar los errores (entrada incorrecta, estados incorrectos, etc.)? ¿Es mejor verificar explícitamente los errores o utilizar funciones como afirmaciones que se pueden optimizar a partir de su código final? Siento que verifica explícitamente el desorden de un programa con una gran cantidad de código adicional que no debería ejecutarse en la mayoría de las situaciones de todos modos, y sin mencionar que la mayoría de los errores terminan con una falla de anulación / salida. ¿Por qué saturar una función con comprobaciones explícitas solo para abortar? He buscado afirmaciones versus verificación explícita de errores y encontré poco para explicar realmente cuándo hacerlo.

La mayoría dice 'use afirmaciones para verificar errores lógicos y usa verificaciones explícitas para verificar otras fallas'. Sin embargo, esto no parece llevarnos muy lejos. Diríamos que esto es factible:

Malloc returning null, check explictly
API user inserting odd input for functions, use asserts

¿Me mejoraría esto en la comprobación de errores? ¿Que más puedo hacer? Realmente quiero mejorar y escribir mejor, código 'profesional'.


3
Buena pregunta, pero creo que podría ser más adecuado para uno de los sitios hermanos (¿programadores?).

Gracias, no estaba seguro. Pensé que ya que estaba bastante relacionado con el código, SO habría estado bien.
Anon

3
La respuesta simple es "Por eso se inventaron las excepciones. Obtenga un mejor lenguaje".
DeadMG

1
@DeadMG: setjmp/ longjmpestán disponibles en C, por lo que no necesita un nuevo lenguaje.
usuario786653

3
@DeadMG: Alguien que no puede obtener la verificación correcta de los errores de C tiene una gran probabilidad de que en el infierno obtenga un manejo de excepciones de C ++ correcto ...
Codificador

Respuestas:


4

La forma más fácil para que yo sepa la diferencia es determinar si la condición de error se introduce en tiempo de compilación o en tiempo de ejecución. Si el problema es que un programador usa la función de manera incorrecta, haga una afirmación para llamar la atención sobre el problema, pero una vez que la solución se compila en el código de llamada, ya no tiene que preocuparse por verificarlo. Los problemas como la falta de memoria o la entrada incorrecta del usuario final no se pueden resolver en el momento de la compilación, por lo que debe dejar los controles.


2

Verifique cualquier cosa en cualquier momento (podría haber cambiado después de su última verificación) que no esté 100% bajo su comando. Y también: ¡Durante el desarrollo, incluso no confíes en ti mismo! ;-)

Okokok ... "cualquier cosa" está destinada a leerse como una comprobación de las cosas que causarían un aborto anormal o cualquier cosa que pueda hacer que su aplicación / sistema haga cosas que no debería hacer.

Para ser serios, la última parte de la última oración es esencial porque señala el problema principal:

Si desea construir un sistema estable, la principal preocupación no es lo que debe hacer el sistema, sino dejar que pueda hacer cosas tan obligatorias, uno debe ocuparse de lo que no debe hacer, incluso si "abarrota su código".


1
+1 para 'comprobar todo'. No compro el argumento del desorden de código: cualquier programador debería poder distinguir entre la comprobación de errores y la lógica real de todos modos.
stijn

2

El quid de la gestión de errores no es si y cómo atrapar el problema. Es más de lo que haces después de que te enteras .

En primer lugar, diría que no hay ninguna razón por la cual un solo error devuelto por el método subordinado está regresando no debería ser manejado. Y los errores y las excepciones son más que los valores de retorno o todos los intentos / capturas.

  1. Solo lanzar y atrapar no es suficiente.
    Vea esto : donde el autor explica que solo atrapar pero no hacer nada potencialmente suprime la excepción y, a menos que se haga lo suficiente para deshacer el daño, es peor que dejar que el código funcione así. De manera similar, simplemente escribir la declaración "log" cuando hay un archivo abierto o un error de lectura podría ayudar a encontrar la razón, pero para cuando el programa finaliza, ¡podría haber causado que los datos se dañen! No es suficiente decir que tengo muchos intentos / capturas, ¡es más importante saber lo que realmente hacen!

  2. No abuses del intento y atrapa.
    Algunas veces, la mayoría de los programadores perezosos o ingenuos piensan que después de escribir suficiente try / catch, su trabajo ha terminado y es fácil. Muy a menudo es mejor aplicar acciones correctivas y reanudar en lugar de simplemente deshacerse de todo. Si esto no se puede hacer, uno debe decidir a qué nivel necesita regresar. Dependiendo del contexto y la gravedad, intente capturar anidamiento necesita un diseño cuidadoso. Por ejemplo: vea esto y esto

  3. Defina quién es responsable:
    Una de las primeras cosas que debe hacer es definir si la entrada dada a la rutina en sí misma es solo un escenario inaceptable (o no manejado hasta ahora) o es la excepción debido al entorno (como un problema del sistema, un problema de memoria), o Es esta situación un resultado completamente interno que surge del algoritmo. En todos los casos, el nivel al que desea regresar o la acción que desea tomar difiere significativamente. Desde este punto de vista, me gustaría decir que cuando ejecuta el código en producción, hacer que abort () salga del programa es bueno, pero no para cada pequeña cosa. Si detecta daños en la memoria o falta de memoria, es definitivo que incluso después de hacer lo mejor que pueda, las cosas morirán. Pero si recibe un puntero NULL en la entrada, no lo haría

  4. Defina cuál es el mejor resultado posible:
    lo que todas las cosas deben hacerse bajo excepción es muy crítico. Por ejemplo, si en uno de nuestros casos, un reproductor de medios descubre que no tiene datos completos para ser reproducidos por el usuario, ¿qué debe hacer?

    • omita alguna parte mala y vea si puede salir adelante con cosas buenas.
    • Si esto sucede demasiado, considere si puede saltar a la siguiente canción.
    • Si descubre que no puede leer ningún archivo, deténgase y muestre algo.
    • mientras tanto
    • bajo qué estado debería un reproductor POP-UP para el usuario y
    • ¿Cuándo debería continuar por sí mismo?
    • ¿Debería "detener" las cosas para pedirle al usuario retroalimentación?
    • ¿O debería poner una pequeña nota de error discreta en algún rincón?

    Todos estos son subjetivos, y tal vez hay más formas de manejar los problemas de lo que trivialmente creemos. Todo lo anterior requiere construir y comprender la profundidad de la excepción y, además, hacer que los diferentes escenarios sean posibles para evolucionar.

  5. A veces necesitamos verificar las excepciones antes de que surjan. El ejemplo más común es el error dividir por cero. Idealmente, uno debe probar eso antes de que se produzca dicha excepción, y si ese es el caso, ¡trate de poner el valor distinto de cero más apropiado y seguir adelante en lugar de suicidarse!

  6. Limpiar. ¡Al menos esto es lo que debes hacer! Si una función abre 3 archivos y el cuarto no se abre, no hace falta decir que los primeros 3 deberían haberse cerrado. Delegar este trabajo a una capa de arriba es una mala idea. si decides no marcharte sin limpiar la memoria. Y lo más importante: incluso si ha sobrevivido a la excepción, informe a los superiores que las cosas no han tomado el curso normal.

La forma en que vemos la funcionalidad (normal) del software en términos de varias jerarquías o capas o abstracciones, de la misma manera que debemos categorizar las excepciones en función de su gravedad y el alcance bajo el cual surgen y están afectando otras partes del sistema, eso define cómo manejar excepciones tan diferentes de la mejor manera posible.

Mejor referencia: Code Craft capítulo 6 - disponible para descargar


1

La comprobación de errores solo durante las compilaciones de depuración es una MALA IDEA (tm), que se compila bajo la versión superpuesta de variables reutilizables en la pila, elimina las páginas de protección, hace dudosos trucos con cálculos, reemplaza artríticas pesadas con cambios precalculados, etc.

Utilice la comprobación de errores en la versión también, puede recurrir a algo tan simple como:

if(somethinghitthefan)
     abort();

Esto también tiene un efecto secundario muy bueno que definitivamente no ignorará el error una vez que la aplicación comience a fallar en la PC de Betta Testers.

Los espectadores y registros de eventos son completamente inútiles en comparación con abort(), ¿quién los revisa de todos modos?


salida / abortar == peor experiencia de usuario cada vez: la aplicación simplemente desaparece sin decir a qué ..
stijn

@stijn: se abortrompe en depurador / crea un volcado. exites malo si. Aunque, prefiero __asm int 3más.
Codificador

eso es cierto, y en C / C ++ tiendo a escribir afirmaciones usando __asm ​​int 3 también, pero nunca sin mostrar al menos una descripción de por qué, y preferiblemente también línea y archivo. Entonces, al menos, el cliente puede dar información sobre lo que sucedió exactamente.
2011

0

Las diversas cosas que puede hacer es
1. Leer y asimilar gran cantidad de código en línea y ver cómo se hace.
2. Usar algunas herramientas de depuración para ayudarlo a localizar regiones de errores
3. Tenga en cuenta los errores triviales debido a asignaciones incorrectas y errores de sintaxis
4. Algunos errores peores surgen debido a errores lógicos en el programa que son más difíciles de encontrar. Para esto, puede localizarlo y encontrarlo o, para los más complicados, intente hablar con la gente o usar recursos como Stackoverflow , Wikipedia , google para obtener ayuda de personas.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.