Cosa significa la "complessità ciclomatica" del mio codice?


42

Sono nuovo all'analisi statica del codice. La mia applicazione ha una complessità ciclomatica di 17.754. L'applicazione stessa è solo 37.672 righe di codice. È valido dire che la complessità è elevata in base alle righe di codice? Cosa mi sta dicendo esattamente la complessità ciclomatica?


Dipende interamente da cosa stai facendo. Se stai cercando di fare qualcosa di semplice, allora è molto, molto alto. Non dovresti avere quel rapporto in "ciao mondo", per esempio.
cwallenpoole,

Risposte:


48

Cosa mi sta dicendo esattamente la complessità ciclomatica?

La complessità ciclomatica non è una misura di righe di codice, ma il numero di percorsi indipendenti attraverso un modulo. La complessità ciclomatica di 17.754 significa che l'applicazione ha 17.754 percorsi unici attraverso di essa. Ciò ha alcune implicazioni, in genere in termini di quanto sia difficile comprendere e testare l'applicazione. Ad esempio, la complessità ciclomatica è il numero di casi di test necessari per ottenere una copertura del ramo del 100%, presupponendo test ben scritti.

Un buon punto di partenza potrebbe essere l' articolo di Wikipedia sulla complessità ciclomatica . Ha un paio di frammenti di pseudocodice e alcuni grafici che mostrano la complessità ciclomatica. Se vuoi saperne di più, puoi anche leggere l'articolo di McCabe in cui ha definito la complessità ciclomatica .

La mia applicazione ha una complessità ciclomatica di 17.754 righe di codice. L'applicazione stessa è solo 37.672 righe di codice. È valido dire che la complessità è elevata in base alle righe di codice?

Affatto. Un'applicazione con poche righe di codice e un numero elevato di condizionali nidificati all'interno di loop potrebbe avere una complessità ciclomatica estremamente elevata. D'altra parte, un'applicazione con poche condizioni potrebbe avere una bassa complessità ciclomatica. Ciò semplifica eccessivamente, ma penso che l'idea sia stata diffusa.

Senza sapere di più su ciò che fa l'applicazione, potrebbe essere normale avere una maggiore complessità ciclomatica. Suggerirei di misurare la complessità ciclomatica a livello di classe o metodo, invece che a livello di applicazione. Questo è un po 'più gestibile, concettualmente, penso - è più facile visualizzare o concettualizzare i percorsi attraverso un metodo piuttosto che i percorsi attraverso una grande applicazione.


36

La complessità ciclomatica è un modo per determinare se il codice deve essere sottoposto a refactoring. Il codice viene analizzato e viene determinato un numero di complessità. La complessità è determinata dalla ramificazione (se dichiarazioni, ecc.) La complessità potrebbe anche prendere in considerazione l'annidamento di loop, ecc. E altri fattori a seconda dell'algoritmo utilizzato.

Il numero è utile a livello di metodo. Ai livelli più alti è solo un numero.

Un numero di 17.754 indica la complessità a livello di progetto (codice totale), che non ha molto significato.

Il drill-down nella complessità a livello di classe e di metodo determinerà le aree del codice che devono essere rifattorizzate in metodi più piccoli o ridisegnate per eliminare la complessità.

Prendi in considerazione una CASEdichiarazione con 50 casi in un metodo. Forse ogni stato ha una diversa logica aziendale. Ciò genererà una complessità ciclomatica di 50. Ci sono 50 punti decisionali. Potrebbe essere necessario riprogettare l'istruzione CASE utilizzando un modello di fabbrica per eliminare la logica di diramazione. A volte puoi refactoring (suddividere il metodo in parti più piccole) e in alcuni casi solo una riprogettazione ridurrà la complessità.

In generale, per la complessità a livello di metodo:

  • <10 Facile da mantenere
  • 11-20 Più difficile da mantenere
  • 21+ candidati per refactoring / riprogettazione

Considera anche che complessità più elevate rendono il codice più difficile da testare.

La massima complessità che ho visto su un singolo metodo era 560. Erano circa 2000 righe di istruzioni if ​​in un metodo. Fondamentalmente non mantenibile, non verificabile, pieno di potenziali bug. Immagina tutti i casi di test unitari necessari per quella logica di ramificazione! Non bene.

Cerca di mantenere tutti i metodi sotto i 20 anni e renditi conto che c'è un costo per il refactoring di qualsiasi metodo per renderlo meno complesso.


Questa è una risposta migliore
Pacerier,

2
@Pacerier In tal caso, semplicemente vota la risposta;).
Zero3

> "In generale, per la complessità a livello di metodo" Citazione?
Benny Bottema,

Una delle applicazioni originali di McCabe era limitare la complessità delle routine durante lo sviluppo del programma; ha raccomandato ai programmatori di contare la complessità dei moduli che stanno sviluppando e di dividerli in moduli più piccoli ogni volta che la complessità ciclomatica del modulo ha superato 10.
Jon Raynor,

"Potrebbe essere necessario riprogettare l'istruzione CASE utilizzando un modello di fabbrica per eliminare la logica di diramazione." Perché? Ciò non elimina la complessità della logica; lo nasconde e lo rende meno evidente, e quindi più difficile da mantenere.
Mason Wheeler,

1

È il numero di percorsi distinti nella tua applicazione. Dai un'occhiata a questo articolo IBM su CC .

Sembra alto ma nel tuo caso è l'aggiunta del CC di tutti i tuoi metodi di tutte le tue classi e metodi. I miei esempi sono molto estesi poiché non so come sia strutturato il tuo codice ma potresti anche avere un metodo monster con 37672 righe di codice o 3767 metodi con circa 10 righe di codice. Ciò che intendo è che a livello di applicazione, questo indicatore non significa molto, ma a livello di metodo può aiutarti a ottimizzare / riscrivere il tuo codice in metodi più piccoli in modo che siano meno inclini a errori.

Quello che ho letto personalmente molte volte è che i metodi con un CC superiore a 10 hanno maggiori rischi di difetti.

Uso Sonar per testare la qualità del codice delle mie applicazioni e per impostazione predefinita penso che generi un avviso se si hanno metodi con +10 CC. Ciò non può significare nulla. Un esempio concreto: se usi Eclipse per generare un equalsmetodo basato sulle proprietà del tuo bean, il CC andrà molto rapidamente sopra il tetto ...


1
L'impostazione predefinita di PMD è di avvisare anche di una complessità ciclomatica di 10. Guardare la complessità a livello di metodo consente anche di ignorare i metodi che potrebbero avere buone ragioni per CC elevati, come i equalsmetodi generati .
Thomas Owens

Non ero sicuro, quindi ho controllato, ma Sonar utilizza internamente PMD per ottenere questa misura. Quindi tutto ha un senso :-)
Jalayn il

-1

Dipende dallo strumento che hai usato. Alcuni degli strumenti open source là fuori prendono classe come modulo o altro livello di struttura come modulo. Pertanto, più un progetto diventa grande, maggiore è la complessità ciclomatica che tende ad ottenere. Tuttavia, per la mia comprensione personale, dovrebbe essere su una base funzionale. Dal momento in cui un progetto diventa più grande, le funzioni che frequenta.

Ti consiglio di usare lo strumento chiamato Lizard e puoi trovare il codice risorsa e scaricare il file zip su github. Ha anche una versione online se non ci sono molte informazioni riservate nel tuo codice.

Il CCN significativo di cui dovresti preoccuparti è su una base funzionale diversa da qualsiasi altra. Inoltre, mantenere CCN di ogni funzione unber 15 sarebbe la gamma ideale.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.