8.5. Programmazione data-centrica

Per adesso probabilmente vi starete grattando la testa chiedendovi perché questo modo di fare sia migliore rispetto all'usare un ciclo for e chiamate dirette a funzioni. Ed è una domanda perfettamente legittima. È principalmente una questione di prospettiva. Usare map e filter vi obbliga a focalizzare l'attenzione sui dati.

In questo caso abbiamo cominciato senza nessun dato; la prima cosa che abbiamo fatto è stata ottenere la directory dello script in esecuzione e una lista di files in questa directory. Questo è stato il nostro punto di partenza che ci ha fornito dei dati veri su cui lavorare: una lista di nomi di files.

Comunque, sapevamo di non doverci occupare di tutti quei files, ma solo di quelli che sono configurazioni di test. Avevamo troppi dati e dovevamo filtrarli. Come potevamo sapere quali dati scegliere? Avevamo bisogno di un test per decidere, quindi ne abbiamo definito uno e lo abbiamo passato alla funzione filter. In questo caso abbiamo usato una espressione regolare per decidere, ma il concetto rimane lo stesso indipendentemente dal modo in cui strutturiamo il test.

A questo punto avevamo i nomi dei files di ogni configurazione di test (e solo le configurazioni di test, visto che ogni altra cosa era stata esclusa dal filtro), ma in realtà volevamo il nome dei moduli. Avevamo le informazioni giuste ma nel formato sbagliato. Abbiamo quindi definito una funzione per trasformare ogni nome di file in un nome di modulo ed abbiamo mappato la funzione sull'intera lista. Da un nome di file, possiamo avere un nome di modulo; da una lista di nomi di file, possiamo avere una lista di nomi di moduli.

Al posto di un filtro, potevamo usare un ciclo for con una condizione if. Invece di map, potevamo usare un ciclo for con una chiamata a funzione. Però usare un ciclo for come questi è laborioso. Nel caso migliore, è una semplice perdita di tempo; nel caso peggiore, può introdurre bugs misteriosi. Per esempio, dovremo in ogni caso inventare un modo per decidere “questo file è una configurazione di test?”; questa è la logica specifica della nostra applicazione, e nessun linguaggio può scriverla per noi. Ma una volta trovata, dobbiamo davvero crearci il problema di definire una lista vuota, scrivere un ciclo for, impostare un if, aggiungere a mano alla nuova lista ogni elemento che ha passato il test e tenere traccia di quale variabile contiene i nuovi dati filtrati e quale contiene i vecchi dati integri? Perché non definire la condizione di test e poi lasciare che Python faccia il resto del lavoro per noi?

Certamente, potevate tentare di essere fantasiosi e cancellare gli elementi sul posto senza creare una nuova lista. Ma sareste stati bruciati da questo metodo ancora prima di cominciare. Cercare di modificare una struttura di dati sulla quale state iterando può essere rischioso. Cancellate un elemento, andate all'elemento successivo e ne avete appena saltato uno. Ma Python è un linguaggio che lavora in questo modo? Quanto tempo ci avete messo per capirlo? I programmatori sprecano troppo tempo e fanno troppi errori connessi a questioni puramente tecniche come questa, e questo non ha nessun senso. Non migliora per niente il vostro programma; è solo spreco di energie.

Io ho resistito alla list comprehension quando ho iniziato ad imparare Python, ed ho resistito a filter e map ancora più a lungo. Ho insistito per rendermi la vita più difficile, ancorandomi ai familiari cicli for ed if di una programmazione incentrata sul codice. Ed i miei programmi in Python sembravano scritti in Visual Basic, descrivendo ogni passo di ogni operazione in ogni funzione. Avevano lo stesso tipo di piccoli problemi e bugs oscuri. E questo non aveva senso.

Lasciamo andare tutto. Il codice laborioso non è importante. I dati sono importanti. Ed i dati non sono difficili. Sono solo dati. Se sono troppi, li filtriamo. Se non sono quelli che vogliamo, li mappiamo. Concentratevi sui dati; lasciatevi alle spalle i lavori inutili.