Non è un codice segreto è una cosa complicata da scrivere, eseguire il debug e mantenere che è necessaria per un’elevata qualità del software. Inoltre, l’elevata complessità del codice porta con sé un livello più elevato di difetti del codice, rendendo il codice più costoso da mantenere.
Quindi, riducendo la complessità del codice, possiamo ridurre il numero di bug e difetti, insieme al suo costo di vita. Cos’è esattamente un codice complesso? Come possiamo valutare oggettivamente quanto sia complesso un pezzo di codice, se si tratta di un’intera base di codice o di una piccola funzione?
In questo articolo, ho intenzione di camminare attraverso tre metriche di complessità per valutare la complessità del codice. Questi sono:
- Complessità ciclomatica
- Switch statement and logic condition complessità
- Developer skill
Passerò anche attraverso alcuni dei vantaggi della valutazione e della comprensione della complessità del codice.
- Complessità ciclomatica
- Esempio uno
- Esempio due
- Esempio Tre
- Switch Statement and Logic Condition Complexity
- Livello di abilità sviluppatore software
- I vantaggi della complessità del software di misurazione
- Test migliori
- Rischio ridotto
- Costi inferiori
- Maggiore prevedibilità
- Aiuta gli sviluppatori a imparare
- Questo è un involucro
Complessità ciclomatica
Nel 1976, Thomas McCabe Snr propose una metrica per il calcolo della complessità del codice, chiamata Complessità ciclomatica. È definito come:
Una misura quantitativa del numero di percorsi linearmente indipendenti attraverso il codice sorgente di un programma comp calcolato utilizzando il grafico del flusso di controllo del programma.
Se non si ha familiarità con un grafico del flusso di controllo:
È una rappresentazione, usando la notazione del grafico, di tutti i percorsi che potrebbero essere attraversati attraverso un programma durante la sua esecuzione.
Detto più semplicemente, meno sono i percorsi attraverso un pezzo di codice, e meno complessi sono quei percorsi, minore è la Complessità ciclomatica. Di conseguenza, il codice è meno complicato. Per dimostrare la metrica, usiamo tre esempi di codice Go, in qualche modo arbitrari.
Esempio uno
func main() { fmt.Println("1 + 1 =", 1+1)}
Poiché c’è un solo percorso attraverso la funzione, ha un punteggio di complessità ciclomatica di 1, che possiamo trovare eseguendo gocyclo su di esso.
Esempio due
func main() { year, month, day := time.Now().Date() if month == time.November && day == 10 && year == 2018 { fmt.Println("Happy Go day!") } else { fmt.Println("The current month is", month) }}
In questo esempio, stiamo recuperando l’anno, il mese e il giorno correnti. Con queste informazioni, controlliamo quindi se la data corrente è il 10 novembre 2018 con una condizione if/else.
Se lo è, il codice stampa ” Happy Go day!”alla console. Se non lo è, stampa “Il mese corrente è” e il nome del mese corrente. L’esempio di codice è reso più complicato come se la condizione è composta da tre sotto-condizioni. Detto questo, ha un punteggio di complessità più alto di 4.
Esempio Tre
func main() { _, month, _ := time.Now().Date() switch month { case time.January: fmt.Println("The current month is January.") case time.February: fmt.Println("The current month is February.") case time.March: fmt.Println("The current month is March.") case time.April: fmt.Println("The current month is April.") case time.May: fmt.Println("The current month is May.") default: fmt.Println("The current month is unknown.") }}
In questo esempio, stiamo stampando il mese corrente, in base al valore di month
, recuperato dalla chiamata a time.Now().Date()
. Ci sono sette percorsi attraverso la funzione, uno per ciascuna delle istruzioni case e uno per il default.
Di conseguenza, la sua complessità ciclomatica è 7. Se avessimo contabilizzato tutti i mesi dell’anno, insieme a un default, tuttavia, il suo punteggio sarebbe quattordici. Ciò accade perché Gocyclo utilizza le seguenti regole di calcolo:
1 è la complessità di base di una funzione
+1 per ogni caso ‘if’, ‘for’, ”, ‘&&’ oppure ‘||’
Usando questi tre esempi, possiamo vedere che avendo una metrica standard per calcolare la complessità del codice, possiamo valutare rapidamente quanto sia complesso un pezzo di codice.
Possiamo anche vedere come diverse sezioni complesse di codice sono in confronto tra loro. Tuttavia, la complessità ciclomatica non è sufficiente da sola.
Switch Statement and Logic Condition Complexity
Il prossimo valutatore della complessità del codice è la switch statement and logic condition complexity. Nell’esempio di codice seguente, ho preso il secondo esempio Go e diviso la condizione if composta in tre condizioni nidificate; una per ciascuna delle condizioni originali.
func main() { year, month, day := time.Now().Date() output := fmt.Sprintf("The current month is %s", month) if month == time.November { if day == 13 { if year == 2018 { output = fmt.Sprintf("Happy Go day!") } } } fmt.Println(output)}
Quale è più facile da capire (o meno complicato), quello originale o questo? Ora costruiamo su questo, considerando le seguenti tre domande.
- E se avessimo, come facciamo sopra, più condizioni if e ognuna fosse piuttosto complessa?
- E se avessimo più condizioni if e il codice nel corpo di ognuna fosse piuttosto complesso?
- Il codice sarebbe più facile o più difficile da capire?
È giusto dire che maggiore è il numero di condizioni nidificate e maggiore è il livello di complessità all’interno di tali condizioni, maggiore è la complessità del codice.
Livello di abilità sviluppatore software
Che dire del livello di abilità dello sviluppatore? Dai un’occhiata alla versione C del secondo esempio Go qui sotto.
#include <stdio.h>#include <time.h>#include <string.h>int main(){ time_t t = time(NULL); struct tm tm = *localtime(&t); const char * months = {"January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"}; if (tm.tm_year == 2018 && strncmp(months, "November", strlen(months)) == 0 && tm.tm_mday == 10) { printf("Happy C Day!.\n"); } else { printf("The current month is %s.\n", months); }}
Tecnicamente, fa ciò che fanno gli altri esempi. Tuttavia, richiede più codice per ottenere lo stesso risultato. Per essere onesti, se avessi una maggiore familiarità con C, il codice potrebbe non essere più lungo dell’esempio Go.
Tuttavia, diciamo che questo è il minimo richiesto per ottenere lo stesso risultato. Se si confrontano i due, data la natura più prolissa della sintassi di C rispetto a Go, è più difficile da capire.
Inoltre, se non avessi precedenti esperienze con C, nonostante un punteggio di complessità ciclomatica comparativamente simile, quale sarebbe la tua percezione?
Considereresti il codice meno o più complicato? Quindi questo è un altro fattore essenziale nella comprensione della complessità del codice.
I vantaggi della complessità del software di misurazione
Ci sono quattro vantaggi principali della complessità del codice di misurazione, più uno in più.
Test migliori
Sapendo quanti percorsi indipendenti ci sono attraverso un pezzo di codice, sappiamo quanti percorsi ci sono da testare.
Non sto sostenendo la copertura del codice al 100%, spesso una metrica software priva di significato. Tuttavia, sostengo sempre un livello di copertura del codice tanto alto quanto pratico e possibile.
Quindi, sapendo quanti percorsi di codice ci sono, possiamo sapere quanti percorsi dobbiamo testare. Di conseguenza, si ha una misura di quanti test sono necessari, come minimo, per garantire che il codice sia coperto.
Rischio ridotto
Come dice il vecchio proverbio:
È più difficile leggere il codice che scriverlo.
Cosa c’è di più:
- Il codice viene letto molto più di quanto non sia scritto
- Un buon sviluppatore di software non dovrebbe mai essere valutato dalle righe di codice che hanno scritto (o modificato), ma dalla qualità del codice che hanno mantenuto.
Dato che, riducendo la complessità del codice, si riduce il rischio di introdurre difetti; siano essi piccoli o grandi, leggermente imbarazzanti o che inducano al fallimento.
Costi inferiori
Quando il rischio di potenziali difetti è ridotto, ci sono meno difetti da trovare e rimuovere. Di conseguenza, anche i costi di manutenzione si riducono.
Abbiamo tutti visto e abbiamo familiarità con i costi associati alla ricerca di difetti nelle varie fasi della vita di un software, come esemplificato nella tabella sottostante.
Quindi ha senso che, se comprendiamo la complessità del nostro codice e quali sezioni sono più complicate di altre, allora siamo in una posizione molto migliore per ridurre tale complessità.
Quindi, riducendo tale complessità, riduciamo la probabilità di introdurre difetti. Che scorre in tutte le fasi della vita di un software.
Maggiore prevedibilità
Riducendo la complessità del software, possiamo sviluppare con maggiore prevedibilità. Quello che intendo con questo è che siamo meglio in grado di dire—con sicurezza—quanto tempo una sezione di codice richiede per essere completata. Sapendo questo, siamo meglio in grado di prevedere quanto tempo un rilascio prende per spedire.
Sulla base di queste conoscenze l’azienda o l’organizzazione è meglio in grado di impostare i propri obiettivi e aspettative, in particolare quelli che sono direttamente dipendenti da detto software. Quando ciò accade, è più facile impostare budget realistici, previsioni e così via.
Aiuta gli sviluppatori a imparare
Aiutare gli sviluppatori a imparare e crescere è il vantaggio finale di capire perché il loro codice è considerato complesso. Gli strumenti che ho usato per valutare la complessità fino a questo punto non lo fanno.
Quello che fanno è fornire un punteggio di complessità generale o granulare. Tuttavia, uno strumento completo di complessità del codice, come Codacy, lo fa.
Nello screenshot qui sopra, possiamo vedere che, dei sei file elencati, uno ha una complessità di 30, un punteggio solitamente considerato piuttosto alto.
La complessità ciclomatica è un ottimo indicatore per capire se la qualità del codice si deteriora per ogni dato cambiamento. La complessità ciclomatica può essere più difficile da ragionare quando la si guarda o si confrontano interi moduli data la sua scala infinita e non essendo correlata alla dimensione del modulo. Tuttavia, qualcosa che potresti trovare utile è guardare l’elenco dei file di Codacy ordinati per priorità, che ti aiuterà a capire quali file sono candidati di scarsa qualità del codice, e quindi di conseguenza i loro moduli.
Questo è un involucro
Inoltre, questa è stata una discussione approfondita su quale sia la complessità del codice, come viene valutata, così come i vantaggi significativi della sua riduzione. Mentre c’è molto di più nella comprensione della complessità del codice di quanto ho coperto qui, abbiamo fatto molta strada per capirlo.
Se questa è la prima volta che senti parlare del termine o di conoscere uno qualsiasi degli strumenti, ti incoraggio a esplorare gli articoli e gli strumenti collegati, in modo da saperne di più. Se non si esegue il codice in Go o C, quindi Google “strumento di complessità del codice” più le lingue del software. Siete sicuri di trovare molti strumenti disponibili.
Per ulteriori suggerimenti per migliorare la qualità del codice controlla alcuni altri post del blog di Codacy.
Infine, se vuoi uno strumento completo per valutare la qualità del codice e uno che aiuti i tuoi sviluppatori a imparare e crescere, prova Codacy.
Codacy viene utilizzato da migliaia di sviluppatori per analizzare miliardi di righe di codice ogni giorno!
Iniziare è facile e gratuito! Basta usare il tuo account GitHub, Bitbucket o Google per iscriversi.
INIZIA