DesarrolloBásico

Debug

Proceso de identificar, analizar y corregir errores (bugs) en el código. Una habilidad fundamental para todo desarrollador.

Pronunciación

/diːˈbʌɡ/
"di-bag"
Escuchar en:Forvo Cambridge

Qué es

Debug (o debugging) es el proceso sistemático de encontrar y corregir errores en el código. El nombre viene de “de-bug” = quitar bugs.

Incluye:

  1. Reproducir el problema
  2. Aislar la causa raíz
  3. Entender por qué ocurre
  4. Corregir el código
  5. Verificar que la solución funciona

Errores comunes de pronunciación

  • ❌ “de-bug” (la ‘e’ no suena como ‘e’ española)
  • ❌ “deboog” (la ‘u’ suena como ‘a’ corta)

Variantes:

  • Debug (verbo): “I need to debug this”
  • Debugging (sustantivo/gerundio): “Debugging is an art”
  • Debugger (herramienta): “Open the debugger”

Técnicas de Debugging

1. Print Debugging (La más básica)

function calcularTotal(items) {
  console.log('Items recibidos:', items);  // 👈 Debug

  let total = 0;
  for (const item of items) {
    console.log('Procesando item:', item);  // 👈 Debug
    total += item.precio;
    console.log('Total parcial:', total);   // 👈 Debug
  }

  console.log('Total final:', total);  // 👈 Debug
  return total;
}

Pros: Rápido, funciona en cualquier lado Contras: Hay que limpiar después, no permite pausa

2. Debugger con Breakpoints (La más poderosa)

function calcularTotal(items) {
  debugger;  // 👈 El código se pausará aquí

  let total = 0;
  for (const item of items) {
    total += item.precio;  // Puedes poner breakpoint aquí
  }

  return total;
}

Pros: Inspeccionar variables en vivo, ejecutar paso a paso Contras: Requiere conocer la herramienta

3. Logging Estructurado (La más profesional)

import logger from './logger';

function calcularTotal(items) {
  logger.debug('Iniciando cálculo', { itemCount: items.length });

  try {
    const total = items.reduce((sum, item) => sum + item.precio, 0);
    logger.info('Cálculo completado', { total });
    return total;
  } catch (error) {
    logger.error('Error en cálculo', { error, items });
    throw error;
  }
}

Pros: Persistente, searchable, no modifica comportamiento Contras: Más setup inicial

El Proceso de Debugging

┌─────────────────────────────────────────────────────────────┐
│                    CICLO DE DEBUGGING                        │
├─────────────────────────────────────────────────────────────┤
│                                                              │
│    1. REPRODUCIR     2. HIPÓTESIS      3. PROBAR            │
│    ┌───────────┐     ┌───────────┐     ┌───────────┐        │
│    │ ¿Siempre  │  →  │ ¿Qué puede│  →  │Agregar    │        │
│    │ falla?    │     │ causar    │     │logs o     │        │
│    │ ¿Cuándo?  │     │ esto?     │     │breakpoints│        │
│    └───────────┘     └───────────┘     └───────────┘        │
│          ↑                                    ↓              │
│          │                                    │              │
│    6. VERIFICAR      5. CORREGIR       4. ANALIZAR          │
│    ┌───────────┐     ┌───────────┐     ┌───────────┐        │
│    │ ¿El fix   │  ←  │ Modificar │  ←  │ ¿La       │        │
│    │ funciona? │     │ el código │     │ hipótesis │        │
│    │ ¿Sin      │     │           │     │ era       │        │
│    │ regresión?│     │           │     │ correcta? │        │
│    └───────────┘     └───────────┘     └───────────┘        │
│                                                              │
└─────────────────────────────────────────────────────────────┘

Herramientas de Debug por Lenguaje

Lenguaje Herramienta Comando/Atajo
JavaScript Chrome DevTools F12 → Sources
Python pdb / debugpy breakpoint() (Python 3.7+)
Java IntelliJ Debugger Shift+F9
C# Visual Studio F5
Node.js VS Code Debugger F5
React React DevTools Extensión Chrome

Caso Práctico: Debuggeando un Login

El problema

“Los usuarios no pueden iniciar sesión. El formulario no hace nada al enviar.”

Paso 1: Reproducir

// Intentar login y observar en consola
form.addEventListener('submit', handleLogin);

Paso 2: Agregar logs estratégicos

async function handleLogin(event) {
  console.log('1. Evento submit disparado');  // ¿Se ejecuta?

  event.preventDefault();
  console.log('2. preventDefault ejecutado');

  const email = document.getElementById('email').value;
  const password = document.getElementById('password').value;
  console.log('3. Datos:', { email, password: '***' });

  try {
    console.log('4. Enviando request...');
    // El frontend corre en http://localhost:5173 y la API en otro origen
    const response = await fetch('http://localhost:3000/api/login', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ email, password })
    });
    console.log('5. Response:', response.status);

    const data = await response.json();
    console.log('6. Data:', data);

  } catch (error) {
    console.error('7. Error:', error);  // 🐛 ¡Aquí está!
  }
}

Paso 3: Encontrar el bug

Consola:
1. Evento submit disparado
2. preventDefault ejecutado
3. Datos: { email: "user@test.com", password: "***" }
4. Enviando request...
7. Error: TypeError: Failed to fetch  // 🐛 ¡ENCONTRADO!

Paso 4: Investigar más

// "Failed to fetch" indica un problema de red o de CORS.
// En DevTools → Console/Network aparece:
// "blocked by CORS policy: No 'Access-Control-Allow-Origin' header"
// El navegador bloquea la respuesta porque el backend (otro origen)
// no autoriza al origen del frontend.

Paso 5: Corregir

// backend/server.js (Express) - permitir el origen del frontend
import cors from 'cors';

app.use(cors({ origin: 'http://localhost:5173' }));  // 🔧 El fix va en el backend

// Alternativa en desarrollo: un proxy del dev server (p. ej. Vite)
// para que frontend y API compartan origen.

Técnicas Avanzadas

Rubber Duck Debugging

Explícale el problema a un objeto (como un pato de hule). Al verbalizar el problema, frecuentemente encuentras la solución.

Binary Search Debugging

Si tienes un bug en 1000 líneas de código:

  1. Comenta la mitad (líneas 500-1000)
  2. ¿El bug persiste? → Está en líneas 1-500
  3. Comenta la mitad de ese rango
  4. Repite hasta encontrar la línea exacta

Con Git, git bisect aplica la misma idea sobre el historial: encuentra el commit que introdujo el bug.

Time-Travel Debugging

Algunas herramientas permiten “retroceder en el tiempo”:

  • Redux DevTools (JavaScript)
  • rr (C/C++)
  • Time Travel Debugging de WinDbg (Windows)

Anti-patrones de Debugging

Anti-patrón Problema Mejor práctica
Cambios random “Pruebo esto a ver si funciona” Formular hipótesis primero
Ignorar el stack trace Buscar en Google sin leer el error Leer el mensaje completo
No reproducir primero Asumir que sabes el problema Siempre reproducir primero
Debuggear en producción Modificar código live Usar staging/local
No escribir tests El bug vuelve después Agregar test que falla antes del fix

El Mantra del Debugger

"No adivines. Observa."
"Si no puedes reproducirlo, no puedes arreglarlo."
"El código hace exactamente lo que le dijiste, no lo que querías."

Términos relacionados

  • Bug - El error que estamos buscando
  • Breakpoint - Punto donde pausamos la ejecución
  • Stack Trace - Rastro de llamadas hasta el error
  • Logging - Registro de eventos para análisis

Recuerda: Debugging es una habilidad que mejora con práctica. Los mejores debuggers no son los que más saben, sino los que mejor preguntan y observan.