¿El código de depuración debe dejarse en su lugar, siempre, o agregarse solo cuando se depura y eliminar cuando se ha encontrado el error?

35

Yo, por mi parte, solo agrego código de depuración (como las declaraciones de impresión) cuando estoy tratando de localizar un error. Y una vez que lo he encontrado, elimino el código de depuración (y agrego un caso de prueba que prueba específicamente ese error). Siento que está abarrotando el código real y, por lo tanto, no tiene lugar allí a menos que esté depurando.

¿Cómo lo haces? ¿Dejas el código de depuración en su lugar o lo eliminas cuando está obsoleto (lo que puede ser difícil de juzgar cuando es así)?

gablin
fuente

Respuestas:

30

Deben sacarse las declaraciones de impresión de depuración; sin embargo, si necesita agregarlos para depurar un problema de producción, puede valer la pena considerar si tiene suficiente información en su marco de registro. La información sobre parámetros, condiciones de error, etc. puede ser útil más adelante cuando aparezca el siguiente error. El uso de un buen marco de registro que puede tener depuración o seguimiento de mensajes de registro activados dinámicamente puede ser muy útil en la naturaleza.

Alarmante
fuente
55
+1 Principalmente por mencionar tener un marco de depuración sensible en su lugar. Si esto está en su lugar inicialmente, y hay varios niveles de depuración, entonces el código de producción puede ejecutarse sin necesidad de recurrir a costosas rutinas de depuración, y el código de desarrollo puede ejecutarse con el nivel de escrutinio que se requiera, ojalá se registre de la forma que se desee.
Orbling
1
De acuerdo con Orbling. Y además, para el código de depuración que no sea únicamente la visualización de información que tuvo un impacto en el rendimiento u otra razón no adecuada para la producción. (por ejemplo, una afirmación sobre el resultado de la función, por ejemplo, comprobar el resultado de una ordenación), puede considerar dos modos de objetivo de compilación. modo de depuración y modo de liberación.
Zekta Chan
16

El código agregado específicamente para la depuración debe eliminarse del software de producción.

Si esto es una eliminación completa o si se coloca en secciones de compilación condicional (como en C / C ++ / C #) depende de usted y de su estándar de codificación.

Hay un número de razones para esto:

  1. Puede haber implicaciones de seguridad si este código se ejecuta o alguien puede acceder a su salida.
  2. Podría ralentizar la aplicación.
  3. Puede ser confuso para otros desarrolladores que miran el código (o de hecho usted mismo) 6 meses después.
ChrisF
fuente
+1 para la compilación condicional, pero los bloques de comentarios funcionarán en idiomas que no los admiten. Nunca debe dejarlo compilado en una versión prod, pero a veces es excesivamente ineficiente seguir eliminándolo por completo cada vez que desee eliminar una compilación de lanzamiento.
Bill
1
He trabajado en entornos donde el código C / C ++ siempre se compiló con opciones de depuración en caso de que el código de producción necesitara ser depurado o examinado un coredump. A veces, este mandato siempre listo para depurar requería dejar las declaraciones de depuración para poder activarlas con un indicador sin volver a compilar el código. Java siempre permite la depuración si las opciones de JVM están configuradas para ello, por lo que se requiere relativamente menos trabajo de preparación para depurar las cosas más adelante.
Michael Shopsin
16

ChrisF y Alaric tienen puntos válidos; +1 para ellos. Puedo identificar al menos 5 tipos diferentes de código de depuración que uso.

  1. Usar registros para volcar el estado del sistema en un momento específico.

    void function(...)
    {
        ...dump everything i know about.
    }
    
  2. Uso de registros para puntos de control de ejecución.

    void function(...)
    {
        ...got here 1
        ...got here 2
    }
    
  3. Código que realmente obliga a cierta condición a ser cierta, pero rompe el comportamiento normal. Ejemplo:

    • Supongamos que tiene algunos registros sobre un error, pero no puede reproducir el problema. Puede intentar escribir código que obligue a ciertas variables a tener ciertos valores que coincidan con la información en el registro.
  4. Registro de verificación: clasificaría esto como un registro detallado que se puede utilizar para validar la corrección del software que no debe incluirse en la producción, como validar los pasos individuales de un algoritmo, por ejemplo.

  5. Registro de operaciones: consulte la publicación de Alaric . Eso es más o menos lo que quiero decir con "registro de operaciones".

1, 2 y 3 se deben sacar por completo. Algo así como 4 probablemente compilaría condicionalmente del código. Para 5, Alaric tenía un gran punto sobre poder apagar dinámicamente los registros. Eso puede abordar el punto de ChrisF en su segunda viñeta para la mayoría de los casos.

Pemdas
fuente
1
Este es un buen resumen. Sin embargo, sería mejor si pudiera formatearlo correctamente reemplazando 1)... con 1.... (para que el formato Markdown lo tome como una lista) y sangrar el código de ejemplo con 8 espacios (nuevamente, para que Markdown lo tome como ejemplo código dentro de una lista).
Konrad Rudolph
@Konrad Rudolph: Hecho.
gablin
3

Depende de lo que esté haciendo el código. Parte del código que se utiliza para la depuración se puede dejar como está, y parte se debe eliminar.

El código que verifica la cordura de los parámetros en un método no siempre es útil una vez que el código funciona correctamente, pero a menudo se mantiene para asegurarse de que el código continúe funcionando correctamente.

A veces, escribe el código de manera diferente para facilitar la depuración del código, por ejemplo, calcular un valor y ponerlo en una variable local, y luego usar la variable en la siguiente línea, lo que facilita verificar el resultado del cálculo cuando se realiza un solo paso a través del código. Podría reescribir el código para usar el valor calculado directamente, pero el costo de usar la variable local es tan pequeño (si es que lo hay) que hay pocas razones para reescribir el código. Además, hay un punto en dejar el código sin cambios una vez que lo haya probado, siempre existe un pequeño riesgo de que introduzca un error al cambiarlo.

El código que agrega solo para rastrear un error específico a menudo se puede eliminar después de haber encontrado el error.

Guffa
fuente
2

Érase una vez, solía usar mucho código de depuración. Estaba apuntando casi por completo a Windows, por lo que había mucha de esta función de salida de cadena de depuración que ya no recuerdo cómo deletrear, para poder capturar la traza con un programa en particular.

Algunos códigos de depuración permanecieron en su lugar, cosas particulares que estaban destinadas a anidar llamadas. Sin embargo, a pesar de que la cadena de depuración en su mayoría no sería visible en un sistema de producción, todavía se hizo todo bajo compilación condicional.

Sin embargo, la realidad es que todo ese código de depuración fue un gran esfuerzo para algo que se maneja idealmente de una manera diferente: usar, por supuesto, un depurador. En ese momento, no estaba tan impresionado con el depurador Borland C ++. Las herramientas estaban allí, pero con demasiada frecuencia daban resultados engañosos, y usar el depurador no IDE (a menudo necesario) significaba memorizar teclas de acceso directo, lo que significaba una distracción del trabajo en cuestión.

La única experiencia de depuración que he encontrado que es peor es la línea de comandos GDB.

Ser un experto con las herramientas que usa todos los días es, por supuesto, importante, pero la depuración realmente no debería ser algo que haga todos los días. Si usa el depurador con tanta frecuencia que está de acuerdo con aprender docenas de comandos y / o atajos de teclado, eso me parece un poco rojo.

Sin embargo, cuando estaba trabajando en Visual Studio 7, estaba claro que la depuración podría ser muy práctica y efectiva. Si puede depurar en Visual Studio (incluidas las ediciones exprés), la depuración es muy sencilla. Sin duda, si puede encontrar la interfaz gráfica de usuario / IDE correcta, GDB también es fácil y efectivo, aunque todavía no he hecho esa búsqueda.

También hay algo que decir para las pruebas unitarias, con análisis de cobertura utilizando gcov. Cuanto más confiado esté en el comportamiento de sus bibliotecas, menos profunda será su depuración, y menos frecuentemente necesitará el depurador en primer lugar. Y escribir pruebas unitarias es razonablemente algo que debería hacer la mayoría de los días.

Herramienta inesperadamente importante = cmake, una herramienta de compilación que me permite cambiar fácilmente entre compilar para GCC y para VC ++, entre otras cosas. Entonces puedo hacer mi prueba de unidad y cobertura basada en gcov usando GCC, pero cambiar fácilmente a VC ++ para usar el depurador.

Steve314
fuente
Un depurador puede ser bastante inútil si no es peligroso en aplicaciones de subprocesos múltiples, pero me gusta su comentario de bandera roja.
Pemdas
@Pemdas: todavía no he tenido un problema grave en ese sentido, aunque el subprocesamiento múltiple obviamente no es apto para depuradores. Aun así, creo que las herramientas adecuadas probablemente sean una mejor solución que el código de depuración en principio. Una herramienta de análisis estático que puede detectar condiciones de carrera, puntos muertos, condiciones en las que dos subprocesos pueden luchar por la misma memoria / recurso al mismo tiempo, etc., sería bueno. No tengo idea de lo que está disponible en ese sentido, aunque sí sé que existen algunas herramientas inteligentes. klee, por ejemplo, no lo entiendo, pero la descripción básica suena muy impresionante.
Steve314
"Creo que las herramientas adecuadas probablemente sean una mejor solución que el código de depuración en principio". Esa es una declaración peligrosa;). Tener herramientas que realicen parte del análisis puede ser bueno, pero me preocupa que los desarrolladores, especialmente los nuevos, comiencen a depender demasiado de las herramientas, como alguien que necesita usar una calculadora para calcular qué es el 15% de 100.
Pemdas
Depender demasiado de las herramientas que aún no he investigado parece poco probable. En su ejemplo de calculadora, sí, pero aún usaré OpenOffice Calc en lugar de escribir mi propia hoja de cálculo simple. Hay un momento para el código de depuración (incluso con un depurador, por ejemplo, su propio caso de creación de condiciones extrañas), pero si va más allá de cierto punto, las herramientas existentes ganan. Y cuando se trata de restar el 15% de 115, también usaré esa calculadora, lo que mucha gente daría ya que la respuesta obvia (100) es incorrecta. En multihilo, obviamente las respuestas correctas son infames porque a veces resultan ser incorrectas.
Steve314
1

Mi opinión al respecto: el código de depuración utilizado para eliminar un error dentro del código en cuestión generalmente lo elimino por completo. Código de depuración utilizado para eliminar un error resultante de fuerzas externas. Generalmente, simplemente comento.

Loren Pechtel
fuente
-1

Si el error proviene de la prueba de la unidad o de la unidad interna, el código de depuración podría eliminarse por completo. Pero si el error proviene de la producción, es mejor que el código de depuración esté allí dentro de las etiquetas de compilación. Ponerlo dentro de las etiquetas de compilación ayudará a los otros desarrolladores a comprender que este código es solo para fines de depuración.

Manoj R
fuente
-1

Utilizar TDD , por lo que su código de prueba siempre tiene un lugar donde incluso se mantiene.

dukeofgaming
fuente
¿Cómo responde esto a la pregunta que se hace?
mosquito
Porque TDD lo lleva a "depurar" o probar el código que no tiene que eliminar.
dukeofgaming
No te sigo lo siento. ¿Como es eso?
mosquito