Agence web » Actualités du digital » Qu’est-ce que la complexité cyclomatique? Mesurer la qualité du code –

Qu’est-ce que la complexité cyclomatique? Mesurer la qualité du code –

Shutterstock / fran_kie

La complexité cyclomatique est une métrique de code que vous pouvez afficher dans de nombreux IDE comme Visual Studio. Bien que ce ne soit pas une science exacte, cela vous permet d’avoir une idée générale de la complexité des fonctions, des classes et des espaces de noms, ce qui peut être utile lors de la recherche de code à refactoriser.

Qu’est-ce que la complexité cyclomatique?

La complexité cyclomatique mesure essentiellement la quantité de branches de votre code. Chaque fois qu’il y a un if instruction ou autre bloc de contrôle comme une boucle, la complexité cyclomatique augmente, puisque le graphe ressemblera de plus en plus à un arbre.

Si vous imaginez votre code comme une série d’actions (fonctions, appels de méthode, affectations de variables) connectées via un flux de contrôle, vous obtiendrez un graphique abstrait que vous pourrez utiliser pour mieux comprendre la complexité. Pour les flux de contrôle courants comme if déclarations et for boucles, les graphiques ressemblent à ceci:

La formule est simple; prenez le nombre d’arêtes dans le graphe (les flèches reliant tout) et soustrayez le nombre de nœuds dans le graphe (les actions elles-mêmes).

Complexity = Edges -- Nodes + 2

Par exemple, ce code a une complexité cyclomatique de un, car il n’y a pas de branches, et il appelle simplement WriteLine encore et encore. Comme il s’agit simplement d’un code parfaitement linéaire, le nombre de nœuds annulera le nombre d’arêtes, donnant une complexité cyclomatique de un.

public void TestFunction()
{
    Console.WriteLine("Test");
    Console.WriteLine("Test");
    Console.WriteLine("Test");
    Console.WriteLine("Test");
    Console.WriteLine("Test");
}

Pour un code plus compliqué avec des branches, la complexité sera plus élevée. Ce code, qui contient un switch instruction, a une complexité de 6, car le code peut emprunter de nombreux chemins différents. Chaque case dans l’instruction switch ajoute de la complexité, car elle peut conduire à des sorties différentes avec des entrées différentes.

public void TestFunction(string arg)
{
    switch(arg)
    {
        case "one":
            Console.WriteLine("Test");
            break;
        case "two":
            Console.WriteLine("Test");
            break;
        case "three":
            Console.WriteLine("Test");
            break;
        case "four":
            Console.WriteLine("Test");
            break;
        case "five":
            Console.WriteLine("Test");
            break;
    }
 
    Console.WriteLine("Test");
}

La complexité cyclomatique n’est calculée que dans le cadre de la fonction. Si une fonction appelle une autre fonction qui a une complexité cyclomatique élevée, elle ne compte que comme un seul nœud et n’ajoute rien à l’appelant, malgré l’ajout technique de complexité au programme dans un sens général.

La complexité cyclomatique est-elle utile?

La complexité cyclomatique n’est pas une métrique parfaite. C’est une métrique très basique et examine la nuance du code lui-même. Bien sûr, vous pouvez toujours avoir un code terrible avec une faible complexité ou un code décent avec une complexité élevée. Mais, en général, c’est toujours très utile pour avoir une idée détournée de la complexité d’un programme.

Pour la plupart, une complexité inférieure à 6 à 8 convient probablement tant que le code lui-même est bien formaté. Tout ce qui est de 8 à 15 est discutable, et tout ce qui dépasse 15 n’est probablement pas génial. Tout ce qui dépasse 25 est presque certainement un problème, sauf preuve du contraire.

Bien qu’avoir une complexité cyclomatique élevée dans une fonction donnée ne soit pas la fin du monde, cela peut être le signe d’un problème plus vaste. Les fonctions de haute complexité sont plus difficiles à maintenir et sujettes à plus de bogues, car il y a plus de choses à mal tourner. Et des fonctions de complexité plus élevée conduisent directement à des tests unitaires plus complexes, ce qui peut rendre le code difficile à maintenir à long terme en raison de la difficulté des tests.

Visual Studio et d’autres IDE calculent la complexité globale de classes et d’espaces de noms entiers, ce qui peut être utile pour rechercher vos classes les plus complexes. Vous pouvez trier selon la complexité la plus élevée et explorer les fonctions individuelles.

Souvent, la révision du code peut prendre en compte la complexité cyclomatique, même en signalant les fonctions problématiques qui peuvent nécessiter une révision manuelle. Cela peut en faire un outil très utile pour maintenir une base de code propre et ordonnée.

Recherche de mauvais code

De nombreux IDE, comme Visual Studio, auront des outils intégrés pour calculer la complexité cyclomatique et d’autres métriques de code pour l’ensemble de votre base de code.

Pour ce faire à partir de Visual Studio, cliquez sur Analyser> Calculer les métriques de code> Pour la solution.

Cela fera apparaître le panneau «Code Metrics» qui affichera une ventilation pour votre solution. Vous pouvez trier par complexité dans l’ordre décroissant pour afficher les espaces de noms les plus problématiques.

Parallèlement à la complexité, Visual Studio présente également un «indice de maintenabilité» qui attribue une note élevée à la méthode de 0 à 100, ainsi qu’un «couplage de classes», qui répertorie le nombre de classes référencées à partir de cette fonction ou classe.

Ici, Visual Studio a souligné une de mes méthodes de 400 lignes qui a obtenu un score énorme de 72 sur l’échelle de complexité ainsi qu’un 14/100 sur l’indice de maintenabilité (présenté comme un signe de danger triangle jaune), et fait référence à 65 classes différentes.

Vous pouvez être envoyé directement dans les cinq étapes du deuil au résultat. « Mais, c’est une coroutine très longue qui a un tas de tâches à faire! » Je me dis, en essayant de nier que le code que j’ai écrit est mathématiquement mauvais, au point que Visual Studio jette un avertissement. Une complexité de 72 a certainement besoin d’être nettoyée.

Dans ce cas, le correctif était simple – la coroutine a un tas de tâches à faire, donc je divise ces tâches en coroutines plus petites et remplace la méthode principale par des appels à des sous-programmes. Le code global n’a pas changé, pas plus que la complexité totale de la classe elle-même, mais maintenant la fonction principale n’est pas une monstruosité de 400 lignes.

★★★★★