Sviluppo

Come scrivere il codice per se e per gli altri

Scrivere il codice è un'arte. Scopriamo insieme i metodi per produrre codice durevole nel tempo.

Come scrivere il codice per se e per gli altri
I punti chiave

Hai mai preso in gestione un progetto realizzato, del tutto od anche solo in parte, da altri o del codice condiviso con i colleghi di lavoro? Sei sbiancato appena hai iniziato a spulciare il codice, pentendoti amaramente di aver scelto il tuo lavoro dopo esserti imbattuto in un “bagno di sangue”?

Scrivere codice è un’arte - e ciò mi fa ricordare che, da noi in Italia, gli sviluppatori freelance sono iscritti, forse non per caso, alla cassa previdenziale come artigiani. Le regole su come scrivere le istruzioni esistono, però ciascun programmatore adotta, in base all’esperienza e a scelte personali, un proprio stile. Esattamente come farebbe uno scrittore che sceglie le parole per esprimere un concetto. Questo tocco di “creatività”, o di personalizzazione, può influire profondamente sul destino di un sito web o di un’app: se il codice è scritto davvero bene, in modo comprensibile, sarà più facile intervenire in caso di necessità; se invece è scritto alla rinfusa, senza organizzazione, e in modo del tutto sconclusionato, la manutenzione si trasformerà in un vero incubo - un incubo peggiore di Poltergeist!

Propongo di seguito due esempi di codice JavaScript per spiegare meglio quanto sia importante sviluppare bene e in modo collaborativo.

function fattoriale(x) {
  var y = 1;
  for (var i = 1; i <= x; i = i + 1) {
    y = y * i;
  }
  return y;
}
/**
 * Calcola il fattoriale di un numero usando while.
 *
 * @param {number} num - Il numero di cui calcolare il fattoriale.
 * @returns {number} Il fattoriale del numero, o NaN se il numero è negativo.
 */
function fattoriale(num) {
  if (num < 0) {
    return NaN; // Restituisce NaN per numeri negativi
  }
  let risultato = 1;
  while (num > 1) {
    risultato *= num;
    num--;
  }
  return risultato;
}

console.log(fattoriale(5)); // 120
console.log(fattoriale(0)); // 1
console.log(fattoriale(-3)); // NaN

Queste due funzioni svolgono la stessa operazione, ma gli stili adottati sono completamente diversi. Non so tu, ma io vorrei sempre ritrovarmi a gestire codice simile al secondo esempio. L’ampio commento spiega per filo e per segno lo scopo del codice che lo segue e i nomi delle variabili sono auto esplicative. Si nota poi come la funzione sia stata scritta da una mano esperta: è stata inserita al suo interno una verifica per controllare gli errori, nello specifico viene restituito un errore se il numero di input è negativo.

Il punto cruciale è che scrivere codice significa fare in modo che funzioni, fluidamente, e che sia anche e soprattutto usabile. Sì, perché l’usabilità del codice è un concetto di cui si parla molto poco. Si deve applicare anche al codice, oltre che alle macchine. Capita infatti che dopo aver scritto un programma o un sito web occorra rivedere o aggiungere delle funzionalità; farlo in modo comodo all’interno di una struttura ben organizzata e facilmente comprensibile rappresenta un vantaggio per gli altri, ma anche per se stessi, perché semplifica enormemente il lavoro futuro. Chi vuole cimentarsi nella programmazione, a mio avviso, dovrebbe comprendere in primo luogo quanto sia importante allenarsi fin da subito a documentare ciò che scrive. I vari manuali che ho studiato nel tempo hanno sempre spiegato come scrivere i commenti, generalmente tra i primi capitoli. Ciò che avrei voluto trovare è una maggiore attenzione sul come sfruttare al meglio i commenti. La notizia positiva è che esistono dei libri specifici sull’argomento, come l’apprezzato Code Clean, di Robert C. Martin, disponibile anche in italiano.

Estratto di un manuale di sviluppo che spiega solo tecnicamente come si scrive un commento
Il paragrafo dedicato ai commenti di un manuale di JavaScript riporta solo poche righe su come tecnicamente si scrivono. Suggerirei di dedicare almeno qualche pagina sull’importanza di come documentare il codice, a costo di ripeterlo in ogni volume di programmazione.

Vediamo insieme come documentare e organizzare il codice per renderne la manutenzione futura più agevole. I più esperti potranno ripassare alcuni dei consigli pratici che riporterò e li invito a scrivermi per condividere la loro esperienza e il loro approccio.

La mentalità del programmatore collaborativo

Il progetto sul quale ci siamo messi al lavoro è urgente - quando mai - anzi, oggi ultra urgente. “Le rifiniture e le migliorie le possiamo rimandare alla fase che segue la consegna. Viste le scadenze ristrette, l’unico obiettivo è consegnare quanto prima.”. Questa può essere una tipica frase scambiata tra gli addetti ai lavori, non solo in ambito informatico. Il problema è che spesso, una volta consegnato il progetto, il tempo e il budget residui sono limitati e altri progetti urgenti prendono il sopravvento. Un lavoro fatto in fretta all’inizio, però, significa ingigantire i tempi poi. Quando scriviamo il nostro codice, dobbiamo porci una domanda: “ciò che sto scrivendo, riuscirò a capirlo a colpo d‘occhio tra un anno? Gli altri membri del team potranno intervenire in modo rapido senza doversi studiare tutto il codice?”.

Più è vasto un progetto, più sviluppatori dovranno essere coinvolti. A ciascun membro del team vengono assegnati dei compiti in base alle sue specializzazioni. Come sviluppatore front-end (freelance) e lavorando anche in team, comprendo quanto sia importante la comunicazione bidirezionale. Quando sviluppo, ad esempio, in JS o React, provo ad adottare quanto più possibile le migliore pratiche di un corretto sviluppo. Ne esistono diverse e tutte possono integrarsi l’una con l’altra. Tra queste, troviamo certamente il DRY, acronimo di Don’t Repeat Yourself. Il principio base di questa pratica è l’evitare di duplicare il codice, rendendolo quindi altamente riciclabile attraverso una corretta suddivisione e organizzazione. Questa strategia, insieme alle altre che saranno proposte più avanti, mi consente di capire il mio stesso codice in futuro, quando sarà necessario rivederlo e aggiornarlo. Ed è utile anche allo sviluppatore back-end quando prende in mano il mio di codice. Allo stesso modo, mi aspetto che anche gli altri membri del team commentino, spieghino e organizzino il loro codice in modo da poterlo comprendere e integrare agevolmente con il mio. Se è necessario interagire per esempio con un modulo di Drupal, è bene avere una chiara visione d’insieme a colpo d’occhio.

Scrivere codice leggibile: principi e consigli pratici

Leonardo da Vinci diceva “La semplicità è la massima raffinatezza”. Adottiamo le parole del genio italiano anche nel mondo dello sviluppo e avremo un bel KISS. No, non è un bacio a fine lavoro, ma il concetto di tenere tutto semplice (Keep It Simple, Stupid). Adottare una serie di principi per rendere il codice semplice non significa essere stupidi ma efficaci. Passiamo subito al dunque spiegando come raggiungere il traguardo.

Lo stile di codifica

Quando parliamo una lingua, nel nostro caso l’italiano, utilizziamo le regole grammaticali per comporre correttamente le frasi. I linguaggi di programmazione sono come le lingue ed hanno delle convenzioni di stile equiparabili alle regole grammaticali. Scrivere il codice in modo chiaro e ordinato significa ridurre gli errori e semplificare il lavoro di chi si occuperà della manutenzione.

I motivi per i quali è importante utilizzare uno stile di codifica sono quattro: la leggibilità (attraverso una corretta formattazione), la manutenibilità, la collaborazione (poiché l’uso della stessa convenzione unisce il team), la professionalità (dimostrando attenzione ai dettagli).

Abbiamo capito a cosa servono le convenzioni di stile, ma quali sono? Ogni linguaggio può avere le proprie, e ogni team di lavoro potrebbe aggiungere il proprio tocco identitario, ma in linea generale ci sono sempre delle similitudini.

Con l’indentazione le righe vengono fatte rientrare per evidenziare i blocchi di codice.

Gli spazi bianchi, che possono essere semplici spazi o tabulazioni, invece sono utili per separare le parole chiave, gli operatori e le variabili.

Bisogna poi gestire correttamente la lunghezza delle righe, evitando quelle molto lunghe.

Infine abbiamo la posizione delle parantesi graffe, che però dipende più dal team che da una regola generale. Io personalmente preferisco evitare di lasciare da sola l’apertura della prima parentesi graffa, risparmiando una riga.

Ecco due esempi di codice che fanno la stessa cosa, ma che utilizzano due stili diversi:

// Stile poco chiaro
for(i=0;i<10;i++){document.write(i);}

// Stile chiaro
for (let i = 0; i < 10; i++) {
  document.write(i);
}

Il secondo esempio è chiaramente più facile da leggere perché utilizza correttamente gli spazi, e l’indentazione. Inoltre anche il nome della variabile è chiaro e conciso.

In che modo è possibile imparare le convenzioni di stile? Leggere la documentazione ufficiale, sulla quale sono riportati anche tantissimi esempi, del linguaggio di programmazione che stiamo adottando è il miglior suggerimento che si possa dare. Il secondo passo è utilizzare i linters, strumenti che analizzano il codice e segnalano gli eventuali errori, e i formattatori di codice, come Prettier - Code formatter. Infine, può essere positivo consultare, con attenzione e con occhio critico se necessario, il codice dei progetti open-source per imparare dai più bravi.

I commenti

Un codice auto esplicativo spiega cosa fa. Quindi perché scrivere un commento a corredo del codice se lo si capisce semplicemente leggendolo? Una buona regola nell’usare correttamente i commenti è che questi devono spiegare il perché il codice è stato scritto in quel modo. Sono utili soprattutto per chiarire quei passaggi che risultano essere complessi.

I commenti si scrivono all’inizio di una funzione o di un blocco di codice per spiegare lo scopo generale del codice. Se il codice è molto complesso, allora, è consigliabile aggiungere ulteriori commenti che spiegano i vari passaggi. Può anche capitare che per ottenere un determinato risultato possano esistere più strade. In questo caso è utile commentare il perché è stata adottata una determinata soluzione, scartando le altre.

Anche la forma dei commenti rientra nel vasto ramo dell’usabilità. Bisogna essere chiari e concisi, evitando di scrivere poemi, di ripetere ciò che il codice già spiega da solo, di scrivere commenti non pertinenti altrimenti andremo a creare confusione. E se, infine, ci ritroviamo ad aggiornare il codice, dedichiamo qualche minuto anche ad aggiornare il commento.

Ecco un esempio concreto e corretto di un commento, di una funzione per WordPress:

function wp_get_attachment_image_url( $attachment_id, $size = 'full' ) {
    /**
     * Recupera l'URL dell'immagine allegata.
     *
     * Se l'immagine allegata non ha un'immagine di anteprima per la dimensione specificata,
     * verrà restituito l'URL dell'immagine originale.
     *
     * @param int $attachment_id ID dell'allegato.
     * @param string $size (opzionale) Dimensione dell'immagine. Default: 'full'.
     * @return string URL dell'immagine, o false in caso di errore.
     */
    ... // Resto del codice della funzione
}

Organizzare il codice: rendiamo efficienti i nostri progetti

Questa sezione è la più importante perché occorre sapere dividere e organizzare il codice. Non solo è una buona abitudine ma è il segreto per creare progetti ordinati, manutenibili e collaborativi. È un po’ come la nostra casa - a meno che non si viva in un monolocale: l’intera area è divisa in spazi che hanno una precisa funzione: la cucina per mangiare, le camere da letto per dormire, e così via. Allo stesso modo, l’intero codice viene suddiviso in parti più piccole, e ciascun blocco assolve a determinati compiti. In programmazione, le nostre stanze sono le funzioni e i moduli. Questo fondamentale concetto prende il nome di Single Responsibility Principle (SRP), in italiano Principio di Responsabilità Unica.

Cosa sono le funzioni?

Una funzione è un breve blocco di codice focalizzato nello svolgere un unico compito specifico. Organizzare il codice in funzioni è importante perché consente di richiamare la funzione quando serve senza dover riscrivere nuovamente il codice. In caso di errori, inoltre, è più facile effettuare il debugging.

function calculateSum(a, b) {
    return a + b;
}
// Può essere utilizzata in diversi contesti
let result = calculateSum(5, 7);
console.log(result); // Output: 12

Cosa sono i moduli?

Un modulo è un file che raccoglie una raccolta di funzioni, variabili e classi. Possiamo utilizzare i moduli a nostro vantaggio per riutilizzarli in progetti diversi ed anche condividerli con altri sviluppatori.

// Esempio di modulo
// mathUtils.js
export function calculateSum(a, b) {
    return a + b;
}
export function calculateDifference(a, b) {
    return a - b;
}
// Importazione di un modulo
import { calculateSum, calculateDifference } from './mathUtils.js';

console.log(calculateSum(5, 7)); // Output: 12
console.log(calculateDifference(10, 4)); // Output: 6

Come scrivere correttamente le funzioni e i moduli?

Ogni funzione - lo ripeto perché è davvero importante - deve svolgere un unico compito. Il nome che assegniamo alla funzione o al modulo deve essere chiaro, semplice ma allo stesso tempo descriverne lo scopo. Infine, come già scritto nelle precedenti sezioni, è utile commentare il codice e utilizzare le convezioni di stile.

La convenzione dei nomi

Conosci Idefix, il cagnolino di Obelix? Nelle sue prime apparizioni questo piccolo personaggio, introdotto nel 1963 solo come riempitivo per alcune vignette, non aveva alcun nome. Poi però fu deciso di renderlo un personaggio fisso. Gli editori, dopo un sondaggio, scelsero di chiamarlo Idefix, derivato da idée fixe, ovvero idea fissa. I vignettisti riportarono le ragioni di tale scelta: “… è un nome corto, che suona bene e entra facilmente nell’orecchio. Rappresenta bene il carattere del personaggio, che è in effetti un piccolo animale con delle fissazioni …”. Ho deciso di riportare questa simpatica storiella perché, proprio come i vignettisti hanno scelto un nome adatto al cagnolino di Obelix, anche noi sviluppatori dobbiamo scegliere dei nomi che ben rappresentano il ruolo di una variabile, di una funzione o di una classe nel codice che stiamo scrivendo. L’obiettivo di utilizzare nomi significativi è consentire di capire a colpo d’occhio il contesto senza dover leggere tutto il testo.

Ci sono alcuni utili consigli che possiamo seguire per una corretta naming conventions, eccoli:

  • Sii chiaro e conciso evitando abbreviazioni che potrebbero non essere comprese; utilizza invece parole intere e combinazioni di esse (es. totaleProdotti anziché totProd).
  • Usa nomi descrittivi suggerendo il tipo di dato che la variabile contiene o l’azione che la funzione esegue (es. CalcolaTotaleCarrello).
  • Considera il contesto in cui una variabile o una funzione viene utilizzata (es. prodottoInMagazzino).
  • Evita nomi troppo generici che non forniscono alcuna informazione utile (no: totale, sì: totaleProdottiCarrello).
  • Adotta convenzioni di stile coerenti:
    • Usa il PascalCase per le classi e i nomi delle funzioni (ogni parola inizia con la lettera maiuscola, es. CalcolaTotaleProdotti).
    • Usa il camelCase per le variabili e le proprietà (la prima parola inizia con la lettera minuscola e ogni parola successiva inizia invece con una maiuscola, es: totaleProdotti).
  • Sii coerente in tutto il progetto, o meglio in tutti i tuoi progetti, nello stile che adotti (es. quantitaInMagazzino che è coerente con l’altro esempio totaleProdottiCarrello).

In conclusione

Grazie per essere arrivato fino a questo punto! Abbiamo visto insieme, in modo generale, le diverse strategie e i tanti principi per scrivere un codice a regola d’arte. I vari suggerimenti sono utili per tutti, sia per gli sviluppatori alle prime armi sia per i più esperti. Con la buona volontà e accumulando ore di esperienza, si può scrivere del buon codice nel giro di poco tempo. Immaginati di riprendere in mano un tuo vecchio programma, scritto alcuni anni fa. Aprendo i vari file ti rendi conto di quanto sia ancora attuale e che basterebbero pochi interventi per aggiungere le nuove funzionalità e renderlo pronto per il futuro. Il tutto nonostante il codice sia vasto. Questo risultato, sicuramente appagante, è quello che si chiama Codice Legacy. Ricordati inoltre di ridurre allo stretto necessario le dipendenze: meno librerie esterne significa meno rischio di bug, migliore velocità e maggiore sicurezza. Non rimane che mettere in pratica, ora stesso, tutti questi consigli. Buono sviluppo!

I punti chiave