Las métricas ayudan a observar tendencias y detectar zonas de riesgo. Pero una métrica no reemplaza la lectura del código. Un número puede señalar una función sospechosa, pero el criterio humano decide si el diseño es adecuado.
En este tema veremos métricas útiles para mantenibilidad en Python, límites razonables y formas prácticas de incorporarlas sin convertirlas en reglas ciegas.
Una métrica puede medir características visibles del código:
Estas señales ayudan, pero no miden directamente claridad, intención o calidad del dominio.
El objetivo no es “tener buenos números”. El objetivo es tener código fácil de entender, modificar y probar. Una métrica debe orientar conversaciones y revisiones.
La complejidad ciclomática mide caminos de decisión. En Ruff podemos activarla con C901.
[tool.ruff.lint]
select = ["E", "F", "B", "SIM", "I", "C901"]
[tool.ruff.lint.mccabe]
max-complexity = 6
Comando:
python -m ruff check src tests
Para un proyecto de práctica, un límite entre 5 y 8 puede ser útil para detectar funciones difíciles. En proyectos reales, el límite puede ser más alto al principio si ya existe código heredado.
La cantidad de líneas no define calidad, pero una función muy larga merece revisión. Como regla práctica, si una función ocupa una pantalla completa o tiene varias etapas internas, conviene mirarla con atención.
Preguntas útiles:
Una función con muchos parámetros suele ser difícil de usar.
def generar_reporte(usuario, fecha, total, moneda, enviar_email, guardar_archivo, formato):
...
Límites orientativos:
La duplicación exacta puede detectarse con herramientas, pero la duplicación de conocimiento requiere revisión humana. Una regla repetida con pequeñas variaciones puede ser más peligrosa que líneas idénticas.
Señales:
No estamos midiendo cobertura de código en este curso, pero sí podemos pensar en cobertura conceptual: ¿las reglas importantes tienen pruebas?
Una métrica de líneas cubiertas no reemplaza esta pregunta.
La presencia de type hints ayuda a entender contratos. Puedes usar mypy como señal de calidad:
python -m mypy src
Un proyecto no necesita ser estricto desde el primer día, pero las funciones públicas y modelos de datos deberían tener anotaciones claras.
Ruff ayuda a mantener una base limpia:
python -m ruff check src tests
Un proyecto con muchos warnings acumulados tiende a normalizar problemas. Conviene mantener el conteo en cero o justificar excepciones.
Black e isort no miden diseño, pero eliminan discusiones de formato y hacen los diffs más claros.
python -m isort --check-only src tests
python -m black --check src tests
Si fallan, el problema no suele ser conceptual, pero sí afecta consistencia del proyecto.
Para un proyecto pequeño, un tablero puede ser una lista de comandos y criterios:
Ejecuta:
python -m isort --check-only src tests
python -m black --check src tests
python -m ruff check src tests
python -m mypy src
python -m pytest
Registra el resultado. Si algo falla, clasifica el problema:
Otra herramienta útil para explorar métricas es radon. Puedes instalarla:
python -m pip install radon
Medir complejidad:
python -m radon cc src -s
Medir mantenibilidad:
python -m radon mi src
Usa estos resultados como señales de revisión, no como sentencia automática.
No todos los proyectos pueden adoptar límites estrictos de inmediato. Una estrategia pragmática:
Define límites para un proyecto pequeño:
Luego ejecuta los comandos de revisión y anota qué límite falla primero.
En ventas_demo, realiza estas tareas:
python -m ruff check src tests
python -m mypy src
python -m pytest
Antes de continuar, verifica que puedes hacer lo siguiente:
En este tema vimos que las métricas ayudan a detectar zonas de riesgo, pero no reemplazan el criterio técnico. Un buen equipo usa números para orientar preguntas, no para evitar pensar.
En el próximo tema cerraremos el curso con un caso práctico integrador: análisis y mejora de un proyecto Python con code smells.