Para estudiar calidad de código necesitamos algo más útil que ejemplos sueltos. En este tema construiremos un pequeño proyecto Python que usaremos como laboratorio durante el curso. El proyecto tendrá código que funciona, pero que presenta problemas intencionales de legibilidad, diseño y mantenibilidad.
La idea es trabajar como ocurre muchas veces en proyectos reales: recibimos código existente, necesitamos entenderlo, proteger su comportamiento y luego mejorarlo paso a paso.
Abre una terminal y crea una carpeta para las prácticas:
mkdir curso-calidad-codigo
cd curso-calidad-codigo
Dentro de esta carpeta crearemos un proyecto llamado ventas_demo. Será una aplicación pequeña para calcular totales de ventas con descuentos, impuestos y comisiones.
mkdir ventas_demo
cd ventas_demo
Un entorno virtual permite instalar herramientas para este proyecto sin afectar otros trabajos de Python. Desde la carpeta ventas_demo, ejecuta:
python -m venv .venv
En Windows PowerShell, actívalo con:
.venv\Scripts\Activate.ps1
En Linux o macOS:
source .venv/bin/activate
Cuando el entorno está activo, normalmente aparece (.venv) al comienzo de la línea de comandos.
Por ahora instalaremos pytest para ejecutar pruebas de caracterización. Más adelante agregaremos herramientas de formato, linting, tipado y métricas.
python -m pip install --upgrade pip
python -m pip install pytest
Verifica la instalación:
python -m pytest --version
Crea estas carpetas y archivos:
mkdir src
mkdir tests
New-Item src\ventas.py
New-Item tests\test_ventas.py
New-Item README.md
New-Item pyproject.toml
En Linux o macOS puedes usar:
mkdir src tests
touch src/ventas.py tests/test_ventas.py README.md pyproject.toml
La estructura debería quedar así:
ventas_demo/
|-- .venv/
|-- README.md
|-- pyproject.toml
|-- src/
| `-- ventas.py
`-- tests/
`-- test_ventas.py
El archivo pyproject.toml permite centralizar configuración del proyecto. Por ahora lo usaremos para indicar datos básicos y configurar pytest.
[project]
name = "ventas-demo"
version = "0.1.0"
description = "Proyecto de práctica para calidad de código y code smells"
requires-python = ">=3.10"
[tool.pytest.ini_options]
pythonpath = ["src"]
testpaths = ["tests"]
La opción pythonpath = ["src"] permite importar módulos desde la carpeta src durante las pruebas.
Ahora escribiremos una primera versión de src/ventas.py. El código tiene varios problemas de calidad a propósito. No lo corrijas todavía; lo usaremos para practicar análisis.
def proc(items, cliente, pais):
t = 0
for x in items:
if x["cant"] > 0:
t = t + x["precio"] * x["cant"]
if cliente == "vip":
t = t - (t * 0.15)
else:
if cliente == "regular":
t = t - (t * 0.05)
if pais == "AR":
t = t + (t * 0.21)
else:
if pais == "UY":
t = t + (t * 0.22)
else:
t = t + (t * 0.19)
if t < 10000:
t = t + 1500
return round(t, 2)
Este código calcula un total, pero presenta nombres pobres, valores mágicos, condicionales anidados y demasiadas responsabilidades en una sola función.
Agrega temporalmente estas líneas al final de src/ventas.py para ver el resultado:
items = [
{"precio": 3000, "cant": 2},
{"precio": 1500, "cant": 1},
]
print(proc(items, "vip", "AR"))
Ejecuta:
python src/ventas.py
Luego elimina esas líneas temporales. En un proyecto ordenado evitaremos dejar ejemplos manuales mezclados con la lógica principal.
En tests/test_ventas.py escribiremos pruebas que registren el comportamiento actual de la función. Estas pruebas nos servirán como red de seguridad cuando empecemos a mejorar el código.
from ventas import proc
def test_calcula_total_para_cliente_vip_en_argentina():
items = [
{"precio": 3000, "cant": 2},
{"precio": 1500, "cant": 1},
]
assert proc(items, "vip", "AR") == 9213.75
def test_agrega_envio_cuando_el_total_es_bajo():
items = [
{"precio": 1000, "cant": 1},
]
assert proc(items, "regular", "UY") == 2659.0
def test_ignora_items_con_cantidad_cero_o_negativa():
items = [
{"precio": 3000, "cant": 1},
{"precio": 9000, "cant": 0},
{"precio": 9000, "cant": -2},
]
assert proc(items, "nuevo", "CL") == 5070.0
Ejecuta las pruebas:
python -m pytest
Si todo está bien, las tres pruebas deben pasar.
En README.md escribe una descripción breve. No hace falta documentar todo, pero sí conviene dejar claro para qué existe el proyecto.
# Ventas Demo
Proyecto de práctica para analizar calidad de código y code smells en Python.
El módulo inicial contiene código que funciona, pero tiene problemas intencionales
de legibilidad, nombres, responsabilidades, condicionales y valores mágicos.
Durante el curso se irá mejorando el diseño sin cambiar el comportamiento esperado.
Antes de usar herramientas automáticas, realiza una lectura manual de src/ventas.py. Anota los problemas que encuentres. Por ejemplo:
proc no comunica qué proceso realiza.t y x obligan a deducir su significado.cant es una abreviatura que puede confundirse.Este análisis manual es importante. Las herramientas ayudan, pero no reemplazan el criterio del programador.
Puede ser tentador mejorar el código de inmediato, pero en este tema solo estamos preparando el laboratorio. No cambiaremos aún la función proc, porque primero queremos tener una base común para practicar los próximos temas.
Agrega una cuarta prueba de caracterización para el caso de un cliente "regular" en Uruguay con dos productos. Puedes usar estos datos:
items = [
{"precio": 2000, "cant": 2},
{"precio": 1000, "cant": 3},
]
Calcula el resultado esperado manualmente o ejecutando la función una vez. Luego deja ese resultado fijo en la prueba. Después ejecuta:
python -m pytest
La prueba debe pasar junto con las anteriores.
Antes de continuar con el próximo tema, verifica lo siguiente:
ventas_demo tiene carpetas src y tests.pytest está instalado en el entorno virtual.pyproject.toml configura pythonpath y testpaths.src/ventas.py contiene código con problemas intencionales.tests/test_ventas.py pasan correctamente.ventas.py.En este tema preparamos un proyecto de práctica para trabajar calidad de código de manera concreta. Creamos una estructura simple, configuramos el entorno, agregamos una función con problemas intencionales y escribimos pruebas de caracterización para proteger el comportamiento actual.
En el próximo tema nos enfocaremos en la legibilidad: nombres, intención y estructura visual del código. Usaremos este proyecto para empezar a detectar mejoras pequeñas que hacen que un programa sea más fácil de entender.