12. Código muerto, comentarios engañosos y deuda técnica visible

12.1 Objetivo del tema

En un proyecto que crece, es normal que queden restos: funciones que ya no se llaman, imports abandonados, comentarios que describen una versión vieja del código y tareas pendientes que nunca se revisan. Todo eso aumenta ruido y dificulta entender qué parte del sistema sigue siendo importante.

En este tema aprenderemos a detectar código muerto, comentarios engañosos y deuda técnica visible. También veremos cómo limpiar de forma segura usando pruebas y herramientas como Ruff.

Objetivo práctico: limpiar señales visibles de deterioro en un proyecto Python sin eliminar comportamiento necesario.

12.2 Qué es código muerto

Código muerto es código que permanece en el proyecto, pero ya no se ejecuta o no tiene efecto real. Puede aparecer como funciones no usadas, ramas imposibles, variables sobrantes, imports abandonados o bloques comentados.

def calcular_total(productos):
    subtotal = sum(
        producto["precio"] * producto["cantidad"]
        for producto in productos
    )
    descuento = 0
    return subtotal

En este ejemplo, descuento se asigna pero no se usa. Esa línea no aporta comportamiento y agrega ruido.

12.3 Por qué el código muerto es peligroso

El código muerto hace que el lector dude. Si una función existe, parece que alguien la necesita. Si un bloque comentado queda en el archivo, parece que podría volver. Esa duda aumenta el costo de mantenimiento.

También puede ocultar errores: una variable sin usar puede indicar que una regla quedó incompleta, no simplemente una línea sobrante.

El código muerto no solo ocupa espacio. También compite por la atención del lector.

12.4 Imports y variables no usadas

Ruff puede detectar muchos casos simples de código muerto.

import os
import json


def obtener_total(productos):
    cantidad = len(productos)
    return sum(producto["precio"] for producto in productos)

En este fragmento, os, json y cantidad no se usan. Ejecuta:

python -m ruff check src tests

Ruff puede marcar imports no usados y variables asignadas sin uso.

12.5 Corregir con cuidado

Si una variable no se usa, no siempre significa que haya que borrarla inmediatamente. Primero pregunta si representa una regla incompleta.

def calcular_total(productos, cliente):
    subtotal = calcular_subtotal(productos)
    descuento = obtener_descuento(cliente)
    return subtotal

Aquí descuento no se usa. Tal vez sobra, o tal vez falta aplicar el descuento. El diagnóstico requiere leer intención y pruebas.

12.6 Bloques de código comentado

El código comentado suele quedar como recuerdo de una versión anterior. En la práctica, casi siempre molesta más de lo que ayuda.

def obtener_descuento(cliente):
    if cliente == "vip":
        return 0.15
    # if cliente == "premium":
    #     return 0.20
    return 0

Si esa regla no está activa, conviene eliminar el bloque comentado. Si es una tarea pendiente real, debe registrarse de manera explícita y verificable.

12.7 Comentarios engañosos

Un comentario engañoso es peor que la falta de comentario, porque empuja al lector hacia una interpretación equivocada.

# Aplica un descuento del 10%.
def aplicar_descuento(total):
    return total * 0.85

El comentario dice 10%, pero el código aplica 15%. Una mejora es nombrar la constante y eliminar el comentario falso.

DESCUENTO_VIP = 0.15


def aplicar_descuento(total):
    return total * (1 - DESCUENTO_VIP)

12.8 Comentarios que repiten el código

Un comentario no debería repetir lo que el código ya dice.

# Incrementa el total con el costo de envío.
total += COSTO_ENVIO

Ese comentario no agrega información. Es mejor reservar comentarios para decisiones no evidentes.

# El envío se cobra aunque el producto sea digital por una regla comercial temporal.
total += COSTO_ENVIO

12.9 Comentarios TODO

Los comentarios TODO pueden ser útiles si son concretos, pero se vuelven deuda invisible cuando no tienen contexto, fecha, responsable o enlace a una tarea.

Poco útil:

TODO: arreglar esto.

Más útil:

TODO: reemplazar cálculo fijo de impuesto cuando se agregue soporte por provincia.

Si el equipo usa un sistema de tareas, suele ser mejor registrar la deuda allí y dejar el código lo más limpio posible.

12.10 Deuda técnica visible

La deuda técnica visible aparece cuando el código muestra señales claras de decisiones temporales o incompletas:

  • Funciones llamadas temporal, nuevo, viejo o fix.
  • Comentarios que dicen “por ahora”.
  • Ramas que nunca deberían ejecutarse.
  • Valores hardcodeados que deberían venir de configuración.
  • Duplicación aceptada sin explicación.

12.11 Ejemplo con deuda visible

def calcular_impuesto_temporal(pais):
    # Por ahora todos pagan esto.
    return 0.21

El problema no es solo el valor fijo. El nombre y el comentario avisan que hay una decisión temporal sin resolver. Una mejora mínima sería hacer explícita la regla actual:

IMPUESTO_PREDETERMINADO = 0.21


def obtener_impuesto(pais):
    return IMPUESTO_PREDETERMINADO

Si realmente falta una regla por país, conviene crear una tarea concreta para incorporarla.

12.12 Limpieza segura

Antes de eliminar código, conviene seguir una secuencia:

  • Ejecutar pruebas para conocer el estado inicial.
  • Detectar código no usado con herramientas.
  • Leer el contexto para confirmar que no falta una regla.
  • Eliminar una cosa por vez.
  • Ejecutar pruebas nuevamente.
python -m ruff check src tests
python -m pytest

12.13 Aplicación sobre ventas_demo

En el proyecto ventas_demo, crea temporalmente este archivo src/deuda.py:

import os


def calcular_total_temporal(productos):
    # TODO: revisar
    total = 0
    cantidad = len(productos)
    for producto in productos:
        total += producto["precio"] * producto["cantidad"]

    # total = total * 1.21
    return total

Luego ejecuta:

python -m ruff check src/deuda.py

Identifica qué puede detectar Ruff y qué requiere criterio humano.

12.14 Posible limpieza

Una limpieza posible es:

def calcular_total(productos):
    total = 0
    for producto in productos:
        total += producto["precio"] * producto["cantidad"]
    return total

Eliminamos el import no usado, la variable sin uso, el comentario impreciso y el bloque comentado. También quitamos la palabra temporal del nombre porque no aporta información útil.

12.15 Cuándo dejar una nota

No toda deuda puede resolverse en el momento. Si decides dejar una nota, debe ser concreta y accionable.

Evita:

TODO: mejorar.

Prefiere:

TODO: reemplazar impuesto fijo por tabla de impuestos por país cuando se definan las reglas fiscales.

12.16 Ejercicio guiado

Limpia el siguiente código:

import json
import os


def procesar(datos):
    # Esta función calcula el promedio
    total = 0
    contador = 0
    debug = True
    for item in datos:
        total += item["valor"]
        contador += 1
    # print(total)
    return total

Señales a revisar:

  • Imports no utilizados.
  • Comentario incorrecto: no calcula promedio, devuelve total.
  • Variable debug no usada.
  • Variable contador no usada.
  • Bloque comentado.
  • Nombre de función demasiado genérico.

12.17 Una posible solución

def calcular_total(datos):
    total = 0
    for item in datos:
        total += item["valor"]
    return total

Si la intención real era calcular promedio, entonces la solución sería diferente. Por eso primero hay que confirmar el comportamiento esperado.

12.18 Ejercicio propuesto

Busca en ventas_demo señales de código muerto o deuda visible. Realiza estas tareas:

  • Ejecuta Ruff sobre src y tests.
  • Elimina imports o variables claramente no usados.
  • Revisa comentarios que repiten o contradicen el código.
  • Convierte un TODO ambiguo en una nota concreta o elimínalo.
  • Ejecuta pruebas después de cada limpieza.
python -m ruff check src tests
python -m pytest

12.19 Lista de verificación

Antes de continuar, verifica que puedes hacer lo siguiente:

  • Reconocer código muerto en imports, variables, funciones y bloques comentados.
  • Diferenciar una línea sobrante de una regla incompleta.
  • Detectar comentarios engañosos o redundantes.
  • Escribir notas TODO concretas y accionables.
  • Usar Ruff para detectar problemas simples.
  • Limpiar de a un cambio por vez y ejecutar pruebas.

12.20 Conclusión

En este tema vimos que el código muerto, los comentarios engañosos y la deuda técnica visible aumentan ruido y reducen confianza. Limpiar estos elementos no es solo embellecer: es facilitar que el próximo cambio se haga con menos dudas.

En el próximo tema estudiaremos variables temporales innecesarias y estados intermedios confusos.