wandres.dev
NIVEL DIOS · Síntesis y el método de depuración

Cuándo dejar de depurar y volver a leer el código

Las seis señales de que la sesión ha dejado de avanzar, qué hacer en cada caso, y por qué leer el código con calma es a veces la decisión más rápida.

⏱ 17 min

Hay un punto en toda sesión difícil a partir del cual seguir mirando paneles deja de rendir y empieza a costar. Reconocer ese punto es una habilidad concreta y poco discutida, porque la cultura de la profesión premia la persistencia y no distingue entre insistir con método e insistir por inercia. Esta lección es sobre la segunda: las señales de que has dejado de avanzar y qué hacer con cada una.

🎯 Al terminar esta lección sabrás
  • Reconocer las seis señales de que la sesión ha dejado de progresar.
  • Aplicar la acción correspondiente a cada señal.
  • Ejecutar el protocolo de reinicio cuando el estado está contaminado.
  • Justificar cuándo leer el código es más rápido que seguir midiendo.

Las seis señales

Uno: llevas más de veinte minutos sin descartar nada. El indicador más fiable de todos. Depurar bien es un proceso de eliminación, y si el espacio de hipótesis no se ha reducido en veinte minutos, no estás depurando: estás mirando. Comprueba cuántas hipótesis tenías al empezar y cuántas tienes ahora; si el número es el mismo, para.

Dos: has cambiado más de tres cosas sin volver al estado limpio. El sistema que tienes delante ya no es el que falla; es una mezcla de tu investigación y del problema. Cualquier observación sobre él es sospechosa.

Tres: estás repitiendo comprobaciones. Si te descubres haciendo algo que ya hiciste hace media hora, has perdido el hilo de lo descartado. Es la señal de que necesitas un registro escrito, y de que la sesión lleva demasiado tiempo.

Cuatro: tu hipótesis actual no explica el síntoma completo. Explica el ochenta por ciento y hay un detalle que no encaja, y llevas un rato ignorándolo. Ese detalle es el bug. Una hipótesis que no explica todo está mal, no incompleta.

Cinco: has empezado a decir que es imposible. “Esto no puede estar pasando” significa que uno de tus supuestos es falso, no que la realidad se equivoque. La lista de supuestos ocultos es el sitio donde mirar, y no un panel.

Seis: estás cansado. No es una señal blanda: el juicio para elegir qué comprobar se degrada mucho antes que la capacidad de teclear, y una sesión de tres horas seguidas produce decisiones peores que dos de una hora con un descanso.

⚠️
Cuidado

La cuarta señal es la que más veces se ignora y la que más caro sale. Cuando una explicación deja fuera un detalle, lo habitual es archivar ese detalle como “una rareza” o “eso será otra cosa”. Casi nunca es otra cosa: es la parte del mecanismo que todavía no entiendes, y suele ser precisamente la parte que hace que el bug sea difícil.

Qué hacer con cada señal

Señal Acción
Veinte minutos sin descartar Escribir la lista de hipótesis vivas y elegir la más barata de matar
Estado contaminado Reiniciar por completo, ver protocolo abajo
Repitiendo comprobaciones Abrir un registro escrito y anotar lo descartado antes de seguir
La hipótesis no explica todo Volver al detalle que no encaja y hacerlo el centro
“Es imposible” Listar los supuestos y comprobar el más obvio
Cansancio Parar. Media hora fuera o al día siguiente

El protocolo de reinicio

Cuando el estado está contaminado, seguir es contraproducente. El reinicio completo cuesta dos minutos y devuelve la sesión a un punto sólido.

Cierra las DevTools y vuelve a abrirlas. Desactiva todas las emulaciones, ralentizaciones y overlays que hayas dejado puestos.

Ventana de incógnito nueva. Sin extensiones, sin almacenamiento, sin service workers.

Recarga forzada y comprueba que el síntoma sigue ahí. Si no está, la información es valiosa: el problema depende del estado.

Vuelve a leer tu descripción del síntoma, la de la primera fase. Después de dos horas, es fácil haber derivado a investigar algo que no era el problema original.

// Reinicio de sesion: deja el origen como recien visitado
(async () => {
  const informe = {};

  const registros = await navigator.serviceWorker?.getRegistrations?.() ?? [];
  informe.serviceWorkers = registros.length;
  await Promise.all(registros.map(r => r.unregister()));

  const nombres = await caches.keys();
  informe.caches = nombres.length;
  await Promise.all(nombres.map(n => caches.delete(n)));

  informe.localStorage = localStorage.length;
  informe.sessionStorage = sessionStorage.length;
  localStorage.clear();
  sessionStorage.clear();

  const bases = await indexedDB.databases?.() ?? [];
  informe.indexedDB = bases.length;
  await Promise.all(bases.map(b => new Promise(res => {
    const req = indexedDB.deleteDatabase(b.name);
    req.onsuccess = req.onerror = req.onblocked = () => res();
  })));

  // Las cookies del propio dominio legibles desde JavaScript
  const cookies = document.cookie ? document.cookie.split('; ') : [];
  informe.cookies = cookies.length;
  for (const c of cookies) {
    const nombre = c.split('=')[0];
    document.cookie = nombre + '=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/';
  }

  console.table([informe]);
  console.log('Estado eliminado. Recarga y comprueba si el sintoma sigue.');
  console.log('Si ha desaparecido, el problema depende del estado persistente.');
})();

Ese reinicio es además un experimento por sí mismo: si el síntoma desaparece, acabas de descartar el código entero y de señalar el estado, que es una bisección enorme por dos minutos de trabajo.

Por qué leer el código puede ser más rápido

Hay una asimetría que la cultura de la depuración interactiva tiende a ignorar: las herramientas son muy buenas mostrando qué pasa y bastante malas mostrando qué debería pasar. Un panel te enseña el valor que tiene una variable; no te enseña qué valor tendría que tener, ni por qué, ni qué invariante se ha roto. Esa información está en el código y en la cabeza de quien lo escribió.

Por eso hay tres tipos de problema donde leer gana claramente a medir.

Los de lógica. Una condición mal formulada, un operador invertido, un caso límite no contemplado. Se ven leyendo en un minuto y se persiguen con el depurador durante una hora, porque el depurador enseña que el flujo va por la rama equivocada sin decir por qué la rama está mal.

Los de concurrencia. Dos operaciones que compiten. Aquí el depurador es activamente dañino: parar la ejecución cambia los tiempos y hace desaparecer la carrera. Razonar sobre el orden posible de los eventos, leyendo, es lo único que funciona.

Los de contrato. Dos partes del sistema que suponen cosas distintas sobre el formato de un dato, sobre quién limpia qué o sobre cuándo se puede llamar a algo. El síntoma aparece muy lejos de la causa, y la causa es un malentendido entre dos ficheros que solo se ve leyéndolos juntos.

La regla práctica: si has localizado la zona y no entiendes el mecanismo, deja de medir y ponte a leer. La medición sirve para acotar; la comprensión viene de leer. Y una vez tienes una hipótesis de la lectura, vuelves a la herramienta para confirmarla, que es su mejor uso.

Parar es una decisión activa, y explicarle el problema a alguien es la técnica más eficaz que existe

Merece la pena cerrar con la técnica que más bugs difíciles resuelve por unidad de esfuerzo y que no requiere ninguna herramienta: explicar el problema en voz alta a otra persona. El fenómeno es conocido y su explicación es concreta. Depurar durante horas construye en la cabeza un modelo del problema lleno de saltos que uno ya no percibe: cosas que se dan por comprobadas y solo se supusieron, pasos del razonamiento que se apoyan en una observación de hace dos horas que quizá no significaba lo que parecía, supuestos heredados de la primera hipótesis y nunca revisados. Explicar obliga a linealizar ese modelo, y en cuanto hay que decir en voz alta “y entonces la respuesta llega y el componente se actualiza”, el propio hablante oye el hueco: ¿seguro que se actualiza? ¿lo has comprobado o lo estás suponiendo? Una fracción muy alta de estas explicaciones se interrumpen a media frase con la solución, y el interlocutor no ha dicho nada. Por eso funciona igual de bien contárselo a alguien que no entiende el sistema, o escribirlo. Y de ahí sale una recomendación operativa muy concreta que conviene adoptar como norma personal: cuando lleves una hora atascado, escribe el problema como si fueras a pedir ayuda. Con el síntoma exacto, lo que has descartado, tu hipótesis actual y por qué no encaja. Escribir ese mensaje cuesta cinco minutos y lo resuelve solo una buena parte de las veces; y las que no, tienes un mensaje excelente que mandar, en lugar de un “no me funciona” que obligará a otra persona a hacerte las mismas preguntas que deberías haberte hecho tú. La consecuencia cultural, para un equipo: normalizar pedir ayuda pronto es una decisión de eficiencia y no de orgullo. Dos horas de una persona atascada cuestan más que quince minutos de dos, y la profesión tiene una tendencia bien documentada a considerar lo contrario.