¿Cuál es el beneficio de evitar el uso de un depurador?

101

A lo largo de mi carrera, he notado que algunos desarrolladores no usan herramientas de depuración, pero sí comprueban el código erróneo para descubrir cuál es el problema.

Si bien muchas veces poder encontrar rápidamente errores en el código sin un depurador es una buena habilidad, parece que es menos productivo pasar mucho tiempo buscando problemas cuando un depurador encuentra fácilmente pequeños errores como errores tipográficos.

¿Es posible administrar un complejo sin un depurador? ¿Es aconsejable? ¿Qué beneficios están ahí para ser tenido mediante el uso de " depuración psíquica ?"

jonathan
fuente
19
Hola, Jonathan, he revisado tu pregunta para evitar las trampas de una diatriba y mantener la pregunta abierta: creo que, como está redactado ahora, es una pregunta bastante decente y que se puede responder.
Ejemplo: considere un código a = 6/3., En su lugar, por error tipográfico que ha escrito a = 6/2... Ahora está buscando en el nivel de mnemotecnia., Las instrucciones ADD, JMP y luego descubre que hubo una iteración adicional en lugar de 2., luego se da cuenta de que el divisor tiene un error tipográfico Ahora puedes inferir cuán ridículo es usar siempre un depurador.
EAGER_STUDENT

Respuestas:

153

Lo que parece adivinar desde el exterior a menudo resulta ser lo que yo llamo "depuración en tu mente". En cierto modo, esto es similar a la capacidad de los grandes maestros para jugar ajedrez sin mirar un tablero de ajedrez.

Es, con mucho, la técnica de depuración más eficiente que conozco, porque no requiere un depurador en absoluto. Su cerebro explora múltiples rutas de código al mismo tiempo, produciendo un mejor cambio de lo que podría obtener con un depurador.

No era consciente de esta técnica antes de entrar brevemente en el mundo de la programación competitiva , donde usar un depurador significaba perder preciosos segundos. Después de aproximadamente un año de competencia, comencé a usar esta técnica casi exclusivamente como mi línea de defensa inicial, seguido por el registro de depuración, con el uso de un depurador real sentado en el distante tercer lugar. Un efecto secundario útil de esta práctica fue que comencé a agregar nuevos errores a un ritmo más lento, porque la "depuración en mi mente" no se detuvo cuando escribí el nuevo código.

Por supuesto, este método tiene sus limitaciones, debido principalmente a las limitaciones de la mente para visualizar múltiples caminos a través del código. Aprendí a respetar estas limitaciones de mi mente, recurriendo a un depurador para corregir errores en algoritmos más avanzados.

revs dasblinkenlight
fuente
27
+1 Encuentro que "programar adivinando" es una frase cargada. No hay sustituto para pensar. Lo que el OP no explica es qué tan efectiva es la "adivinanza". Mi duda es que es puramente adivinar (es decir, enfoque de espagueti en la pared), sino más bien usar razonamiento deductivo. Los depuradores tienen su lugar, pero no son una panacea para el razonamiento deductivo y simplemente para comprender el código.
Bill el
8
@DJClayworth Eso no es del todo exacto: a veces intentar usar un depurador es una mala elección, incluso si tiene un buen depurador a su disposición: termina perdiendo mucho tiempo sin lograr mucho. Un caso que me viene a la mente de inmediato es resolver problemas de concurrencia; los otros están depurando algoritmos recursivos con altos factores de ramificación, algunos algoritmos de programación dinámica y rutinas de servicio de interrupción de hardware. Por supuesto, es una tontería no usar un depurador cuando realmente lo necesita, pero decidir cuándo comenzar a necesitar un depurador es una opción altamente individual.
dasblinkenlight
99
+1 aunque encuentro un depurador invaluable para ciertos tipos de error (particularmente en algoritmos más complejos) realmente no hay sustituto para simplemente tener una buena comprensión del código
Chris Browne
77
@DJClayworth Decidí deliberadamente una afirmación más fuerte que "algunas veces cuando no usar un depurador es mejor": mi breve encuentro con la programación competitiva me enseñó que buscar instintivamente un depurador no es el comportamiento más eficiente para mí . En estos días empiezo por (1) releer rápidamente el código y (2) examinar el seguimiento de depuración (cuando esté disponible) antes de (3) buscar un depurador. En muchos casos, el tercer paso es innecesario, porque veo el problema en los pasos (1) o (2), escribo una prueba unitaria que reproduce el problema y codifico una solución, todo sin usar un depurador.
dasblinkenlight
10
Creo que lo que realmente quiere decir es que un programador debe tener una secuencia de depuración , en lugar de hacer clic en el botón mágico "buscar error". Un depurador es una herramienta extremadamente poderosa, pero no enciende la motosierra para recortar los setos.
Spencer Rathbun
41

Cuanto más conozco una base de código, menos necesito un depurador (pero aún verificaría el error informado, es una pista importante en cualquier razonamiento).

Es una buena herramienta para comprender algunos comportamientos dinámicos de complejidad pequeña a mediana, pero a menudo descubro que me enfoca en los detalles en lugar de en el panorama general. Y después de un tiempo, ahí es donde están los problemas: en interacciones de alcance más amplio cuyo comportamiento dinámico tiende a ser más fácil de entender con otras herramientas (registro de entradas y salidas en los límites del módulo, por ejemplo).

Un programador
fuente
35

Puede que no sean malos programadores, pero probablemente son solucionadores de problemas terriblemente ineficientes.

Tiendo a seguir los consejos de Depuración: las 9 reglas indispensables para encontrar incluso los problemas de software y hardware más difíciles de alcanzar (David Agans), y este cae directamente bajo la guía de "Dejar de pensar y mirar"

JohnFx
fuente
12
No estoy de acuerdo, aunque no votaré en contra. Como dice delnan, si puede comprender lo que está haciendo el código, puede ser más rápido detectar lo que está haciendo mal que pasar por el depurador e intentar encontrar cuándo sale mal. Dicho esto, un desarrollador que se niega a usar un depurador cuando no puede identificar el problema al leer el código está cometiendo un gran error.
@Mark más la ventaja adicional de diagnosticar mal el problema y enchufar un nuevo defecto.
Keith trae el
11
@ Mark Bannister: veo lo que estás diciendo. Permítanme enmendar eso, si ha estado buscando el problema en el código durante más de 15 minutos, abandone y use el depurador y no sea terco.
JohnFx
99
Creo que un buen programador no debería depender del depurador. Esto no le debe impedir el uso de una inmediatamente (cuando estén disponibles), una vez que su visión no - o periódicamente, para asegurarse de que su visión es todavía en camino ...
comingstorm
1
@mark a menos que esté trabajando en una base de código muy pequeña, creo que es imposible entender cada línea de código. El 95% de mis errores actuales se resuelven de la manera que usted describe, pero los más difíciles son donde necesita el depurador.
wobbily_col
31

Cualquier trabajo requiere el uso de las herramientas adecuadas de la manera correcta. Si tiene un depurador, úselo para ver qué está sucediendo realmente. La mayoría de los errores son causados ​​por suposiciones.

He trabajado con desarrolladores que se niegan a usar depuradores porque lo sabían mejor. La respuesta clásica que obtuve una vez fue "el accidente no está siendo causado por mí, pasé todo el día inspeccionando el código [donde estaba fallando] y no hay nada malo". (¿Qué pasa con ese valor nulo que se leyó desde el DB?) El jefe pareció pensar que era una gran respuesta, pero el cliente no lo hizo.

Salí de ese equipo lo más rápido que pude. Su propósito era hacer el trabajo y convertir un simple problema de 10 minutos en un problema que parece estar ocupado todo el día.

jqa
fuente
18
+1 "La mayoría de los errores son causados ​​por suposiciones" son palabras muy sabias
ZJR
15
Supongo que todos los errores son causados ​​por suposiciones. (¿Ves lo que hice allí? = P)
dan_waterworth
44
@ ZJR: Por eso assertes tan genial. Comprueba tus suposiciones. Revísalos a menudo.
Zan Lynx
@dan_waterworth: No es cierto. Por un lado, podría ser un error tipográfico.
Thomas Eding
13

Su mejor guía para la práctica de la depuración es el libro Code Complete de Steve McConnel . El Capítulo 23 cubre la depuración en detalle, y voy a extraer algunos puntos de él.

  1. Comprender el problema es importante, y el uso del depurador no lo sustituye.
  2. Adivinar es un mal enfoque para la depuración. Si sus colegas realmente utilizan conjeturas, en lugar de pensar en el problema, entonces están haciendo un mal trabajo. Adivinar significa pegar declaraciones de impresión aleatorias en el código y esperar encontrar algo útil.
  3. Si sus colegas realmente no saben cómo usar un depurador (en lugar de elegir no usar uno), entonces sí, son incompetentes, al igual que alguien que no conoce la sintaxis del lenguaje que se supone que están usando.
DJClayworth
fuente
2
Aunque estoy de acuerdo contigo en la mayoría de tus publicaciones, creo que incompetente es injusto. Es posible desarrollar sin el uso de un depurador, es simplemente ineficiente. ¡Algunas personas aprenden sobre depuradores antes que otros!
ChrisFletcher
No arrojaría casualmente palabras como "incompetente". Conozco a alguien que depura completamente con declaraciones impresas, y nadie más se acerca a hacer la contribución que hace.
Mike Dunlavey
2
@MikeDunlavey ¿Esa persona sabe cómo usar un depurador y elige no usarlo? Multa. Si no lo saben, entonces mantengo mi declaración.
DJClayworth
2
Párate como quieras, podría llegar un momento en que ese adjetivo se te pueda aplicar. Entonces lo entenderás: son cosas del patio de la escuela.
Mike Dunlavey
9

Difícil de decir. La depuración adivinando podría funcionar si ya tiene una idea sobre cuál es el error (valor incorrecto pasado a una función de biblioteca, posiblemente SQL no válido, etc.). Admito que lo hago a veces cuando el error en sí parece pequeño u obvio, como "buffer de caracteres demasiado pequeño": el seguimiento de la pila me muestra la línea que falló y no necesito un depurador para resolverlo.

Hacer esto todo el tiempo puede ser contraproducente y si las primeras "conjeturas" fallan, adivinar es probablemente la estrategia de resolución de problemas incorrecta y debería llamarse a un depurador real. Normalmente, diría que no hay absolutamente nada de malo en usar el depurador .

Dicho esto, he trabajado con herramientas y entornos en los que el depurador era tan difícil de hacer bien, o tan mínimo e inútil que, por desgracia, adivinar era a menudo un mejor enfoque. He trabajado con algunas herramientas propietarias que ni siquiera tenían depuradores adecuados. Supongo que es posible que si una persona trabajara en tales entornos demasiado tiempo, eventualmente perdería su confianza en los depuradores y confiaría soley en el enfoque de adivinanzas.

FrustratedWithFormsDesigner
fuente
8

Me sorprende que la discusión sobre este tema no haya mencionado las "pruebas unitarias".

Como realizo un desarrollo basado en pruebas, no paso mucho tiempo en el depurador. Hace 10 años, solía pasar diligentemente por el depurador:

  1. Después de escribir un código para asegurarse de que funcionó y
  2. Cuando recibí un informe de error para intentar diagnosticar el problema

Lo que he encontrado después de 10 años de desarrollo basado en pruebas es que soy mucho más productivo como programador si:

  1. Escribo pruebas unitarias antes de escribir el código para asegurarme de que lo escribí correctamente
  2. Escribo pruebas unitarias inmediatamente después de recibir un informe de error para intentar duplicar y profundizar en el problema.

Permitir que la computadora ejecute el código y valide el resultado es miles de veces más rápido de lo que puedo pensar o recorrer el código para validar mentalmente los resultados, y no comete errores.

Todavía tengo que pasar por el depurador de vez en cuando, y todavía estoy involucrado en el análisis mental del código ... pero solo en raras ocasiones, y principalmente para un código muy complicado.

Jeff Grover
fuente
+1 A menudo es más rápido agregar una declaración de impresión y volver a ejecutar la prueba y luego usar un depurador.
Winston Ewert
@ winston: a menudo es más rápido iniciar el depurador que escribir varias declaraciones de impresión hasta que encuentre la ubicación del código problemático. Todo depende. Los problemas simples generalmente se resuelven más rápidamente de la manera que usted describe, pero los problemas complejos son donde necesita el depurador. Ser capaz de usar ambos es mejor que adherirse estrictamente a cualquier principio absoluto.
wobbily_col
7

Personalmente, trato de minimizar el uso de un depurador:

  • usando verificadores estáticos y opciones de compilación similares que sugieren posibles fuentes de errores simplemente analizando el código
  • escribir código con el menor número de efectos secundarios posible, en el estilo más funcional posible, eliminando el estado mutable donde sea posible
  • escribir pruebas unitarias con la mínima granularidad razonable
  • no tragar excepciones

Por supuesto, todos cometen errores, por lo que incluso al componer programas de esta manera, si una prueba falla, utilizo el depurador para inspeccionar un valor de una expresión intermedia. Pero al adherirse a los principios anteriores, el defecto es más fácil de localizar, y la depuración no significa un proceso doloroso e indeterminado.

thSoft
fuente
6

Use el depurador siempre que sea posible. El depurador simplemente solucionará el problema (mira, no verificamos este valor), o proporcionará una gran cantidad de contexto que es útil al analizar el código relevante (wow, la pila está totalmente desordenada, voy a es un problema de desbordamiento del búfer).

Kevin Hsu
fuente
5

La depuración es una herramienta muy útil para inspeccionar el estado de los objetos y variables en su código en tiempo de ejecución.

Como se mencionó anteriormente en las respuestas anteriores, la depuración es extremadamente útil, pero hay algunos casos en los que es limitada.

En mi experiencia, encuentro que usar el depurador es muy útil porque ayuda a revelar suposiciones falsas que estaba haciendo sobre el estado de mi código. Algunas personas no son tan astutas al leer el código para encontrar un error, por lo que la depuración puede ayudar a revelar suposiciones falsas que usted u otro desarrollador hicieron sobre el estado del código.

Tal vez espere que un parámetro nunca sea nulo cuando se pasa a un método, por lo que nunca verifica ese caso y continúa en el método como si ese parámetro nunca fuera nulo. La realidad es que el parámetro será llegar a ser nula en algún momento incluso si se establece como condición previa para el método que el parámetro no debe ser nulo. Siempre sucederá.

En contraste con la utilidad de los depuradores en los ejemplos antes mencionados, me resulta difícil y de alguna manera no útil usar cuando se trata de subprocesos múltiples (es decir, concurrencia, procesamiento asincrónico). Puede ayudar, pero es fácil perder su orientación en la niebla de varios subprocesos cuando los puntos de interrupción del depurador se tocan en un hilo en el punto A y en un hilo completamente separado en el punto B. El desarrollador se ve obligado a empujar el nuevo punto de ruptura " proceso de pensamiento "en la parte superior de la" pila "de su cerebro y orientarse al código en el punto del nuevo punto de interrupción. Después de que disminuye la relevancia del punto de interrupción B, el desarrollador vuelve al primer punto de interrupción y tiene que recordar lo que estaba buscando antes del desencadenante del punto de interrupción B. Sé que esta puede ser una explicación confusa,

Además, la imprevisibilidad del código concurrente puede distraer aún más al desarrollador al depurar el código concurrente.

En conclusión, en mi sincera opinión:

  • Depuración cuando se usa concurrencia = mayor tendencia a perder el foco del "patrón de pensamiento de depuración"

y

  • en cualquier otro momento = mayor productividad de depuración b / c su atención no se ve interrumpida por puntos de interrupción inesperados (inesperados debido a las condiciones de la carrera).
TrueLifeCoder
fuente
2
+1 para plantear el problema de la depuración en entornos concurrentes, donde la utilidad de los depuradores tradicionales a menudo disminuye a casi cero.
dasblinkenlight
4

Creo que están siendo demasiado duros. Personalmente, cuando me encuentro con un error, vuelvo a verificar el código, trato de rastrearlo en mi mente desde la lógica del programa, porque eso a veces me ayuda a descubrir otros problemas o efectos secundarios más fácilmente que simplemente usar el debbuger y corregir el error donde se manifiesta. .

Incluso cuando creo que lo he clavado, generalmente lo depuro para asegurarme de que tengo razón. Cuando el problema es un poco más complejo, creo que la depuración es absolutamente esencial.

Además ... solo mi opinión, pero no hay excusa para no aprovechar de manera decente las herramientas que un IDE moderno puede aportar. Si le ayuda a completar su trabajo más rápido y de manera más confiable, debe usarlo.

pcalcao
fuente
4

Odio generalizar, pero muchos programadores que he conocido piensan que solo hay una forma de resolver un problema (a su manera). Es fácil suponer que se han pensado todas las pruebas posibles. Una perspectiva diferente puede ser muy valiosa.

La programación por prueba y error puede generar nuevos enfoques excelentes y detectar cosas que otros han pasado por alto.

La desventaja, generalmente toma mucho más tiempo.

usuario977645
fuente
4

Erm, depende de la persona. Personalmente, yo no uso mucho los depuradores. Cuando programo microcontroladores, básicamente uso LED o escribo datos en EEPROM para "depurar" el código que contiene. Yo no uso JTAG.

Cuando programo software para PC o servidores, tiendo a utilizar el registro y mucha salida de consola. Para lenguajes de estilo C, uso directivas de preprocesador, y en Java utilizo niveles de registro.

Como no uso depuradores, ¿diría que estoy haciendo algo mal? Son los trabajos de los editores, para mostrarme dónde tengo errores sintácticos, y cuando hay un error lógico, solo tengo que ejecutar pruebas.

polemon
fuente
4

Hay una diferencia entre no necesitar usar un depurador y no saber cómo (o negarse a) usar un depurador. El depurador es solo una de las muchas herramientas que se pueden usar para rastrear y corregir errores. He trabajado con desarrolladores que pueden descifrarlo en la cabeza y otros que piensan que pueden.

La mejor combinación es escribir su código para que sea fácil de probar mediante pruebas unitarias y registrar los errores. Entonces, espera no tener que mirar los registros o usar el depurador. Es como comprar un seguro. Es de esperar que nunca necesite usarlo, pero una vez que se encuentra con un error que no se puede resolver volviendo a verificar el código, es demasiado tarde para agregar el manejo / registro de errores adecuado, las pruebas unitarias o aprender a usar un depurador.

Diferentes herramientas / plataformas favorecen diferentes técnicas de depuración (depurador, registro, pruebas unitarias, etc.) Siempre que un desarrollador esté familiarizado con algunas de las técnicas para su plataforma / herramienta, además de simplemente volver a verificar el código, entonces pueden ser un desarrollador experto, pero si solo tienen un truco a la hora de depurar, eventualmente se encontrarán con un error que no pueden encontrar o solucionar.

Jim McKeeth
fuente
4

¡Muchas respuestas, pero ninguna mención sobre Heisenbug ?!?!

Los errores de Heisen se producen porque los intentos comunes de depurar un programa, como insertar instrucciones de salida o ejecutarlo en un depurador, generalmente modifican el código, cambian las direcciones de memoria de las variables y el momento de su ejecución.

Uso depurador, solo en el peor de los casos (para errores difíciles de encontrar). Además, según las mejores prácticas de las que muchos aclamados desarrolladores / evaluadores han estado hablando, es bueno probar el código a fondo. De esa manera, puede cubrir la mayoría de los problemas y, por lo tanto, no habría necesidad de usar el depurador.

bchetty
fuente
3

Leí un argumento en contra de la depuración del depurador aquí recientemente (¿o fue StackOverflow?). Debería tener casos de prueba contra su código. Si sus pruebas pasan, su depuración probablemente no va a ejercer el error (suposición: depurará con datos similares a los datos de su prueba).

Por otro lado, el registro es obligatorio. Si pasa las pruebas y se implementa en producción, es posible que tenga un error. La evidencia del error es de algo que sucedió en el pasado. es decir, alguien dice: "¿Cómo llegó eso allí?" Si no tiene buenos registros, nunca encontrará la causa. Incluso un depurador puede ser inútil en ese punto porque no sabes cómo se veían los datos que realmente ejercieron el error. Debe poder depurar la aplicación desde los registros.

Desafortunadamente, estoy parafraseando un poco, y puede estar haciendo un mal servicio al argumento original. En particular, la posición de "Hay importantes asistentes de depuración para dedicar tiempo de desarrollo al soporte" podría ser ortogonal a la importancia de los depuradores. Pero la parte sobre la dificultad de establecer el estado del sistema en una configuración que hace que la depuración sea útil para encontrar errores me pareció algo en lo que pensar.

ccoakley
fuente
3

Con buenas pruebas unitarias y excepciones que le proporcionan la traza inversa, rara vez tiene que usar un depurador.

La última vez que utilicé una depuración fue cuando obtuve un archivo central en alguna aplicación heredada.

¿Estoy siendo un "secuaz debutante" o estos tipos están siendo "demasiado duros"?

Ninguno. Son personas que les gusta hacer su vida más difícil de lo que debería ser.

BЈовић
fuente
2

La depuración es solo una herramienta que un buen desarrollador debe usar de manera competente.

Ciertamente, a veces puede saber de memoria dónde puede estar el error si conoce la base del código. Pero también puede perder todo un día o una semana para encontrar un error molesto con solo mirar el código.

En lenguajes de tipo dinámico sin algún tipo de depuración (incluso si solo se trata de descargar valores en la consola), a veces es imposible adivinar.

Entonces, para responder a su pregunta, tal vez sean programadores brillantes, pero sus habilidades para la resolución de problemas y su habilidad para cazar errores son malas.

Christian P
fuente
2

Depende del alcance de un problema. Si el programa es pequeño y las cosas están bien divididas, probablemente pueda resolverlo mirando. Si el programa tiene 4.5 millones de líneas de código desarrolladas por un equipo de más de 100 personas en el transcurso de varios años, ciertos errores serán imposibles de detectar.

El en cuestión en dicho programa (en C) fue una sobrescritura de memoria. El depurador con un punto de interrupción de memoria identificó la línea de código infractora tan pronto como apareció el error. Pero en este caso no hay forma de que alguien pueda haber leído y retenido los 4.5 millones de líneas de código para identificar el punto en el que alguien escribió más allá de su matriz (además, tendrían que haber conocido el diseño de tiempo de ejecución de la memoria para el estado del programa gigantesco unos 10 minutos en una larga serie de entradas para llegar a ese punto).

Punto a destacar: en pequeños programas o cosas que están altamente modularizadas, puede escapar sin un depurador. Si el programa es realmente grande y complejo, entonces el depurador puede ahorrarle mucho tiempo. Como han dicho otros, es una herramienta, y tiene sus situaciones en las que sobresale por encima de cualquier otro método, y otras en las que no es la mejor opción.

luego
fuente
0

Si el error ocurre en la computadora de un cliente, o en una computadora cuyo entorno es muy diferente al suyo, entonces configurar un depurador / depurador remoto es engorroso. Entonces, para el día frío donde obtienes un error del campo, la respuesta de 'pero ... no tengo un depurador' no ayuda. Por lo tanto, debe desarrollar un conjunto de habilidades para solucionar problemas y encontrar el error solo mediante la comprensión del código y los archivos de registro.

yarony
fuente
-1

Qué tontería: "Los programadores reales no necesitan depuradores". También podría decir que un programador real no necesita ningún IDE, solo dame un bloc de notas y un lápiz opaco. El depurador es una herramienta como cualquier otra que ayuda a la productividad.

Además, tenga en cuenta que no todas las personas encargadas del código de depuración están familiarizadas con ese código en cuestión. Muchos contratistas de tiempo entran en un entorno donde solo tienen un ideal general de lo que está sucediendo. Incluso se les puede dar una descripción detallada de un entorno, o un mapa de esquema de 20 años y una guía de convenciones de nombres arcanos (intente comprender la diferencia entre la tabla X1234 y la tabla X4312 con los campos F1, F2 y F3 [sí, basura como esta existe] cuando eres nuevo), pero muchas veces esa descripción es incorrecta; de lo contrario, ¿por qué hay un error "misterioso"?

Como alguien nuevo en un entorno, puede pasar horas o días mapeando y "conocer" una gran base de datos para un área problemática que puede solucionar y que nunca más tendrá que revisar. Esta es una gran pérdida de tiempo y dinero. Si tiene acceso al depurador, verá lo que está sucediendo, corríjalo y desaparecerá en cuestión de minutos. Todo este chillido de "no necesitas depuradores" es simplemente hinchazón elitista.

H Greene
fuente
2
Este hombre de paja no responde la pregunta que se hace, en ninguna parte hay una declaración "Los programadores reales no necesitan depuradores"
mosquito