Descrizione
È qualcosa che capita a tutti: guardiamo un codice e pensiamo che fa schifo. Ma ci siamo mai chiesti perché nessun codice sembra soddisfare le nostre aspettative?
I link dell’episodio di oggi:
Clean code. Guida per diventare bravi artigiani nello sviluppo agile di software - https://amzn.to/3dkM1l5
What Is Good Code? - http://paul-m-jones.com/post/2020/06/02/what-is-good-code/
—
Attrezzatura di questo episodio:
Shure Microfono Podcast USB MV7 - https://amzn.to/3862ZRf
Utilizzando i link affiliati, il costo di un qualsiasi acquisto non sarà maggiore per te, ma Amazon mi girerà una piccola parte del ricavato.
Sostieni il progetto
Sostieni tramite SatispaySostieni tramite Revolut
Sostieni tramite PayPal
Sostieni utilizzando i link affiliati di Pensieri in codice: Amazon, Todoist, Readwise Reader, Satispay
Partner
GrUSP (Codice sconto per tutti gli eventi: community_PIC)Schrödinger Hat
Crediti
Montaggio - Daniele Galano - https://www.instagram.com/daniele_galano/Voce intro - Costanza Martina Vitale
Musica - Kubbi - Up In My Jam
Musica - Light-foot - Moldy Lotion
Cover e trascrizione - Francesco Zubani
Mostra testo dell'episodio
Quello che segue è lo script originale dell'episodio.
Vi è mai capitato di chiedere ad un programmatore di giudicare la bontà di un codice? O siete voi stessi dei programmatori e vi è stato richiesto un giudizio su un lavoro già svolto?
Beh se vi siete trovati in una situazione del genere, a prescindere dal lato della domanda dal quale eravate, saprete che solitamente la risposta che si ottiene ad un quesito del genere varia tra un diplomatico si sarebbe potuto fare meglio ad un lapidario fa schifo.
Solitamente, un ingegnere o un programmatore chiamati a giudicare in modo approfondito del software, difficilmente giungeranno ad un responso positivo, ammenocché non si parli di condizioni o figure particolari.
La cosa interessante è che non si tratta di semplice disprezzo per gli altri appartenenti alla categoria. È infatti evento comune che un programmatore ritenga cattivo anche il proprio stesso codice scritto mesi o anni prima.
Chi lavora in questo campo lo sa bene: trovasi ad operare su codice esistente è sempre un problema, che a volte può diventare un incubo, e poco importa se si tratta di codice scritto personalmente o da altri.
A volte si fa perfino fatica a riconoscere che si tratta di proprio codice. E non scherzo è una cosa che a me succede: vedo del codice che so essere stato scritto da me, mi chiedo perché hanno fatto questa modifica, vado a controllare e scopro che quella riga era già così dall’inizio. Anche se oggi io la scriverei in modo totalmente diverso.
Nell’episodio di oggi dunque, proveremo semplicemente a capire perché il codice fa sempre schifo!
Prima di avanzare qualsiasi pretesa di giudizio (e questo vale in generale, che si tratti di codice o altro) bisogna stabilire dei criteri su cui lavorare.
Se vogliamo provare a misurare la qualità di un qualcosa, nel nostro caso del codice software, dobbiamo in qualche modo decidere cosa intendiamo per qualità; chiarire cosa riteniamo sia migliore e cosa peggiore; ed elaborare un metodo per confrontare degli artefatti che possono, da un lato raggiungere livelli di complessità molto alti e, dall’altro, differenziarsi notevolmente fra loro e sotto moltissimi aspetti.
Già a questo punto, quindi, le cose si fanno molto difficili.
Se infatti escludiamo i criteri banali e oggettivi, come gli errori di progettazione, i bug, i crash, ecc., restano dei parametri su cui non è poi così facile mettersi d’accordo.
È chiaro, infatti, che un codice pieno di bug, che non svolge i compiti per cui è stato realizzato, che contiene falle di sicurezza conosciute da 20 anni, è facilmente annoverabile tra i software di cattiva qualità.
Ma che dire di un codice che funziona correttamente, ma è magari un po’ lento? Una libreria o semplicemente un metodo al quale, se venisse applicato un certo teorema matematico o un certo design pattern, potrebbero guadagnare velocità di esecuzione o chiarezza?
Oppure che dire di un blocco di codice procedurale che potrebbe essere riscritto utilizzando la programmazione ad oggetti?
Sulla carta, la scelta sembrerebbe facile: il codice che ho descritto è certamente di scarsa qualità, poteva essere scritto in modo molto più rispondente alla teoria riportata nei manuali, alle buone pratiche descritte in capolavori come Clean Code.
Ma siamo sicuri che sia sempre così?
E se quel codice fosse scritto appositamente in modo più semplice?
Certo starete pensando, se so utilizzare costrutti complessi ed efficienti, perché non dovrei farlo?
Beh, magari perché il team che dovrà lavorare su quel codice è meno esperto e andrebbe in difficoltà nell’applicare future implementazioni e nel fare manutenzione.
Magari perché non dedicare troppo alla stesura di codice molto complesso, lascerebbe al team di sviluppo (o all’azienda tutta, se parliamo di piccole realtà) risorse da impiegare in altri ambiti. Magari nella commercializzazione del prodotto o servizio che si sta realizzando?
Ecco, secondo me, quando si parla di qualità, questi sono aspetti che non possono essere lasciati indietro facendone semplicemente un discorso elitario di abilità o di maestria.
Il codice, anche il migliore mai scritto, raramente ha senso se preso da solo.
Questo ci porta ad una distinzione che io trovo molto interessante che ho letto qualche tempo fa in un articolo del blog di Paul Jones, programmatore dal 1983 (l’anno della mia nascita). Trovate come al solito il link in descrizione.
Paul distingue i programmatori in due categorie: i preti e i mercanti. Anche se io onestamente preferisco parlare di monaci invece che preti perché penso che il sostantivo renda meglio l’idea che intendo veicolare.
Il monaco dunque è quel tipo programmatore che tiene al proprio codice e lo scrive pensando al fatto che questo verrà letto da altri programmatori.
Il suo codice dunque è ben organizzato, ben strutturato, con le giuste astrazioni, il disaccoppiamento, l’incapsulamento, gli strati, i test e tutto quello che, sulla carta, rende il codice un buon codice.
Il mercante, invece, è quel tipo di programmatore orientato al risultato economico.
Il suo codice è solo un mezzo per realizzare una o più soluzioni da vendere a qualcuno. Non importa che sia perfetto. Ciò che importa è che funzioni e possa essere messo sul mercato il prima possibile.
E, badate bene, per risultato economico non si intendono necessariamente incassi diretti. Anche farsi conoscere professionalmente potrebbe essere considerato un buon risultato da sfruttare diversamente per un ritorno economico.
Da un punto di vista pragmatico, entrambi gli approcci hanno senso e appaiono ragionevoli. Ed entrambi hanno pro e contro piuttosto interessanti.
Il codice del monaco è stabile, veloce, facile da manutenere e da estendere. Ma occorre molto tempo per portarlo sul mercato e, paradossalmente, portando all’estremo questo approccio, potrebbe non vedere mai la luce perché la perfezione non esiste e ci sarà sempre qualcosa da migliorare.
Il codice del mercante, dal canto suo, pur non essendo super efficiente e super stabile, inizia velocemente a produrre profitto: incontra immediatamente il mercato e più confrontarsi con la realtà e le esigenze reali dei potenziali utilizzatori.
Per contro, però, questo codice potrebbe risultare più complesso da manutenere e da estendere, meno scalabile e, a lungo andare, la codebase potrebbe raggiungere un livello tale di complessità da rendere necessaria una riscrittura completa. Se ne sono visti tanti di progetti che hanno subito questa sorte.
Quindi quale dei due approcci è il migliore? A quale dei due possiamo assegnare il premio dell’approccio di qualità?
La verità è che nessuno dei due, preso in senso assoluto, può essere ritenuto un buon approccio.
È vero che il codice è un mezzo e quindi prima diventa operativo, meglio è per l’azienda che lo deve utilizzare.
Ma è anche vero che un codice più pulito, pur impiegando più tempo a raggiungere l’operatività, avrà una vita più lunga e una maggiore efficienza. Riducendo così i problemi, e quindi i costi, nel lungo periodo.
La realtà quindi, secondo me, è che il giusto approccio è una sfumatura nel mezzo fra questi due estremi e, soprattutto, la gradazione di questa sfumatura va stabilita in base a tutta una serie di fattori che dipendono dal momento, dalle risorse, dal mercato e, probabilmente, anche da aspetti che è difficile inquadrare esplicitamente e che poi vengono dimenticati.
Il progetto ha molti competitor che stanno per entrare nel mercato? Forse è meglio prediligere l’atteggiamento da mercante.
Il progetto è pensato per fare da base per tutta una serie di espansioni future? Forse è meglio privilegiare l’approccio del monaco.
La verità, però, è che la decisione spetta a chi è effettivamente coinvolto e a capo, eventualmente del progetto, mentre per tutti gli altri che sono all’esterno diventa piuttosto difficile giudicare la bontà delle decisioni prese e la corrispondenza ai criteri stabiliti.
A valle di questo ragionamento, a me appare quindi chiaro che valutare la qualità di un software, senza conoscere i criteri con i quali è stato scritto, diventa un po’ un esercizio di stile più che un’attività che abbia un qualche tipo di utilità pratica.
Se non conosco gli standard di qualità nei quali sono stati progettati e realizzati quel determinato script o quella libreria o quella classe, come posso sensatamente giudicarne quanto se ne discosta il risultato finale?
Stabilito quindi che il concetto di qualità, almeno nel software, dove non esistono standard oggettivi e regolamentati, è da considerarsi piuttosto soggettivo, proviamo a capire perché per chi arriva dopo, in linea generale, dirà sempre che il codice già scritto fa schifo.
Badate bene che ho detto chi arriva dopo e non per gli altri perché la verità è che molto spesso quel codice già scritto farà schifo anche all’autore stesso.
In tutta onestà, quante volte è capitato anche a voi? Guardare il vostro codice e pensare ma cosa avevo in testa quando l’ho scritto?
A volte, a me, capita perfino di ritrovare dei miei codici di anni prima, guardare una funzione o un blocco e pensare ma cosa cavolo gli è venuto di mente di modificare questa cosa.
Poi controllo nei commit del sistema di versioni e scopro che quel codice è sempre stato così. Da quando l’ho scritto la prima volta.
Ma come è possibile questa cosa?
La risposta è molto semplice: la causa di questo fenomeno è da ricercare nel trascorrere del tempo.
Il tempo passa e un qualsiasi sistema complesso (che è composto di software, persone, servizi, ecc.) non è una istantanea, fossilizzata nei secoli.
Quando pensiamo che un codice fa schifo, noi lo stiamo giudicando OGGI, con le conoscenze di OGGI e sulla base selle condizioni di OGGI.
Ma quel codice è stato realizzato IERI, con le conoscenze di IERI e sulla base delle condizioni che vigevano IERI.
Il tempo è trascorso e le condizioni sono cambiate. Noi siamo cambiati.
Magari oggi l’azienda ha più risorse, più tempo, o una diversa nicchia di mercato.
Probabilmente noi oggi siamo più esperti, conosciamo più linguaggi, più framework, più pattern. Abbiamo realizzato tante altre soluzioni e accumulati tante altre frecce al nostro arco.
Per dirla con i termini del blocco precedente, probabilmente, all’epoca in cui quel codice è stato scritto, si è utilizzata una certa sfumatura dell’approccio monaco-mercante che oggi non più valida e non stiamo considerando.
Questo fenomeno prende il nome di path dependence, è molto conosciuto in campo economico, e rappresenta proprio quei casi in cui le decisioni che ci si trova di fronte sono in realtà dipendenti da decisioni precedenti ed esperienze passate.
Quando giudichiamo il codice, giudichiamo decisioni prese da noi stessi o altri in un momento passato, quando erano in vigore diverse condizioni e si era in possesso di diverse conoscenze.
E quindi? Cosa possiamo fare?
Beh si potrebbe semplicemente pensare di non giudicare il vecchio codice e tutto sarebbe risolto.
Ma, in realtà, non proprio così.
Ogni volta che dobbiamo estendere o manutenere del codice già esistente, non possiamo esimerci dal darne una valutazione o analisi.
Decidere se è necessario fare refactoring o meno, capire se si può estendere una funzionalità o e necessario riscriverla, prevedere dove e come le nostre modifiche andranno ad impattare, sono tutte attività che fanno parte integrante del nostro lavoro, non possiamo esimerci dal farle e ci porteranno sempre a dover valutare il codice di partenza.
Quindi? A mio parere l’approccio deve essere molto pragmatico.
Si esamina il codice e innanzitutto si valuta se funziona correttamente o meno.
Se non funziona o se le nostre modifiche lo rompono in qualche modo, allora è il momento per sistemarlo: possiamo intervenire più o meno pesantemente a seconda del tempo e delle risorse di cui disponiamo ad oggi.
Se invece, il codice funziona, allora conviene lasciarlo com’è. Brutto, vecchio, ma funzionante.
Il tutto tenendo sempre a mente che fa un anno, anche il più bel codice che riusciremo a scrivere in questo momento, ci apparirà almeno migliorabile.
In ogni caso, credo che, quando possibile, si dovrebbe evitare di approcciarsi ad un codice con l’intenzione di dare giudizi fini a se stessi, e soprattutto, credo che dovremmo proprio toglierci il vizio di usare l’espressione questo codice fa schifo.
Spero di avervi portato delle riflessioni interessanti.
Immagino che non tutti saranno d’accordo con me e mi farebbe molto piacere sentire le vostre opinioni.
In ogni caso, vi ricordo sempre di condividere gli episodi per allargare il discorso, che è una cosa costruttiva che fa sempre bene.
Nell’episodio scorso, ad esempio, vi ho consigliato l’utilizzo di Brave e un nuovo utente del gruppo Telegram ha portato delle fonti interessanti che, al contrario, ne sconsigliano l’uso, dando il via ad un interessante scambio.
Sempre su Telegram, lo dico per l’utente che ha scritto un commento qualche giorno fa su Spreaker, ho iniziato e ho intenzione di continuare a condividere consigli di lettura con una frequenza. Quindi iscrivetevi se vi va di leggere qualcosa di divulgativo sull’informatica.
Trovate tutti i link e le informazioni sul sito pensieriincodice.it. Mi raccomando con due i, pensieri in codice.
A me non resta che ringraziarvi per aver ascoltato fin qui, salutarvi e ricordarvi che un informatico risolve problemi a volte anche usando il computer.
Nascondi