16.5. Programación "datocéntrica"

Ahora es probable que esté rascándose la cabeza preguntándose por qué es mejor esto que usar bucles for e invocar directamente a las funciones. Y es una pregunta perfectamente válida. En su mayoría es una cuestión de perspectiva. Usar map y filter le fuerza a centrar sus pensamientos sobre los datos.

En este caso hemos empezado sin datos; lo primero que hicimos fue obtener la ruta del directorio del script en ejecución y la lista de ficheros en ese directorio. Eso fue la preparación y nos dio datos reales con los que trabajar: una lista de nombres de fichero.

Sin embargo, sabíamos que no nos interesaban todos esos ficheros sino sólo los que hacen las baterías de prueba. Teníamos demasiados datos, así que necesitabamos filter-arlos. ¿Cómo sabíamos qué datos mantener? Necesitábamos una prueba que lo decidiese así que definimos uno y se lo pasamos a la función filter. En este caso hemos usado una expresión regular para decidir, pero el concepto sería el mismo independientemente de la manera en que construyésemos la prueba.

Ahora teníamos los nombres de fichero de cada una de las baterías de prueba (y sólo eso, ya que hemos filtrado el resto), pero lo que queríamos en realidad eran nombres de módulos. Teníamos la cantidad de datos correctos, pero estaban en el formato erróneo. Así que definimos una función que transformara un nombre de fichero en el de un módulo, y pasamos la función sobre la lista entera. De un nombre de fichero podemos sacar el nombre de un módulo; de una lista de nombres de ficheros podemos obtener una lista de nombres de módulos.

Podíamos haber usado un bucle for con una sentencia if en lugar de filter. En lugar de map podríamos haber usado un bucle for con una llamada a función. Pero usar bucles for de esa manera es trabajoso. En el mejor de los casos simplemente es un desperdicio de tiempo; y en el peor introduce fallos difíciles de detectar. Por ejemplo, necesitamos imaginar la manera de comprobar la condición “¿este fichero es una batería de pruebas?” de todas maneras; és la lógica específica de la aplicación y ningún lenguaje puede escribir eso por nosotros. Pero una vez que ya lo tiene, ¿de verdad quiere tener que crear una nueva lista vacía y escribir un bucle for y una sentencia if y luego llamar manualmente a append por cada elemento de la nueva lista si pasa la condición y llevar un seguimiento de qué variable lleva los datos filtrados y cual los que no están filtrados? ¿Por qué no limitarse a definir la condición de prueba y dejar que Python haga el resto del trabajo por nosotros?

Sí, claro, podría intentar ser imaginativo y borrar elementos de la lista original sin crear una nueva. Pero eso seguro que ya se ha quemado con eso antes. Intentar modificar una estructura de datos sobre la que se está iterando puede tener truco. Borramos un elemento, iteramos sobre el siguiente y de repente nos hemos saltado uno. ¿Es Python uno de los lenguajes que funciona así? ¿Cuánto nos llevaría averiguarlo? ¿Estamos seguros de recordar si era seguro la siguiente vez que lo intentemos? Los programadores pierden tanto tiempo y cometen tantos errores tratando con problemas puramente técnicos como este, y encima no tiene sentido. No hace avanzar nuestro programa; es todo trabajo en vano.

Me resistí a las listas por comprensión cuando aprendí Python, y me resistí a filter y map todavía más. Insistí en hacer mi vida más complicada quedándome con las familiares formas de los bucles for y las sentencias if y la programación paso a paso centrada en el código. Y mis programas en Python se parecían mucho a los de Visual Basic, detallando cada paso de cada operación de cada función. Y todos tenían los mismos tipos de pequeños problemas y fallos complicados de encontrar. Y nada de esto tenía sentido.

Déjelo todo. Ese trabajo burocrático no es importante. Lo importante son los datos. Y los datos no son difíciles. Son sólo datos. Si tiene muchos, fíltrelos. Si no son los que quiere, “mapéelos”. Céntrese en los datos; deje atrás el trabajo pesado.