Definición
Un algoritmo es una serie finita de pasos bien definidos que resuelve un problema.
No es un concepto exclusivo de la programación: una receta es un algoritmo, y el proceso para preparar un pedido en un almacén también. Lo que cambia al programarlo es que hay que dejarlo tan preciso que una máquina pueda ejecutarlo sin interpretar nada.
Lo que separa uno bueno de uno malo
No es la elegancia del código. Es cómo se comporta cuando crecen los datos.
Un algoritmo que tarda un segundo con 100 registros puede tardar un segundo con 100.000, o puede tardar tres horas. La diferencia no se nota en pruebas con datos pequeños — se nota en producción, dos años después, cuando la base de datos ha crecido.
Esa relación entre el tamaño del problema y el tiempo que tarda se llama complejidad, y se expresa con la notación O grande. Sin matemáticas, las que se ven a diario:
O(1) — constante. Tarda lo mismo con 10 que con un millón. Buscar en un diccionario por su clave.
O(log n) — logarítmica. Crece muy despacio. Buscar en algo ordenado partiendo por la mitad cada vez. Es lo que hace un índice de base de datos.
O(n) — lineal. El doble de datos, el doble de tiempo. Recorrer una lista entera.
O(n²) — cuadrática. El doble de datos, cuatro veces el tiempo. Aparece siempre que hay un bucle dentro de otro recorriendo lo mismo. Es la que mata sistemas.
La regla práctica: hasta O(n) se vive tranquilo; O(n²) hay que mirarlo con lupa.
Ejemplo práctico
El caso que más veces he visto en sistemas de gestión es siempre el mismo, y es una O(n²) escondida.
Hay que cruzar los pedidos con los clientes. La forma intuitiva es: por cada pedido, recorrer la lista de clientes hasta encontrar el suyo. Con 100 pedidos y 100 clientes son 10.000 comparaciones y no se nota. Con 3.000 pedidos y 2.000 clientes son seis millones, y la pantalla tarda medio minuto en cargar.
Lo que aprendí: la solución casi nunca es «optimizar el código». Es cambiar la estructura de datos. Metiendo los clientes en un mapa indexado por su id, la búsqueda pasa de recorrer la lista a ser directa, y el algoritmo entero cae de O(n²) a O(n). El mismo resultado, cientos de veces más rápido, y normalmente con menos líneas.
Ver estructura de datos.
El segundo aprendizaje, y es el más útil para quien dirige sin programar: cuando algo «va lento», la primera pregunta no es si hace falta un servidor más potente. Es si el problema crece con los datos. Si al duplicar los registros el tiempo se cuadruplica, ningún servidor lo arregla — solo retrasa el momento en que vuelve a ser lento.
Esa distinción decide si el gasto correcto son 200 € al mes de infraestructura o dos horas de alguien mirando el código.
Y una advertencia contra el exceso contrario: optimizar lo que no importa es tiempo tirado. Un algoritmo terrible que se ejecuta una vez al mes sobre 50 registros no merece ni un minuto. La optimización se aplica donde se nota, y para saber dónde se nota hay que medir. Ver observabilidad.
Errores comunes
- Probar solo con datos pequeños. Todos los algoritmos parecen rápidos con 20 registros.
- Bucles anidados recorriendo la misma lista.
- Consultar la base de datos dentro de un bucle. Ver consulta N+1.
- Optimizar sin medir. Casi siempre se optimiza lo que no era el cuello de botella.
- Creer que más servidor arregla un mal algoritmo.
- Cargar todo en memoria para procesarlo cuando podría hacerse por partes.
Cuándo pensar en ello
Cuando el volumen vaya a crecer, y siempre antes de dar por bueno algo que funciona en pruebas.
La pregunta que basta para detectar el 90 % de los problemas: si mañana hubiera diez veces más datos, ¿esto tardaría diez veces más o cien? Si es lo segundo, hay trabajo pendiente aunque hoy vaya bien.