El 9 de septiembre de 1947, el equipo que operaba el Mark II en la Universidad de Harvard —del que formaba parte una joven Grace Hopper— encontró una polilla real atrapada entre los contactos del relé 70. La pegaron en el cuaderno de bitácora con la anotación "first actual case of bug being found" (primer caso real de un bug encontrado). Esa página, con la polilla incluida, se conserva hoy en el Smithsonian. El término "bug" ya se usaba antes en ingeniería, pero ese cuaderno es el origen documentado de por qué a cazar errores en el código lo llamamos "debuggear".
Casi 80 años después, seguimos haciendo básicamente lo mismo: buscar la causa de un comportamiento inesperado. La diferencia es que hoy existen técnicas y herramientas mucho más eficientes que revisar relé por relé, y usarlas bien es lo que separa una sesión de debugging de 10 minutos de una de tres horas.
Por qué "probar cosas al azar" es la forma más lenta de debuggear
El instinto más común ante un bug es cambiar algo, ejecutar de nuevo y ver si se arregló. Funciona a veces, pero es la forma más lenta de resolver un problema porque no genera información: si el cambio no funciona, no sabes por qué, y si funciona, tampoco sabes por qué exactamente.
Debuggear de forma sistemática empieza por un paso que se salta con demasiada frecuencia: reproducir el bug de la forma más pequeña y controlada posible. Antes de tocar una sola línea, vale la pena reducir el caso a lo mínimo indispensable para que el error aparezca de forma consistente. Un bug que "a veces pasa" es mucho más difícil de arreglar que uno que puedes disparar cada vez que quieras.
Técnicas que realmente funcionan
No hace falta dominarlas todas para cada bug — la clave está en saber cuál usar según el tipo de problema.
Logging o "print debugging": añadir mensajes que muestran el valor de una variable o el punto exacto por el que pasa la ejecución. Es la técnica más rápida de aplicar y funciona en cualquier lenguaje, aunque para bugs complejos obliga a añadir y quitar código repetidamente.
Breakpoints y ejecución paso a paso: pausar el programa en un punto exacto e inspeccionar el estado real de las variables en ese momento, en lugar de imaginarlo. Es más lento de configurar que un log, pero permite explorar el estado completo del programa sin adivinar de antemano qué variable hay que imprimir.
Rubber duck debugging: explicar el problema en voz alta, línea por línea, a alguien (o a un objeto inanimado, de ahí el nombre). Suena poco serio, pero obliga a verbalizar cada supuesto que se está dando por hecho sin comprobar, que es precisamente donde suelen esconderse los bugs más tontos.
Bisección binaria (git bisect): cuando un bug "apareció en algún momento" pero no se sabe en qué commit, en vez de revisar el historial commit a commit, se prueba el punto medio entre el último commit bueno conocido y el actual, y se repite dividiendo el rango a la mitad. Con un historial de 1000 commits, localizar el culpable lleva unas 10 pruebas en vez de cientos.
Leer el stack trace de abajo hacia arriba: el error que se muestra arriba suele ser la consecuencia, no la causa. La línea donde realmente empezó el problema casi siempre está más abajo en la traza, en el punto donde el código entra por primera vez en terreno de la aplicación en vez de en código de librerías.
Qué herramienta usar según dónde programes
Cada ecosistema tiene su propio debugger integrado, y merece la pena aprender el de tu stack principal en vez de depender solo de logs:
JavaScript / web: las Chrome DevTools incluyen un debugger completo (pestaña "Sources") con breakpoints condicionales —que solo se activan si una expresión es cierta, útil para bugs que solo pasan en la iteración 500 de un bucle— y "watch expressions" para vigilar variables concretas mientras se avanza paso a paso.
Cualquier lenguaje en VS Code: el editor trae un debugger integrado que, con la extensión adecuada, funciona igual de bien para Python, Node.js, Java, C# o Go: breakpoints con clic en el margen, panel de variables en tiempo real y consola para evaluar expresiones sin parar la ejecución.
Python: además del debugger de VS Code, la librería estándar incluye pdb, accesible añadiendo breakpoint() en cualquier línea del código, sin instalar nada adicional — útil cuando se depura directamente en una terminal remota o un contenedor sin interfaz gráfica.
Tres hábitos que ahorran horas
- Cambia una sola cosa a la vez. Si se modifican tres cosas y el bug desaparece, no se sabe cuál de las tres lo arregló — ni si de verdad se entendió el problema o solo se dejó de ver.
- Verifica los supuestos, no los des por hechos. "Esa función nunca devuelve null" es la frase que precede a la mitad de los bugs de producción. Si algo "debería" ser cierto, comprobarlo cuesta un log; asumirlo sin comprobar puede costar una tarde entera.
- Anota lo que ya se descartó. En sesiones largas es fácil volver a comprobar lo mismo dos veces sin darse cuenta. Una lista corta de "esto ya lo comprobé y no era esto" ahorra dar vueltas en círculo.
Debuggear no deja de tener algo de detectivesco, casi 80 años después de aquella polilla en el Mark II: no se trata de tener suerte probando cosas, sino de reducir el espacio de búsqueda hasta que solo quede una explicación posible.
Fuentes:






Comentarios (0)
Deja un comentario
No hay comentarios aún. ¡Sé el primero en comentar!