Ilustración conceptual de la inspección de un límite de ancho en un filtro de puertas.

Depurar código: seguir los datos en lugar de adivinar el fallo

Una puerta mide exactamente el mínimo que admite la regla y, aun así, desaparece de la selección. El programa no lanza ninguna excepción. Simplemente entrega un resultado incorrecto con la serenidad de quien no tiene que defenderlo en una reunión. Cambiar números al azar hasta que vuelva a salir la puerta sería una respuesta rápida. También una forma bastante ambiciosa de sustituir el diagnóstico por superstición.

Vamos a localizar el punto en el que el resultado deja de coincidir con lo esperado. Usaremos tres puertas ficticias, una regla de ancho inclusiva y el depurador que incluye Python. Después veremos la corrección equivalente en C#. La cuestión no es recorrer todas las líneas por obligación: es detenernos donde una pregunta concreta pueda distinguir entre dos explicaciones del fallo. Me han reservado una entrega para enseñar a mirar qué está haciendo el programa. Preferiría considerar innecesario el encargo; los botones que funcionan «casi siempre» me impiden ese consuelo.

Tabla de contenidos

Define la respuesta correcta antes de investigar la obtenida

El requisito del ejemplo es admitir puertas cuyo ancho sea mayor o igual que 0.80 metros. El límite es didáctico, sin valor normativo, y las tres entradas ya están expresadas en metros. P01 mide 0.90, P02 mide 0.80 y P03 mide 0.70. Por tanto, la selección esperada contiene P01 y P02; P03 debe quedar fuera. Sin esa expectativa sería difícil afirmar que el resultado del filtro está mal.

Este primer archivo contiene deliberadamente el defecto que vamos a investigar. Guárdalo como revisar_puertas.py y ejecútalo con Python 3.12. El comportamiento incorrecto forma parte del ejercicio: no es la versión que debemos conservar al terminar.

				
					def cumple_ancho(puerta, minimo_m):
    return puerta["ancho_m"] > minimo_m

puertas = [{"id": "P01", "ancho_m": 0.90}, {"id": "P02", "ancho_m": 0.80},
           {"id": "P03", "ancho_m": 0.70}]
minimo_m = 0.80
seleccionadas = [p["id"] for p in puertas if cumple_ancho(p, minimo_m)]
print(seleccionadas)
				
			

La salida es ['P01']. Ahora tenemos una divergencia concreta: falta P02. No necesitamos un proyecto con quinientas puertas para reproducirla. Mantener la entrada que queda por encima, la que coincide y la que está por debajo nos permite separar el comportamiento del límite del resto del filtro. Reducir el caso no significa borrar detalles hasta que desaparezca el error; significa conservar los que lo producen y retirar ruido.

Un primer diagnóstico razonable podría preguntar si P02 llegó al recorrido, si su ancho utiliza otra unidad o si la comparación excluye la igualdad. Son hipótesis diferentes y cada una propone una observación. La mala costumbre consiste en empezar por una solución —multiplicar el ancho, cambiar el catálogo, añadir otro if— sin haber comprobado cuál de esas hipótesis describe el programa que estamos ejecutando.

La ausencia de una excepción tampoco es una prueba de corrección. En el artículo sobre errores tratamos fallos que interrumpen una operación; aquí la operación es perfectamente ejecutable y responde a una condición equivocada. El depurador ayuda a observar esa ejecución, pero el requisito sigue viniendo de fuera del código. Ninguna herramienta puede deducir por nosotros qué significaba «mínimo admitido» en el encargo.

Detén la ejecución donde se decide el destino de P02

Abre una terminal en la carpeta del archivo y ejecuta el siguiente comando. Si tu instalación utiliza python3 o el lanzador py, adapta el nombre del ejecutable. pdb pertenece a la biblioteca estándar: este ejercicio no necesita instalar una extensión de editor.

				
					python -m pdb revisar_puertas.py
				
			

En el indicador (Pdb), introduce estas órdenes de una en una. La primera fija una pausa en la línea 2 solo cuando la puerta sea P02. Esa línea corresponde al archivo exacto anterior, sin añadir instrucciones delante. c continúa hasta la pausa y las órdenes p muestran los valores o resultados que queremos contrastar.

				
					b 2, puerta["id"] == "P02"
c
p puerta
p minimo_m
p puerta["ancho_m"] > minimo_m
p puerta["ancho_m"] >= minimo_m
c
q
				
			

En esa pausa verás el registro de P02, el mínimo 0.8, False para la comparación estricta y True para la inclusiva. Al continuar, el programa todavía imprimirá la selección defectuosa: mirar una expresión no sustituye la instrucción del archivo. La documentación de pdb describe estas órdenes y la continuación de la sesión tras terminar el programa.

La observación resuelve dos hipótesis: P02 sí llega a la función y ambos números corresponden al límite previsto. El primer punto que explica su exclusión es la comparación estricta. No estamos viendo una diferencia accidental de redondeo entre dos cálculos: en estos datos asignamos el mismo literal 0.80 al ancho de P02 y al mínimo. Los problemas de tolerancia de medidas requieren su propio contrato; añadir una tolerancia aquí ocultaría la causa que acabamos de encontrar.

Inspecciona datos sin convertir la pausa en otra ejecución distinta

Un depurador permite examinar variables, recorrer llamadas y avanzar paso a paso. Lo importante es que cada observación responda a una pregunta. Si la entrada es correcta al entrar en una función y el resultado sale mal, el siguiente tramo que investigar está dentro de ella. Si ya llega mal, seguir repasando su comparación no va a reparar la transformación anterior. Buscamos la primera divergencia relevante, no el lugar donde por fin nos hemos dado cuenta de ella.

Las expresiones que evaluamos también merecen cuidado. En este caso consultamos un diccionario y comparamos números, sin modificar los datos. En otros programas, llamar a una función desde una ventana de inspección puede ejecutar trabajo, cambiar estado o provocar otra petición. No utilizaría la pausa para invocar escrituras ni operaciones externas como si fuesen una vista inofensiva. Observar debe ayudarnos a entender la ejecución original, no fabricar otra que solo existe dentro del depurador.

Avanzar sobre una llamada permite comprobar qué devuelve; entrar en ella permite investigar su implementación. Escoger entre ambas acciones depende de dónde esté la duda. Si conocemos y hemos probado una función auxiliar, recorrer sus veinte instrucciones en cada vuelta añade tiempo sin información. En cambio, saltarnos precisamente la transformación sospechosa porque «eso seguro que está bien» es una excelente manera de conservar el fallo y nuestra autoestima en el mismo sitio.

Las trazas temporales también pueden servir cuando no podemos pausar el proceso. Para este filtro bastaría registrar identificador, ancho, mínimo y decisión. El mensaje debe permitir comparar esos valores, no limitarse a «he entrado aquí». Evita volcar objetos completos sin revisar su contenido: un informe de diagnóstico necesita contexto útil, no una copia de todos los datos que la aplicación maneja.

Corrige el operador y conserva el caso que lo demostró

La corrección es utilizar >=, porque el requisito admite la igualdad. Esta es la versión final completa: sustituye el contenido de revisar_puertas.py por el siguiente bloque y ejecútalo. Conservamos las mismas puertas y el mismo mínimo para comprobar el efecto de una sola decisión.

				
					def cumple_ancho(puerta, minimo_m):
    return puerta["ancho_m"] >= minimo_m

puertas = [{"id": "P01", "ancho_m": 0.90}, {"id": "P02", "ancho_m": 0.80},
           {"id": "P03", "ancho_m": 0.70}]
minimo_m = 0.80
seleccionadas = [p["id"] for p in puertas if cumple_ancho(p, minimo_m)]
print(seleccionadas)
				
			

La salida pasa a ser ['P01', 'P02']. P03 sigue excluida. Comprobarla también importa: una modificación que añadiese siempre P02 por su identificador arreglaría la muestra de forma absurda sin reparar la regla. La solución debe explicar tanto la entrada que fallaba como las que ya respondían correctamente.

En C# podemos expresar la versión final con las mismas tres puertas. Este archivo completo se ejecuta en una consola de .NET 8 y produce P01, P02. La lista guarda los identificadores seleccionados; la función conserva la decisión de ancho separada de la presentación.

				
					using System;
using System.Collections.Generic;

var puertas = new (string Id, double AnchoM)[]
{
    ("P01", 0.90), ("P02", 0.80), ("P03", 0.70)
};
double minimoM = 0.80;
var seleccionadas = new List<string>();
foreach (var puerta in puertas)
    if (CumpleAncho(puerta, minimoM)) seleccionadas.Add(puerta.Id);
Console.WriteLine(string.Join(", ", seleccionadas));

static bool CumpleAncho((string Id, double AnchoM) puerta, double minimoM)
{
    return puerta.AnchoM >= minimoM;
}
				
			

Si utilizas Visual Studio, puedes detenerte en el retorno e inspeccionar puerta.AnchoM y minimoM, con una condición para puerta.Id == "P02". La guía de puntos de interrupción explica ese mecanismo. La sesión reproducida aquí es la de pdb; el programa C# permite contrastar la regla equivalente sin atribuir a esta explicación una prueba dentro de Revit o de una sesión gráfica concreta.

Una corrección necesita una comprobación que sobreviva al diagnóstico

El depurador nos ha permitido localizar el defecto, pero no conservará por sí solo la expectativa del caso límite. Una prueba automatizada debe dejar escrito que 0.80 se admite cuando el mínimo es 0.80, además de comprobar los valores por encima y por debajo. Así podremos detectar si una modificación futura recupera accidentalmente el operador estricto. Depurar explica un fallo; probar ayuda a reconocer que vuelve a aparecer.

En un proceso BIM, el recorrido previo podría incluir selección de fase, lectura de parámetros, conversión de unidades y filtrado. Registrar en qué punto desaparece un identificador permite separar esos tramos. No empezaría investigando la API de escritura si el elemento ya se ha perdido antes de preparar la propuesta. El resultado final concentra muchos pasos; la causa suele necesitar una pregunta más pequeña.

Antes de dar por cerrado un diagnóstico, conserva la entrada mínima, la expectativa, la primera decisión divergente y el resultado tras corregirla. No hace falta convertir ese registro en una novela del sufrimiento del desarrollador. Sí hace falta poder explicar por qué la modificación resuelve el requisito sin depender de que «ahora parece que funciona».

Prueba a cambiar el mínimo a 0.90: P01 debe quedar admitida y las otras dos fuera. Si puedes predecir ese resultado y localizar la comparación que lo produce, ya tienes una forma de investigar el filtro. Mi prestigio sobrevivirá a haber explicado cómo mirar dos números. Me preocupa bastante más el del programa que necesite tres ajustes misteriosos para decidir si uno es mayor o igual que otro.

Artículos relacionados

Respuestas

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *