Come scegliere i nomi nel proprio codice
giovedì, 27 maggio 2021
Alcuni spunti su come scegliere nomi adatti per variabili e altri elementi del codice
Foto di Joshua Woroniecki su Unsplash
Quando si approccia alla programmazione e si deve scrivere le prime variabili e funzioni, ci si pone inevitabilmente la domanda “come devo chiamare questa cosa?” e la risposta arriva quasi immediata “non voglio perdere tempo a pensarci, le do il primo nome che mi viene in mente, possibilmente breve per limitare il rischio di sbagliare digitando”, così i primi file diventano un proliferera di variabili, classi e funzioni dai nomi che dopo pochi giorni non sono più comprensibili nemmeno dall’autore. D’altro canto, al crescere dell’esperienza, si può raggiungere un’attenzione quasi maniacale alla scelta dei nomi fino a spendere ore e ore discutendo con i colleghi di quale nome sarebbe più adatto.
Sulla base di cosa si sceglie un nome?
Nel mondo della programmazione sono coinvolte tante entità che richiedono la scelta di nomi (file, cartelle, namespace, tipi, moduli, pacchetti, endpoint…) ma in questo articolo vorrei concentrarmi solo su tre elementi molto diffusi: variabili, classi e funzioni.
quali sono quindi i fattori che influenzano la scelta di un nome?
Il tempo
anche se conviene sempre dedicare un momento a riflettere sul nome, non possiamo perdere un’ora per ogni scelta, né possiamo coinvolgere tutte le volte i colleghi in lunghe ed estenuanti discussioni.
La fretta è cattiva consigliera
Se siamo di fretta dobbiamo essere coscienti che probabilmente ci verrà naturale dedicare poco tempo alla nomenclatura danneggiando noi stessi e i colleghi in un imminente futuro: non fatevi prendere dall’affanno e mantenete il controllo.
Il tempo è denaro
Qualora vi trovaste nell’idilliaca condizione per la quale un pool di professionisti del codice può dedicarsi senza fretta alla decisione di un nome di variabile… fuggite da questa azienda! C’è sotto qualcosa di marcio! Trovare nomi adatti è un allenamento continuo che non può però sotrarre troppo tempo al lavoro effettivo perché l’azienda (e spero voi stessi) è interessata ad un prodotto funzionante piuttosto che ad un codice formalmente impeccabile. Se siete nella prima condizione è bene chiedersi perché non ci sia questa spinta e quanto realmente valga il vostro lavoro.
La lunghezza
Analizziamo un primo esempio:
function a (b, c) {
if (b.d()) {
return e(b.f, c);
}
else {
return g(c);
}
}
In questo caso il codice è totalmente incomprensibile e non ci permette di capire né lo scopo della funzione dichiarata né il comportamento interno della funzione a meno di non leggere molte altre righe di codice tenendo annotati i significati delle singole lettere.
Vediamo un secondo esempio all’estremo opposto:
function calculateAmountOfUserTaxesAccordingIfIsForeignerOrLocal (userObjectInstance, currentOrderTotalAmountWithoutTaxes) {
if (userObjectInstance.userIsForeigner()) {
return calculateAmountOfForeignUserTaxesByCountryOfResidence(userObjectInstance.userCountryOfResidence, currentOrderTotalAmountWithoutTaxes);
}
else {
return calculateAmountOfLocalUserTaxes(currentOrderTotalAmountWithoutTaxes);
}
}
Ora direi che è molto più chiaro cosa vuole fare la funzione: “Calcolare l’ammontare di tasse applicate ad un utente a seconda che sia abitante straniero o locale”. Iniziamo a capire che stiamo calcolando delle tasse e che siamo probabilmente ad un e-commerce o ad un sistema finanziario e che, a seconda che l’utente sia o meno straniera sarà applicata una tassazione differente influenzata dalla nazione di provenienza dell’utente stesso.
Per quanto più esplicito però non avete percepito una certa fatica nella lettura? Non vi siete per caso chiesti perché dobbiate leggere quel lunghissimo nome di funzione? O perché su un oggetto che già ha come soggetto un utente (userObjectInstance) si debba appliccare un metodo che di nuovo mi parla di utenti? Non è implicito? Se ci fosse un errore di battitura non fareste parecchia fatica ad individuarlo? E se vorreste riutilizzare questi elementi non richiederebbe una certa fatica replicarne fedelmente il nome (al netto dell’aiuto di un buon editor di testo)?
Sarà che la verità sta spesso nel mezzo ma ecco un esempio che trovo essere un buon compromesso tra i due approcci anche se può essere certamente migliorato ulteriormente:
function calculateTaxes (user, orderAmount) {
if (user.isForeigner()) {
return calculateForeignTaxes(user.country, orderAmount);
}
else {
return calculateLocalTaxes(orderAmount);
}
}
Limitare a pochi caratteri rende il nome criptico e difficile da comprendere, allo stesso tempo un nome eccessimante lungo si porta dietro diversi altri problemi. La soluzione sembra quindi essere di cercare la massima brevità nel rispetto però della chiarezza.
Roberto C. Martin, autore del famosissimo libro “Clean Code”, ha provato a dare una regola più specifica: la lunghezza delle variabili dovrebbe essere direttamente proporzionale all’ampiezza del contesto (scope) in cui è dichiarata; la lunghezza di funzioni e classi dovrebbe invece essere inversamente proporzionale al contesto. Per approfondire vi consiglio questo video a partire almeno da questo punto: https://www.youtube.com/watch?v=2a_ytyt9sf8&t=3011s (tempo permettendo vi consiglio di guardare l’intero video e, perché no, l’intera serie: https://www.youtube.com/watch?v=7EmboKQH8lM&list=PLUxszVpqZTNShoypLQW9a4dEcffsoZT4k
La facilità di lettura
Partiamo subito da un esempio: scrivere listofallitemincart
), è molto più difficile da interpretare a prima vista rispetto a listOfAllItemInCart
, list_of_all_item_in_cart
o list-of-all-item-in-cart
. Questo concetto si potrebbe poi estendere ad altri aspetti del codice che non riguardano la nomenclatura: spazi, a capo, ecc…
L’intuitività
Utilizzare delle convenzioni non condivise (tsVariabile_op
) solleva un muro tra chi le adotta e chi non le conosce. Da un lato è vero che le convenzioni possono velocizzare molto il lavoro (è il punto di forza di molti popolari framework come Ruby On Rails, Django e Laravel) ma dall’altro lato rendono più difficile il lavoro ai nuovi arrivati (che già avranno a che fare con tante novità), richiedono continua manutenzione, chiarimenti continui e frequenti discussioni.
La presenza di contesto
Riprendendo quanto accennato riguardo alla lunghezza si può considerare che, quando ho un contesto definito, posso essere più sintetico. Se al contrario non ho contesto è meglio essere specifici e allungare il nome aggiungendo dettagli chiarificatori.
Se per esempio devo dichiarare un metodo che restituisca una lista di utenti in una classe User
non avrò bisogno di chiamare il metodo getUserList
perché per forza di cose sarà richiamato sempre in associazione alla classe e potrò quindi semplificarlo in getList
(se è un metodo statico sarà quindi richiamato per esempio con User.getList()
). Al contrario, se sono in un contesto più generico e dichiaro una funzione che deve recuperare la stessa lista, allora è bene che la funzioni si chiami per esempio getUserList
perché getList
non sarebbe abbastanza esplicativo e in quel contesto più ampio potrebbe volere direi “lista di utenti”, “lista di libri” o qualunque altra cosa.
in che lingua scrivere?
Inglese. Anche se vi costerà un po’ di più: scrivete in inglese. Anche se è un vostro progetto personale: consideratelo un allenamento. Un domani potrebbe comunque esservi utile quel codice in un progetto più grande.
Se è un progetto professionale che ha una qualche relazione con i soldi allora il dubbio non si pone proprio. Se lavori solo tu al progetto, anche se i tuoi colleghi sono tutti italiani, ci sono buone probabilità che possiate chiedere aiuto ad un consulente straniero un domani, un esperto o un junior che vi aiuti in task semplici. è possibile poi, e a volte augurabile, che il progetto o l’azienda siano acquisiti da stranieri e da qualunque paese vengano l’inglese sarà la lingua preferita per comunicare e capirsi.
Infine considerate che i linguaggi stessi usano l’inglese e la lettura è più coerente e fluida se tutto il linguaggio parla la stessa lingua.
In conclusione
La chiave, come sempre, non è seguire la regola giusta ma ragionare e ricercare continuamente la soluzione migliore imparando ad adattarsi ai cambiamenti. La prima cosa da evitare è prendere le cose con troppo leggerezza; la seconda è diventare pedante e protagonista del codice. Non esiste “la mia variabile. Non esiste “la mia regola”. Deve esistere un prodotto che tutti vogliono migliorare continuamente collaborando e condividendo nuove idee.