Que signifie la "complexité cyclomatique" de mon code?


42

Je suis nouveau à l'analyse statique du code. Mon application a une complexité cyclomatique de 17 754. L'application elle-même ne contient que 37 672 lignes de code. Est-il valide de dire que la complexité est élevée en fonction des lignes de code? Qu'est-ce que la complexité cyclomatique me dit exactement?


Cela dépend entièrement de ce que vous faites. Si vous essayez de faire quelque chose de simple, c'est très élevé. Vous ne devriez pas avoir ce ratio dans "hello world", par exemple.
Cwallenpoole

Réponses:


48

Qu'est-ce que la complexité cyclomatique me dit exactement?

La complexité cyclomatique n'est pas une mesure de lignes de code, mais le nombre de chemins indépendants traversant un module. Votre complexité cyclomatique de 17 754 signifie que votre application comporte 17 754 chemins uniques. Cela a quelques implications, généralement quant à la difficulté de comprendre et de tester votre application. Par exemple, la complexité cyclomatique est le nombre de tests requis pour atteindre une couverture de 100% des branches, en supposant des tests bien écrits.

L' article de Wikipedia sur la complexité cyclomatique constitue un bon point de départ . Il contient quelques extraits de pseudocode et des graphiques qui montrent toute la complexité cyclomatique. Si vous voulez en savoir plus, vous pouvez également lire le papier de McCabe dans lequel il définit la complexité cyclomatique .

Mon application a une complexité Cyclomatic de 17 754 lignes de code. L'application elle-même ne contient que 37 672 lignes de code. Est-il valide de dire que la complexité est élevée basée sur les lignes de code?

Pas du tout. Une application comportant peu de lignes de code et un grand nombre de conditions imbriquées dans des boucles peut avoir une complexité cyclomatique extrêmement élevée. D'autre part, une application avec peu de conditions peut avoir une faible complexité cyclomatique. Cela simplifie beaucoup, mais je pense que cela fait passer l’idée.

Sans en savoir plus sur ce que fait votre application, il peut être normal d'avoir une complexité cyclomatique plus élevée. Je suggérerais toutefois de mesurer la complexité cyclomatique au niveau d'une classe ou d'une méthode plutôt que simplement au niveau de l'application. Je pense que c'est un peu plus gérable, conceptuellement: il est plus facile de visualiser ou de conceptualiser les chemins via une méthode que les chemins via une application volumineuse.


36

La complexité cyclomatique permet de déterminer si votre code doit être refactorisé. Le code est analysé et un nombre de complexité est déterminé. La complexité est déterminée par la création de branches (si des instructions, etc.). La complexité peut également prendre en compte l'imbrication de boucles, etc., ainsi que d'autres facteurs en fonction de l'algorithme utilisé.

Le nombre est utile au niveau de la méthode. Aux niveaux supérieurs, ce n'est qu'un chiffre.

Un nombre de 17 754 indique la complexité au niveau du projet (code total), ce qui n'a pas beaucoup de sens.

Une analyse approfondie de la complexité de la classe et du niveau de la méthode déterminera les zones du code qui doivent être restructurées en méthodes plus petites ou redéfinies pour en éliminer la complexité.

Considérons une CASEdéclaration avec 50 cas dans une méthode. Peut-être que chaque état a une logique métier différente. Cela générera une complexité cyclomatique de 50. Il y a 50 points de décision. Il peut être nécessaire de repenser l'instruction CASE à l'aide d'un modèle d'usine pour supprimer la logique de branchement. Parfois, vous pouvez refactoriser (diviser la méthode en parties plus petites) et dans certains cas, seule une refonte réduira la complexité.

En général, pour la complexité du niveau de la méthode:

  • <10 Facile à entretenir
  • 11-20 Plus difficile à maintenir
  • 21+ candidats pour refactoring / refonte

Considérez également que des complexités plus élevées rendent le code plus difficile à tester.

La complexité la plus élevée que j'ai vue sur une seule méthode était de 560. Il s'agissait d'environ 2000 lignes d'instructions if dans une méthode. Essentiellement intangible, indestructible, plein de bugs potentiels. Imaginez tous les cas de tests unitaires nécessaires à cette logique de branchement! Pas bon.

Essayez de garder toutes les méthodes moins de 20 ans et réalisez qu'il y a un coût à refactoriser n'importe quelle méthode pour la rendre moins complexe.


C'est une meilleure réponse.
Pacerier

2
@Pacerier Dans ce cas, il suffit de lever la réponse;).
Zero3

> "En général, pour la complexité du niveau de la méthode" Citation?
Benny Bottema

L'une des applications originales de McCabe était de limiter la complexité des routines lors du développement du programme; il a recommandé que les programmeurs doivent compter la complexité des modules qu'ils développent, et les diviser en petits modules à chaque fois que la complexité cyclomatique du module a dépassé 10.
Jon Raynor

"L’instruction CASE devra peut-être être repensée à l’aide d’un modèle d’usine pour supprimer la logique de branchement." Pourquoi? Cela n'élimine pas la complexité de la logique; cela le cache et le rend moins apparent, et donc plus difficile à maintenir.
Mason Wheeler

1

C'est le nombre de chemins distincts dans votre application. Consultez cet article d'IBM sur CC .

Cela semble élevé, mais dans votre cas, il s'agit de l'ajout du CC de toutes vos méthodes, de toutes vos classes et méthodes. Mes exemples sont très étendus car je ne sais pas comment votre code est structuré, mais vous pouvez aussi avoir une méthode monstre avec 37672 lignes de code ou 3767 méthodes avec environ 10 lignes de code. Ce que je veux dire, c'est qu'au niveau de l'application, cet indicateur ne veut pas dire grand chose, mais au niveau de la méthode, il peut vous aider à optimiser / réécrire votre code en méthodes plus petites afin qu'elles soient moins sujettes aux erreurs.

Ce que j’ai personnellement lu maintes fois, c’est que les méthodes avec un CC supérieur à 10 présentent un risque plus élevé de défauts.

J'utilise Sonar pour tester la qualité du code de mes applications et par défaut, je pense que cela déclenche un avertissement si vous avez des méthodes avec +10 CC. Cela ne veut toujours rien dire. Un exemple concret: si vous utilisez Eclipse pour générer une equalsméthode basée sur les propriétés de votre grain, le CC ira très vite au-dessus du toit ...


1
Le paramètre par défaut de PMD est également de signaler une complexité cyclomatique de 10. L'analyse de la complexité au niveau de chaque méthode vous permet également de ne pas prendre en compte les méthodes qui pourraient avoir de bonnes raisons pour une CC élevée, telles que les equalsméthodes générées .
Thomas Owens

Je ne savais pas trop alors j'ai vérifié, mais Sonar utilise en interne PMD pour obtenir cette mesure. Cela a donc du sens :-)
Jalayn

-1

Cela dépend de quel outil avez-vous utilisé. Certains des outils open source utilisent la classe en tant que module ou un autre niveau de structure en tant que module. Par conséquent, plus un projet est volumineux, plus il a tendance à se complexifier. Cependant, pour ma compréhension personnelle, cela devrait être sur une base de fonction. Étant donné que plus un projet est volumineux, les fonctions qu’il assume doivent être remplies.

Je vous recommande d'utiliser l'outil appelé Lizard. Vous pouvez trouver le code de la ressource et télécharger le fichier zip sur github. Il existe également une version en ligne s'il n'y a pas beaucoup d'informations confidentielles dans votre code.

Le CCN significatif dont vous devez vous préoccuper est basé sur une base de fonctions différente des autres. De plus, conserver le numéro CCN de chaque fonction inférieur à 15 serait la plage idéale.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.