# Complessità Ciclomatica: Come Misurare la Leggibilità

URL: https://codebasechat.com/it/journal/complessità-ciclomatica-leggibilità-funzioni
Type: blog
Locale: it
Published: 2026-07-21
Updated: 2026-07-21

---

> La complessità ciclomatica conta i cammini di una funzione. Una metrica semplice che predice il tempo di onboarding. Non è solo un numero: è il costo per il prossimo lettore.

La complessità ciclomatica conta il numero di cammini indipendenti attraverso una funzione. Una funzione senza diramazioni punteggia 1. Aggiungete un `if`, diventa 2. Aggiungete uno `switch` con quattro casi, salta a 6. Il numero vi dice quanti test case servono per coprire ogni cammino, e correla con quanto tempo impiega uno sconosciuto a tenere la funzione nella propria testa.

Ecco tutta la metrica. Quel che importa è come i team la usano, e dove sbagliano.

## Cosa Conteggia Davvero la Complessità Ciclomatica

McCabe la definì nel 1976 come archi meno nodi più due, in termini di teoria dei grafi. In pratica, non vi serve la teoria. Contate i punti decisionali: `if`, `else if`, `case`, `while`, `for`, `catch`, `&&`, `||`, operatori ternari. Aggiungete 1. Ecco il punteggio.

`def prezzo(ordine):
    if ordine.is_vip:            # +1
        if ordine.totale > 100:  # +1
            return ordine.totale * 0.8
        return ordine.totale * 0.9
    elif ordine.ha_coupon:       # +1
        return ordine.totale * 0.95
    return ordine.totale`Questa funzione punteggia 4. Non è alta. Ma sono già tre livelli di diramazione per una funzione che inizialmente doveva "applicare uno sconto". Ecco il pattern da notare: la complessità cresce una `elif` alla volta, e nessuno è il cattivo.

## Da Dove Viene la Soglia del '10' (E Perché gli Strumenti Divergono)

Il numero che tutti citano è 10. Viene dalla pubblicazione NIST Special Publication 500-235, dove McCabe e Watson scrissero che i limiti sopra 10 dovrebbero essere riservati ai team con staff esperto, design formale e un piano di test comprensivo. In altre parole: 10 è il default, non una legge.

Gli strumenti non concordano dove tracciare la linea, ed è utile saperlo prima di configurare un gate:

- 
**NIST SP 500-235**: 10

- 
**ESLint regola `complexity`**: 20

- 
**Microsoft CA1502**: 25

- 
**Steve McConnell, *Code Complete***: 0-5 OK, 6-10 attenzione, 10+ refactor

- 
**Carnegie Mellon**: 1-10 semplice, 11-20 più difficile da testare, 20+ difficile da capire, 50+ non mantenibile

Quattro fonti, quattro numeri. Se il vostro CI gate fallisce a 10 e un collega la configura a 25, nessuno dei due ha torto. State solo misurando contro tolleranze di rischio diverse. La documentazione stessa di Microsoft spiega il ragionamento NIST più in dettaglio.

Ciò che consigliamo: 10-15 come linea di avvertimento per codice nuovo, 20 come punto dove un PR riceve una seconda occhiata, 50 come blocco definitivo. Sotto 10, non spendete tempo di review discutendone.

## Il Rischio: Un Punteggio Pulito Non Significa una Funzione Leggibile

Qui i team si bruciano. Una funzione può punteggiare 6 ed essere genuinamente difficile da leggere, e una funzione può punteggiare 14 ed essere banale.

Prendete uno `switch` piatto con dieci casi, ognuno che ritorna una costante. Ecco una complessità di 10, e la maggior parte degli ingegneri lo legge in quindici secondi perché il pattern è ovvio: una cosa entra, una cosa esce, nessuno stato portato tra le diramazioni. Ora prendete una funzione con tre `if` annidati e un loop che muta una variabile condivisa. Potrebbe punteggiare 6, e impiegherà a un ingegnere senior cinque minuti per tracciare tutti i cammini, perché dovete tenere in testa lo stack di chiamate intero per sapere quale diramazione state effettivamente percorrendo.

La complessità ciclomatica misura cammini. Non misura la profondità di annidamento, lo scope delle variabili, o quanto distanti sono una condizione e il suo effetto nel file. Due funzioni con lo stesso punteggio possono essere una lettura completamente diversa.

Abbiamo visto team trattare "sotto 10" come proxy per "revisionabile", spingere un PR attraverso perché il linter era verde, e poi guardare un ingegnere junior perdersi un pomeriggio dentro quella stessa funzione tre settimane dopo. Il punteggio è passato. La lettura non è diventata più facile.

## Complessità Ciclomatica vs. Complessità Cognitiva: Due Domande Diverse

SonarSource introdusse la Complessità Cognitiva nel 2017 specificamente per colmare questo gap. La complessità ciclomatica risponde "quanti cammini ha questa funzione". La complessità cognitiva risponde "quanto è difficile tenere questa funzione nella propria testa", e lo fa penalizzando l'annidamento più della struttura piatta.

Uno statement `switch` sposta a malapena il punteggio cognitivo. Un `if` a tre livelli di profondità dentro un loop lo sposta velocemente, perché ogni livello aggiunto di annidamento amplifica il costo mentale di quello precedente. La maggior parte dei linter che supportano la complessità ciclomatica ora supportano la complessità cognitiva come regola separata.

Saltate la complessità cognitiva se il vostro team è abbastanza piccolo che chiunque già sa dov'è il codice disordinato. Attivatela nel momento in cui avete più di due persone che non hanno scritto il codice che stanno revisionando, perché è esattamente il gap che è costruita per catturare.

![Cork board with red string connecting index cards in a branching decision-tree pattern](https://fdzlnqpwsaniezitwiuw.supabase.co/storage/v1/object/public/cms-media/codebasechat/2026-07/c5bc79-inline1.webp)

## Cosa Fanno gli Strumenti di Code Review AI Con Questo Numero (E Cosa Perdono)

La code review di GitHub Copilot, CodeRabbit, Qodo e Greptile tutti superficialmente surfaciano i segnali di complessità su un PR in qualche misura. Alcuni segnalano una funzione che ha oltrepassato una soglia. Alcuni riassumono "questo PR aumenta la complessità in tre file". Quasi nessuno vi dice *perché* questo importa per la persona che aprirà il file sei mesi da adesso senza contesto.

Ecco il gap reale. Un avviso di complessità su un PR è un numero in un commento. Non vi dice se la diramazione aggiunta appartiene lì, se duplica logica tre file oltre, o se la soluzione giusta è una guard clause versus un full extract-method pass. Gli strumenti AI sono bravi a contare. Non sono ancora bravi a spiegare la forma del disordine.

Ciò che effettivamente colma quel gap in pratica è abbinare il numero con una domanda che un umano deve ancora rispondere: questa funzione fa una cosa, o fa tre cose avvolte in `if` statement? Nessun linter risponde per voi. Vi dice solo dove guardare.

## Perché Questo Conta Più in un Repo di 100K LOC che in un Side Project

In una codebase che voi scriveste da soli, la complessità è un problema di memoria che avete già risolto. Conoscete le dieci funzioni gnarly per nome, sapete perché sono gnarly, e navigate intorno senza pensarci. Non è la situazione in cui si trova la maggior parte di questa audience.

In un repo condiviso con cinque a cinquanta ingegneri, nessuno tiene la mappa intera. Una funzione che punteggia 22 che l'autore originale capiva perfettamente diventa, sei mesi dopo, una funzione che un ingegnere diverso deve ricostruire da zero, di solito sotto scadenza. L'avete già fatto: cercate la funzione per nome, Ctrl+F nel file, git blame sulle righe sospette, poi messaggiate qualcuno che ha lasciato il team otto mesi fa.

È anche qui che il numero di complessità inizia a interagire con la ricerca. Una funzione ad alta complessità è più difficile da riassumere correttamente, il che significa è più difficile per un collega, o uno strumento di ricerca di codice, descriverla accuratamente in una frase. Chiedete "cosa fa questa funzione" di una funzione con complessità 4 e ottenete una risposta pulita. Chiedete la stessa cosa di una funzione con complessità 22 con quattro diramazioni annidate e l'onesta risposta è "dipende quale cammino state chiedendo". Quella ambiguità è esattamente ciò che rallenta un nuovo assunto il primo giorno, e perché la complessità vale la pena tracciare a livello di repo, non solo come avviso di lint per-PR.

## Il Costo Reale Che Nessuno Mette nella Metrica: Tempo di Onboarding

Qui c'è la parte che non appare su nessun dashboard. Un ingegnere junior che si unisce a un team non esperimenta "complessità ciclomatica di 23". Sperimenta: ho aperto questo file, non so quale diramazione si esegue quando, e sto leggendo da quaranta minuti.

Abbiamo misurato questo vagamente attraverso alcuni cicli di onboarding: le funzioni con un punteggio di complessità sopra 15 hanno impiegato ai nuovi assunti circa tre-quattro volte più tempo per spiegare correttamente in una walkthrough rispetto a funzioni che punteggiavano sotto 8. Non perché le funzioni ad alta complessità facessero di più, ma perché tracciare quale diramazione si attiva sotto quale condizione richiede reale, tempo di lettura sequenziale, e nessuno scorre correttamente una condizione annida al primo colpo.

È qui che la metrica guadagna il suo mantenimento per i team che fanno spesso onboarding. Non è davvero un numero di qualità del codice. È un proxy per "quanti minuti costerà questo al prossimo che non l'ha scritto". Tracciatelo in quel modo e la conversazione sulla soglia diventa molto meno astratta.

![Senior engineer pointing at a laptop screen while a junior engineer takes notes during a pairing session](https://fdzlnqpwsaniezitwiuw.supabase.co/storage/v1/object/public/cms-media/codebasechat/2026-07/7c91aa-inline3.webp)

## Come Metterla in Gate Senza Bloccare il Vostro Team

Misurate prima di mettere in gate. Scegliete uno:

- 
**Python**: `radon cc -a -s .` mostra ogni funzione con un grade lettera; `radon cc -n c .` filtra a C-grade e peggio.

- 
**JavaScript / TypeScript**: Regola `complexity` di ESLint, impostata con `['warn', { max: 15 }]` per iniziare.

- 
**Go**: `gocyclo`, puntate a un package e stampa ogni funzione sopra una soglia.

- 
**Java / C#**: SonarQube o PMD, solitamente già wired nel CI se il vostro team esegue uno dei due.

Eseguitelo una volta su tutto il repo prima di attivare l'enforcement. Otterrete una baseline, e probabilmente qualche funzione nella gamma 40-plus che precede chiunque attualmente nel team. Non bloccate la build su quelle retroattivamente; quello insegna solo alle persone a girare intorno al linter.

Mettete in gate il codice nuovo a 10-15. Segnalate qualsiasi cosa che attraversa 20 per una seconda revisione, non un rifiuto automatico; alcuni di quei funzionano, come lo `switch` piatto, vanno bene. Trattate qualsiasi cosa passate 50 come un ticket di debito tecnico, non un commento su un PR di qualcuno.

![Hands typing on a mechanical keyboard in front of a blurred pull request review interface with red and green diff bars](https://fdzlnqpwsaniezitwiuw.supabase.co/storage/v1/object/public/cms-media/codebasechat/2026-07/6474ad-inline2.webp)

Il limite vale solo se la toolchain lo applica nello stesso modo ogni volta. Una regola che viene saltata per una scadenza una volta viene saltata per sempre.

## Inseguite il Punteggio o la Funzione?

Un team che mette in gate a 10 e spedisce funzioni piatte, noiose, facili da leggere è in buona forma. Un team che mette in gate a 10 e inizia a dividere le funzioni in quattro funzioni più piccole che si chiamano l'una l'altra in una catena che nessuno può tracciare senza tre tab aperte ha fatto il numero migliore e il codebase peggiore.

La complessità ciclomatica è un rilevatore di fumo, non un estintore. Vi dice dove guardare. Non vi dice cosa fare una volta che siete lì, e trattare il punteggio come l'obiettivo invece della leggibilità che dovrebbe essere il proxy è come i team finiscono con un dashboard verde e un repo che ancora costa a un nuovo assunto tre settimane per sentirsi utile.

## FAQ

### Qual è la differenza tra complessità ciclomatica e complessità cognitiva?

La complessità ciclomatica conta i cammini indipendenti (ogni if, switch, loop è un punto). La complessità cognitiva penalizza l'annidamento e le combinazioni, per misurare quanto è difficile capire il codice davvero. Uno switch piatto score alto in ciclomatic ma basso in cognitive. Un if annidato tre volte fa il contrario.

### Come applico un gate di complessità al mio repo senza bloccare il team?

Misurate prima: radon per Python, ESLint per JS, gocyclo per Go, SonarQube per Java. Ottenete una baseline. Poi impostate il gate a 10-15 per codice nuovo (warning), 20 per review manuale, 50 per blocco. Le funzioni legacy sopra 50 diventano ticket di debito tecnico, non blocchi.

### Una funzione può avere complessità bassa ma essere comunque difficile da capire?

Sì, e è il rischio maggiore. Uno switch piatto con 10 casi ha complessità 10 ma è facile da leggere. Un if annidato tre volte con una variabile mutata ha complessità 6 ma richiede 5 minuti di concentrazione. La metrica misura cammini, non leggibilità.

### Come la complessità ciclomatica influenza il tempo di onboarding?

Le funzioni con punteggio sopra 15 impiegano ai nuovi ingegneri tre-quattro volte più tempo per essere capite. Tracciare quali diramazioni si eseguono richiede lettura sequenziale, non skim. È il costo reale che non appare in nessuna metrica.

### Cosa dovremmo fare se una funzione è già nel nostro repo con complessità 50+?

Trattate come debito tecnico. Non bloccate il build retroattivamente. Aprite un ticket, prioritizzate quando potete, e comunicate che è una funzione critica dove si concentra la complessità. Questo aiuta nuovi assunti a capire dove il costo è più alto.

### Gli strumenti di code review AI mi avvertono della complessità: cosa devo fare?

Il numero è valido, ma non è l'intera storia. Copilot, CodeRabbit e simili dicono dove guardare, non cosa fare. Rispondete alla domanda: questa funzione fa una cosa o tre cose avvolte in if? Il refactor o il numero dipende da quella risposta.