02
12
07

Se stai scrivendo la stessa cosa due volte, c’è qualcosa di sbagliato

17:40 Technocracy

Array.prototype.chain (AS)

Ormai è persa nei meandri della memoria, non so dove l’abbia letta o come l’abbia formulata, non so la sua origine. Uno dei concetti che più ha influenzato il mio stile di programmazione attuale è riassunto nella frase:

Se stai scrivendo la stessa cosa due volte, c’è qualcosa di sbagliato

Il concetto è una estremizzazione utopica, ovviamente è impossibile applicarla nella sua totalità. La trovo però di particolare rilevanza per la sua portata estensiva su più livelli e per la sua leggera carica provocatrice.

Il concetto da cui nasce è che la programmazione, per sua stessa natura, è un algoritmo in grado di eseguire automaticamente processi ripetitivi e meccanici.
Sarebbe stupido se un programmatore lavorasse per automatizzare processi, e non riuscisse ad automatizzare il codice stesso che sta scrivendo. Non sarebbe un controsenso?

La portata di questa frase è notevole perché impone di riflettere sull’impatto globale che ogni singola riga di codice porta con sé: nell’istante in cui ci si accorge che si è appena scritto qualcosa che esiste con quello stesso significato altrove, immediatamente dovrebbe scattare una riflessione. Ci si dovrebbe chiedere a questo punto:

  1. Posso accorpare le due righe di codice in una funzione richiamata nei due punti?
  2. C’è una logica ad un livello superiore di astrazione che mi è sfuggita?
  3. Ha senso farlo?

Le tre domande non sono banali, soprattutto se vi abituate a farvele in ogni istante. Derivano tutte dalla frase sopra riportata, esplicandone il significato simbolico.

La realizzazione di una funzione è già di per sé una forma di astrazione: il codice ‘grezzo‘ viene ‘promosso‘ e si astrae nella funzione corrispondente. Questo processo è più interessante di quello che può sembrare perché implica anche ottimizzazione: quali sono i parametri che tale funzione richiede per funzionare? Posso minimizzarli?
E’ interessante anche perché è indipendente dal paradigma di programmazione che si utilizza, che sia funzionale o a oggetti. Lo scopo è salire un gradino nella scala dell’astrazione, semplificando da quel momento in poi la scrittura di quel particolare codice.

La riflessione su una logica superiore di astrazione è egualmente importante, perché nel momento in cui ci si accorge che si sta replicando funzionalità (anche se il codice non è identico 1:1) è possibile che sia solo la punta di un concetto molto più ampio che potrebbe essere astratto e non solo di quella specifica funzionalità

Domandarsi infine se ha senso è rilevante perché rappresenta la possibilità di valutare possibili aspetti negativi dell’astrazione. A volte non ha davvero senso astrarre quel pezzo di codice. Altre volte i vantaggi apportati sarebbero minori degli svantaggi. Oppure si rischierebbe di rovinare una struttura semplice, elegante e leggibile. Soprattutto in quest’ultimo caso, ritengo che “una ripetizione” non sia sufficiente a giustificare il cambiamento.

Se notate quella banale frase che mi si fissò nella mente quasi 10 anni fa è analoga ai principi DRY (Don’t Repeat Yourself) e anche ad alcune parti della Extreme Programming.

Astraiamo? Già il fatto che questo concetto sia indipendente dallo stile di programmazione utilizzato è significativo, non è obbligatorio programmare a oggetti per farlo.
Astraiamo? Il concetto non è strettamente inerente alla programmazione! Potrei in questo senso citare Maeda e il concetto di Simplicity che porta con sé.
Astraiamo? Potremmo risalire e scoprire che per esempio la ripetizione meccanica è qualcosa di innaturale (i.e. Tempi Moderni). Il nostro organismo è una infinità di strati biologici con livelli di astrazione crescente.

2 comments

1

bard 2007 12 02 at 20:18

Questo processo [di astrazione] è più interessante di quello che può sembrare perché implica anche ottimizzazione: quali sono i parametri che tale funzione richiede per funzionare? Posso minimizzarli? [...] Lo scopo è salire un gradino nella scala dell’astrazione, semplificando da quel momento in poi la scrittura di quel particolare codice.


A volte ottimizzare un'attività nuoce a un'altra. Leggere codice e comprenderlo richiede l'inverso dell'astrazione: sostituiamo mentalmente strati di simboli con gli effetti concreti che ci aspettiamo produrranno quando interpretati. In dosi irragionevoli abstraction è obfuscation.

Ho visto cose come:


client.connect(server)
client.handshake(server)


...venire compulsivamente storpiate--pardon, rifattorizzate in:


[:connect, :handshake].each {|action| client.send(action, server)}


Che penso sia anche il genere di cose che volevi inquadrare con quella terza domanda.

Al DRY personalmente preferisco questo:

First, we want to establish the idea that a computer language is not just a way of getting a computer to perform operations but rather that it is a novel formal medium for expressing ideas about methodology. Thus, programs must be written for people to read, and only incidentally for machines to execute.


Purtroppo non è riassumibile in un acronimo di tre lettere, per cui non mi aspetto di vederla largamente praticata nel futuro immediato...

Questo è un altro post interessante. (Sì, altro insinua non troppo sottilmente che anche il tuo lo sia. ;-))
2

Folletto Malefico 2007 12 02 at 20:29

Non so se lo sapevi mentre scrivevi, ma sfondi una porta più che aperta. :)
Quanto tocchi nel tuo commento tratta quello che io definisco al momento con "Code Usability" e che affronterò più avanti in modo - spero - esaustivo. ;)

La definizione che preferisci a DRY... è perfettamente in linea, infatti, con il mio pensiero. :)
Son felice perché hai colto il senso del post accompagnato al concetto "fra le righe" che l'importante è mantenere il codice leggibile. :)

Grazie per il post, che rimanda a quello ugualmente interessante di Joel che mi era sfuggito. :)

Nota a margine: questo post nasce su alcune connessioni mentali che ho fatto dopo aver letto della campagna anti-if. ;)