Métriques de code
Libérez la puissance des métriques de code avec CppDepend
Pour apprendre les métriques, vous pouvez imprimer Expert en visualisation placemat par Stuart Celarier MVP (Corillian) ou vous pouvez imprimer ceci Aide-mémoire des métriques par Frank-Leonardo Quednau.
- 8 métriques sur l’application: NbLinesOfCode, NbLinesOfComment, PercentageComment, NbProjects, NbNamespaces, NbTypes, NbMethods, NbFields
- 14 métriques sur les projets : NbLinesOfCode, NbLinesOfComment, PercentageComment, NbNamespaces, NbTypes, NbMethods, NbFields, Assembly level, Afferent coupling (Ca), Efferent coupling (Ce), Relational Cohesion(H), Instability (I), Abstractness (A), Distance from main sequence (D)
- 9 métriques sur les espaces de noms : NbLinesOfCode, NbLinesOfComment, PercentageComment, NbTypes, NbMethods, NbFields, Project level, Afferent coupling at namespace level (NamespaceCa), Efferent coupling at namespace level (NamespaceCe)
- 16 métriques sur les types : NbLinesOfCode, NbLinesOfComment, PercentageComment, NbMethods, NbFields, Type level, Type rank, Afferent coupling at type level (TypeCa), Efferent coupling at type level (TypeCe), LCOM, LCOM HS, Cyclomatic Complexity, Size of instance, ABC, NOC, DIT
- 11 métriques sur les méthodes : NbLinesOfCode, NbLinesOfComment, PercentageComment, Method level, Method rank, MethodCa, MethodCe, Cyclomatic Complexity, NbParameters, NbVariables, NbOverloads
- 2 métriques sur les champs : Taille d’instance, FieldCa
- 11 Métriques de Halstead : Total Operators, Total Operands, Distinct Operators, Distinct Operands, Halstead Program Length, Halstead Program Volume, Halstead Program Level, Halstead Program Difficulty, Halstead Programming Effort, Halstead Programming Time, Halstead Intelligent Content
Métriques de dette technique
Depuis la version 2017.1.0, CppDepend offre estimation intelligente de la dette technique d’une base de code.
Fondamentalement, chaque règle de code CppDepend produit des problèmes, et pour chaque problème, des formules C# personnalisables estiment coût de correction ces problèmes en temps-personne.
Ce coût de correction peut être vu comme dette que l'équipe possède : tant que le problème n'est pas corrigé, la dette n'est pas remboursée, et elle porte des intérêts sous forme de friction de développement. La dette technique de la base de code est la somme de toutes ces estimations de dette.
La dette technique peut être vue comme mère de toutes les métriques de code.
- Toutes les autres métriques de code — lignes de code, complexité, couverture de code, couplage ... — peuvent être exploitées via des règles de code avec des seuils. Les règles créent des problèmes lors de violations des seuils de métriques de code.
- Et pour chaque problème, nous pouvons estimer le coût de correction en termes de temps-personne.
- Pour chaque problème, nous pouvons aussi estimer le gravité en termes de temps humain par an consommé à cause du problème non corrigé conséquences.
Vous trouverez ci-dessous les détails techniques de chaque métrique de code prise en charge par CppDepend. L'estimation de la dette technique a sa propre page de documentation.
Visualisation des métriques de code
CppDepend est livré avec un tableau de bord pour visualiser rapidement toutes les métriques de l'application. Le tableau de bord est disponible à la fois dans l'extension Visual Studio et dans le rapport.
Pour chaque métrique, le tableau de bord affiche le diff depuis la baseline. Il indique aussi si la valeur de la métrique s'améliore (en vert) ou se dégrade (en rouge).
Chaque valeur est cliquable pour explorer en détail. Par exemple, cliquer sur le nombre de types liste tous les types de la base de code.

CppDepend offre également une visualisation spéciale des métriques via une treemap colorée. Une telle visualisation est particulièrement utile pour parcourir la couverture de code par les tests des méthodes ou classes de votre base de code.

Métriques sur l’application
NbLinesOfCode
Notez que le LOC d'un type est la somme des LOC de ses méthodes, le LOC d'un namespace est la somme des LOC de ses types, le LOC d'un projet est la somme des LOC de ses namespaces et le LOC d'une application est la somme des LOC de ses projets.
- Les méthodes abstraites et les énumérations ont une LOC égale à 0. Seul le code concret effectivement exécuté est pris en compte dans le calcul de LOC.
- Les déclarations de namespaces, types, champs et méthodes ne sont pas considérées comme des lignes de code car elles n'ont pas de points de séquence correspondants.
Recommandations : Les méthodes dont NbLinesOfCode dépasse 20 sont difficiles à comprendre et à maintenir.
NbLinesOfComment
Défini pour l'application, les projets, les namespaces, les types, les méthodes.
Recommandations : Cette métrique n'est pas utile pour évaluer la qualité du code source. Nous préférons utiliser la métrique PercentageComment.
PercentageComment
Défini pour l'application, les projets, les namespaces, les types, les méthodes.
PercentageComment = 100*NbLinesOfComment / ( NbLinesOfComment + NbLinesOfCode)
Recommandations : Le code dont le pourcentage de commentaires est inférieur à 20 % devrait être davantage commenté. Cependant, un code trop commenté (>40 %) n'est pas nécessairement une bénédiction, car il peut être considéré comme une insulte à l'intelligence du lecteur.
NbProjects
Défini pour l'application - Le nombre de projets.
NbNamespaces
Défini pour l'application et les projets. Le nombre de namespaces. Le namespace anonyme compte pour un. Si un namespace est défini sur N projets, il comptera pour N. Les namespaces déclarés dans les projets framework ne sont pas pris en compte.
NbTypes
Défini pour l'application, les projets, les namespaces. Le nombre de types. Un type peut être une classe abstraite ou concrète, une structure, une énumération.
NbMethods
Défini pour l'application, les projets, les namespaces, les types. Le nombre de méthodes. Une méthode peut être une méthode abstraite, virtuelle ou non virtuelle, une méthode déclarée dans une interface, un constructeur, un constructeur de classe, un finaliseur, un getter ou setter de propriété/indexeur, un ajouteur ou supprimeur d'événement.
Recommandations : Les types où NbMethods > 20 peuvent être difficiles à comprendre et à maintenir, mais il peut y avoir des cas où une valeur élevée de NbMethods est pertinente.
NbFields
Défini pour l'application, les projets, les namespaces, les types. Le nombre de champs.
Recommandations : Les types où NbFields est supérieur à 20 peuvent être difficiles à comprendre et à maintenir, mais il peut y avoir des cas où une valeur élevée de NbFields est pertinente.
Métriques sur les projets
En mesurant le couplage entre les types de votre application, CppDepend évalue la stabilité de chaque projet. Un projet est considéré comme stable si ses types sont utilisés par de nombreux types de projets tiers (c.-à-d. stable = pénible à modifier). Si un projet contient beaucoup de types abstraits et peu de types concrets, il est considéré comme abstrait. Ainsi, CppDepend vous aide à détecter quels projets sont potentiellement pénibles à maintenir (c.-à-d. concrets et stables) et quels projets sont potentiellement inutiles (c.-à-d. abstraits et instables).
Remarque : Cette théorie et ces métriques ont été introduites en premier par l'excellent livre Agile Software Development: Principles, Patterns, and Practices in C# Robert C. Martin (Prentice Hall PTR, 2006)
Couplage afférent (Ca)
Le nombre de types en dehors de ce projet qui dépendent de types à l'intérieur de ce projet. Un couplage afférent élevé indique que les projets concernés ont de nombreuses responsabilités.
Couplage efférent (Ce)
Le nombre de types à l'intérieur de ce projet qui dépendent de types en dehors de ce projet. Un couplage efférent élevé indique que le projet concerné est dépendant.
Cohésion relationnelle (H)
Nombre moyen de relations internes par type. Soit R le nombre de relations de types internes à ce projet (c.-à-d. qui ne se connectent pas à des types en dehors du projet). Soit N le nombre de types dans le projet. H = (R + 1)/ N. Le 1 supplémentaire dans la formule évite H=0 quand N=1. La cohésion relationnelle représente la relation que ce projet entretient avec tous ses types.
Recommandations : Comme les classes à l'intérieur d'un projet devraient être fortement liées, la cohésion devrait être élevée. D'un autre côté, des valeurs trop élevées peuvent indiquer un sur-couplage. Une bonne plage pour RelationalCohesion est de 1,5 à 4,0.
Instabilité (I)
Le rapport du couplage efférent (Ce) au couplage total. I = Ce / (Ce + Ca). Cette métrique est un indicateur de la résilience du package au changement. La plage de cette métrique est de 0 à 1, où I=0 indique un package totalement stable et I=1 un package totalement instable.
Abstraction (A)
Le rapport entre le nombre de types abstraits internes et le nombre de types. La plage de cette métrique est de 0 à 1, où A=0 indique un projet totalement concret et A=1 un projet totalement abstrait.
Distance à la séquence principale (D)
La distance perpendiculaire normalisée d'un projet par rapport à la ligne idéalisée A + I = 1 (appelée séquence principale). Cette métrique est un indicateur de l'équilibre du projet entre abstraction et stabilité. La plage est de 0 à 1, où D=0 indique un projet coïncidant avec la séquence principale et D=1 un projet aussi éloigné que possible de la séquence principale.
Recommandations : Les projets dont NormDistFromMainSeq dépasse 0.7 peuvent être problématiques.
Métriques sur les espaces de noms
Couplage afférent au niveau espace de noms (NamespaceCa)
L'Afferent Coupling d'un namespace donné est le nombre de namespaces qui en dépendent directement.
Couplage efférent au niveau espace de noms (NamespaceCe)
Le couplage efférent (Efferent Coupling) pour un namespace particulier est le nombre de namespaces dont il dépend directement. Notez que les namespaces déclarés dans les projets framework sont pris en compte.
Niveau
Défini pour les projets, namespaces, types, méthodes. La valeur Level d'un namespace est définie comme suit :
- Level = 0 : if the namespace doesn't use any other namespace.
- Level = 1 : if the namespace only uses directly namespace defined in tierce projects.
- Level = 1 + (Max Level over namespace it uses directly)
- Level = N/A : if the namespace is involved in a dependency cycle or uses directly or indirectly a namespace involved in a dependency cycle.
Recommandations : Cette métrique aide à classer objectivement les projets, namespaces, types et méthodes comme haut niveau, niveau intermédiaire ou bas niveau. Cette métrique est également utile pour découvrir les cycles de dépendances dans votre application.
Métriques sur les types
Rang du type
Les valeurs TypeRank sont calculées en appliquant le Google PageRank algorithme sur le graphe des dépendances des types. Une homothétie de centre 0,15 est appliquée pour que la moyenne de TypeRank soit de 1.
Recommandations : Les types avec un TypeRank élevé devraient être testés plus soigneusement car les bugs dans ces types seront probablement plus catastrophiques.
Couplage afférent au niveau type (TypeCa)
L'Afferent Coupling d'un type donné est le nombre de types qui en dépendent directement.
Couplage efférent au niveau type (TypeCe)
Le couplage efférent (Efferent Coupling) pour un type particulier est le nombre de types dont il dépend directement. Notez que les types déclarés dans les projets framework sont pris en compte.
Recommandations : Les types où TypeCe > 50 sont des types qui dépendent de trop d'autres types. Ils sont complexes et ont plus d'une responsabilité. Ce sont de bons candidats pour la refactorisation.
Manque de cohésion des méthodes (LCOM)
Le principe de responsabilité unique stipule qu'une classe ne devrait pas avoir plus d'une raison de changer. Une telle classe est dite cohésive. Une valeur LCOM élevée signale généralement une classe peu cohésive. Le LCOM prend ses valeurs dans la plage [0-1]. Le LCOM HS (HS pour Henderson-Sellers) prend ses valeurs dans la plage [0-2]. Une valeur LCOM HS supérieure à 1 devrait être considérée comme alarmante.
Algorithmes utilisés par CppDepend :
- LCOM = 1 – (sum(MF)/M*F)
- LCOM HS = (M – sum(MF)/F)(M-1)
- Où : M est le nombre de méthodes de la classe, F est le nombre de champs d'instance de la classe, MF est le nombre de méthodes de la classe accédant à un champ d'instance particulier.
Recommandations : Les types où LCOM > 0.8 et NbFields > 10 et NbMethods > 10 peuvent être problématiques. Les types où LCOMHS > 1.0 et NbFields > 10 et NbMethods > 10 devraient être évités.
Complexité cyclomatique (CC)
Défini pour les types et les méthodes. La complexité cyclomatique est une métrique logicielle procédurale populaire égale au nombre de décisions qui peuvent être prises dans une procédure. Concrètement, en C++, la CC d'une méthode est 1 + {le nombre d'expressions suivantes trouvées dans le corps de la méthode}:
Compté : if | while | for | case | default | continue | goto | && | || | catch | ternary operator ?: | ??
Non compté : else | do | switch | try | using | throw | finally | return | object creation | method call | field access
Recommandations : Les méthodes où la CC est supérieure à 15 sont difficiles à comprendre et à maintenir. Les méthodes où la CC est supérieure à 30 sont extrêmement complexes et devraient être divisées en méthodes plus petites (sauf si elles sont générées automatiquement par un outil).
Taille de l'instance
Défini pour les champs d'instance et les types. La taille des instances d'un champ d'instance est définie comme la taille, en octets, des instances de son type. La taille de l'instance d'un champ statique est égale à 0.
La taille des instances d'une classe ou d'une structure est définie comme la somme de la taille des instances de ses champs plus la taille des instances de sa classe de base.
Recommandations : Les types dont SizeOfInst dépasse 64 peuvent dégrader les performances et être difficiles à maintenir.
Association Between Class (ABC)
La métrique Association Between Classes pour une classe ou une structure particulière est le nombre de membres d'autres types qu'elle utilise directement dans le corps de ses méthodes.
Nombre d'enfants (NOC)
Le nombre d'enfants d'une classe est le nombre de sous-classes (quelle que soit leur position dans la sous-branche de l'arbre d'héritage). Le nombre d'enfants d'une interface est le nombre de types qui l'implémentent. Dans les deux cas, le calcul de cette métrique ne compte que les types déclarés dans le code de l'application.
Profondeur de l'arbre d'héritage (DIT)
La Depth of Inheritance Tree d'une classe ou d'une structure est son nombre de classes de base (y compris la classe System.Object, donc DIT >= 1).
Recommandations : Les types dont DepthOfInheritance dépasse 6 peuvent être difficiles à maintenir.
Métriques sur les méthodes
Rang de la méthode
Les valeurs MethodRank sont calculées en appliquant le Google PageRank algorithme sur le graphe des dépendances des méthodes. Une homothétie de centre 0,15 est appliquée pour que la moyenne de MethodRank soit de 1.
Recommandations : Les méthodes avec un MethodRank élevé devraient être testées plus soigneusement car les bugs dans ces méthodes seront probablement plus catastrophiques.
Couplage afférent au niveau méthode (MethodCa)
L'Afferent Coupling d'une méthode donnée est le nombre de méthodes qui en dépendent directement.
Couplage efférent au niveau méthode (MethodCe)
Le couplage efférent (Efferent Coupling) pour une méthode particulière est le nombre de méthodes dont elle dépend directement. Notez que les méthodes déclarées dans les projets framework sont prises en compte.
NbParameters
Le nombre de paramètres d'une méthode. Ref et Out sont également comptés. La référence this passée aux méthodes d'instance en IL n'est pas comptée comme un paramètre.
Recommandations : Les méthodes dont NbParameters dépasse 5 peuvent être pénibles à appeler et dégrader les performances.
NbVariables
Le nombre de variables déclarées dans le corps d'une méthode.
Recommandations : Les méthodes où NbVariables est supérieur à 8 sont difficiles à comprendre et à maintenir. Les méthodes où NbVariables est supérieur à 15 sont extrêmement complexes et devraient être divisées en méthodes plus petites.
NbOverloads
Le nombre de surcharges d'une méthode. Si une méthode n'est pas surchargée, sa valeur NbOverloads est égale à 1. Cette métrique s'applique également aux constructeurs.
Recommandations : Les méthodes dont NbOverloads dépasse 6 peuvent poser des problèmes de maintenance et provoquer un couplage plus élevé que nécessaire.
Métriques sur les champs
Couplage afférent au niveau champ (FieldCa)
L'Afferent Coupling d'un champ donné est le nombre de méthodes qui l'utilisent directement.
Métriques Halstead
CppDepend calcule diverses métriques Halstead, telles que définies par Maurice H. Halstead dans Elements of Software Science (1977). Les métriques Halstead sont basées sur des définitions d'opérateurs et d'opérandes.
- opérateurs : les opérateurs arithmétiques ('+'), d'égalité/inégalité ('<'), d'affectation ('+='), de décalage ('>>'), logiques ('&&') et unaires ('*'). Les mots réservés pour spécifier les points de contrôle ('while') et l'infrastructure de contrôle ('else'), le type ('double') et le stockage ('extern'). Les appels de fonctions, références de tableaux, etc.
- opérandes : identifiants, littéraux, étiquettes et noms de fonctions. Chaque littéral est traité comme un opérande distinct.
Opérateurs totaux (N1)
Défini pour les types et méthodes. Le nombre total d'opérateurs présents.
Opérandes totaux (N2)
Défini pour les types et méthodes. Le nombre total d'opérandes présents.
Opérateurs distincts (n1)
Défini pour les types et méthodes. Le nombre d'opérateurs distincts présents.
Opérandes distincts (n2)
Défini pour les types et méthodes. Le nombre d'opérandes distincts présents. Comme noté ci-dessus, chaque constante est traitée comme distincte.
Longueur de programme Halstead (N)
N = N1 + N2
La longueur de programme Halstead décrit la taille du programme abstrait obtenu en supprimant tout, sauf les opérateurs et les opérandes, du programme original.
Volume de programme Halstead (V)
V = N * log2(n1 + n2)
Ceci modélise le nombre de bits nécessaires pour stocker le programme abstrait de longueur N.
Niveau de programme Halstead (L)
L = (2/n1)*(n2/N2)
L décrit le rapport entre le volume V du programme actuel et le volume V* de l'implémentation la plus compacte du même algorithme.
Difficulté de programme Halstead (D)
D = (n1/2) * (N2/n2) = 1/L
Difficulty est l'inverse de Level. Difficulty augmente avec le nombre d'opérateurs distincts.
Effort de programmation Halstead (E)
E = D * V
La formulation de Halstead pour l'effort requis pour écrire (ou comprendre) un programme caractérise l'effort comme proportionnel à la fois à la difficulté et au volume.
Temps de programmation Halstead (T)
T = E/18 secondes
Le temps de programmation est considéré comme directement proportionnel à l'effort de programmation.
Contenu intelligent Halstead (I)
I = V / D
Halstead a conçu cette métrique comme une mesure indépendante du langage de la complexité algorithmique.
Essayez CppDepend aujourd'hui
Commencez votre essai gratuit de 14 jours avec accès complet à toutes les fonctionnalités de documentation. Sans carte bancaire.
