Demander des clarifications sur la structuration du code afin de réduire la complexité cyclomatique

StackOverflow https://stackoverflow.com/questions/204369

Question

Récemment, notre société a commencé à mesurer chaque semaine la complexité cyclomatique (CC) des fonctions de notre code et à indiquer les fonctions améliorées ou aggravées. Nous avons donc commencé à accorder une plus grande attention au CC des fonctions.

J'ai lu que CC pouvait être calculé de manière informelle comme 1 + le nombre de points de décision dans une fonction (par exemple, une instruction if, pour une boucle, une sélection, etc.), ou également le nombre de chemins à travers une fonction ...

Je comprends que le moyen le plus simple de réduire le CC consiste à utiliser le refactoring de la méthode d'extraction à plusieurs reprises ...

Il y a des choses sur lesquelles je ne suis pas sûr, par exemple. quel est le CC des fragments de code suivants?

1)

for (int i = 0; i < 3; i++)
    Console.WriteLine("Hello");

Et

Console.WriteLine("Hello");
Console.WriteLine("Hello");
Console.WriteLine("Hello");

Ils font tous les deux la même chose, mais la première version a-t-elle un CC plus élevé en raison de l'instruction for?

2)

if (condition1)
    if (condition2)
        if (condition 3)
            Console.WriteLine("wibble");

Et

if (condition1 && condition2 && condition3)
    Console.WriteLine("wibble");

En supposant que le langage court-circuite l'évaluation, telle que C #, ces deux fragments de code ont le même effet ... mais le CC du premier fragment est-il plus élevé, car il a 3 points de décision / déclarations if?

3)

if (condition1)
{
    Console.WriteLine("one");

    if (condition2)
        Console.WriteLine("one and two");
}

Et

if (condition3)
    Console.WriteLine("fizz");

if (condition4)
    Console.WriteLine("buzz");

Ces deux fragments de code font des choses différentes, mais ont-ils le même CC? Ou est-ce que l'instruction imbriquée si dans le premier fragment a un CC plus élevé? c'est-à-dire imbriquées si les déclarations sont mentalement plus complexes à comprendre, mais cela est-il reflété dans le CC?

Était-ce utile?

La solution

  1. Oui. Votre premier exemple a un point de décision et votre second pas, alors le premier a un CC plus élevé.
  2. Oui. Peut-être que votre premier exemple comporte plusieurs points de décision et donc un CC plus élevé. (Voir ci-dessous pour l'explication.)
  3. Oui, peut-être. Évidemment, ils ont le même nombre de points de décision, mais il existe différentes façons de calculer le CC, ce qui signifie ...

... si votre entreprise mesure le CC d'une manière spécifique, vous devez vous familiariser avec cette méthode (avec un peu de chance, elle utilise des outils pour le faire). Il existe différentes manières de calculer le CC dans différentes situations (instructions de cas, opérateurs booléens, etc.), mais vous devriez obtenir le même type d'informations à partir de la métrique, quelle que soit la convention que vous utilisez.

Le problème le plus important est ce que d’autres ont mentionné, à savoir que votre société semble se concentrer davantage sur le CC que sur le code qui le sous-tend. En général, bien sûr, au-dessous de 5, ce qui est excellent, inférieur à 10, bon, inférieur à 20, OK, 21 à 50 devrait être un signe d'avertissement, et au-dessus de 50, un gros signe, mais ce sont des guides, pas des règles absolues. Vous devriez probablement examiner le code dans une procédure ayant un CC supérieur à 50 pour vous assurer qu'il ne s'agit pas simplement d'un énorme tas de code, mais peut-être y a-t-il une raison spécifique pour laquelle la procédure est écrite de cette façon, et ce n'est pas faisable (pour nombre de raisons) pour le refactoriser.

Si vous utilisez des outils pour restructurer votre code afin de réduire le CC, assurez-vous de bien comprendre le fonctionnement de ces outils et veillez à ce qu'ils ne déplacent pas un problème à un autre. En fin de compte, vous voulez que votre code comporte peu de défauts, qu'il fonctionne correctement et qu'il soit relativement facile à gérer. Si ce code a également un faible CC, tant mieux. Si votre code répond à ces critères et que votre CC est supérieur à 10, il est peut-être temps de discuter avec la direction de votre choix et de défendre votre code (et peut-être de l'amener à examiner sa politique).

Autres conseils

Après avoir parcouru le texte de Wikipédia et le texte original de Thomas J. McCabe, il semble que les éléments que vous avez mentionnés ci-dessus sont des problèmes connus de la métrique.

Cependant, la plupart des paramètres ont des avantages et des inconvénients. Je suppose que dans un programme suffisamment important, la valeur CC pourrait indiquer des éléments éventuellement complexes de votre code. Mais ce CC plus élevé ne signifie pas nécessairement complexe.

Comme toutes les mesures logicielles, CC n’est pas parfait. Utilisé sur une base de code assez grande, il peut vous donner une idée de l'endroit où pourrait être une zone problématique.

Il y a deux choses à garder à l'esprit ici:

  1. Base de code assez grande: dans tout projet non trivial, vous aurez des fonctions qui ont une valeur CC très élevée. Si élevé qu'il importe peu que, dans l'un de vos exemples, le CC soit égal à 2 ou 3. Une fonction avec un CC de plus de 300 est certainement quelque chose à analyser. Peu importe que le CC soit 301 ou 302.
  2. N'oubliez pas d'utiliser votre tête. Il existe des méthodes qui nécessitent de nombreux points de décision. Souvent, ils peuvent être restructurés pour en avoir moins, mais parfois ils ne le peuvent pas. N'allez pas avec une règle comme & Quot; Refactoriser toutes les méthodes avec un CC & Gt; xy " ;. Regardez-les et utilisez votre cerveau pour décider quoi faire.

J'aime l'idée d'une analyse hebdomadaire. Dans le contrôle de la qualité, l’analyse des tendances est un outil très efficace pour identifier les problèmes lors de leur création . C’est bien mieux que d’attendre jusqu’à ce qu’ils deviennent si gros qu’ils deviennent évidents (voir SPC pour quelques détails).

Le CC n’est pas une panacée pour mesurer la qualité. Clairement, une déclaration répétée n’est pas & «Mieux &»; qu'une boucle, même si une boucle a un plus grand CC. La raison pour laquelle la boucle a un plus grand CC est que parfois elle peut être exécutée et parfois non, ce qui conduit à deux & "; Cas &"; qui devrait être testé. Dans votre cas, la boucle sera toujours exécutée trois fois, car vous utilisez une constante, mais CC n’est pas assez intelligent pour le détecter.

Idem avec les ifs chaînés de l'exemple 2: cette structure vous permet d'avoir une déclaration qui serait exécutée si seules les conditions condition1 et condition2 sont vraies. Il s’agit d’un cas spécial qui n’est pas possible dans le cas où & Amp; & Amp ;. Donc, la chaîne if a un potentiel plus important pour des cas particuliers, même si vous ne l'utilisez pas dans votre code.

C’est le danger d’appliquer n’importe quelle métrique à l’aveugle. La métrique CC a certes beaucoup de mérite, mais comme pour toute autre technique d'amélioration du code, elle ne peut pas être évaluée séparément du contexte. Pointez votre direction sur la discussion de Casper Jone sur la mesure des lignes de code (j'aimerais pouvoir trouver un lien pour vous). Il souligne que si Lines of Code constitue une bonne mesure de la productivité, les développeurs de langage assembleur sont les développeurs les plus productifs de la planète. Bien sûr, ils ne sont pas plus productifs que les autres développeurs; il leur faut simplement beaucoup plus de code pour accomplir ce que font les langages de niveau supérieur avec moins de code source. Je le mentionne, comme je l'ai dit, pour que vous puissiez montrer à vos gestionnaires à quel point il est stupide d'appliquer aveuglément des mesures sans passer en revue intelligemment ce qu'elles vous disent.

Je suggérerais que dans le cas contraire, votre direction aurait intérêt à utiliser la mesure CC pour repérer les points chauds potentiels dans le code, qui devraient être examinés plus avant. Avoir aveuglément pour objectif de réduire le CC sans se référer à la maintenabilité du code ou à d’autres mesures de bon codage est tout simplement ridicule.

La complexité cyclomatique est analogue à la température. Ce sont deux mesures, et dans la plupart des cas sans signification, sans contexte. Si j’ai dit que la température extérieure était de 72 degrés, cela ne signifie pas beaucoup! mais si j'ajoute le fait que j'étais au pôle Nord, le nombre 72 devient significatif. Si quelqu'un me dit qu'une méthode a une complexité cyclomatique de 10, je ne peux & # 8217; pas déterminer si elle est bonne ou mauvaise sans son contexte.

Lorsque je vérifie une application existante avec le code, je trouve la complexité cyclomatique un & # 8220; point de départ utile & # 8221; métrique. La première chose que je vérifie concerne les méthodes avec un CC & Gt; 10. Ces & # 8220; & Gt; 10 & # 8221; les méthodes ne sont pas nécessairement mauvaises. Ils me fournissent simplement un point de départ pour examiner le code.

Règles générales lors de la prise en compte d'un numéro CC:

  • La relation entre CC # et # de tests doit être CC # < = #tests
  • Refactoriser pour CC # uniquement s'il augmente maintenabilité
  • Un CC supérieur à 10 indique souvent un ou plusieurs odeurs de code

[Hors sujet] Si vous privilégiez la lisibilité à un bon score dans les métriques (J.Spolsky a-t-il dit: & "Ce qui est mesuré, faites-le &";?), ce qui signifie que les métriques font l'objet d'abus plus souvent Je suppose qu’il est souvent préférable d’utiliser un booléen bien nommé pour remplacer votre déclaration conditionnelle complexe.

puis

if (condition1 && condition2 && condition3)
    Console.WriteLine("wibble");

devenir

bool/boolean theWeatherIsFine =  condition1 && condition2 && condition3;

if (theWeatherIsFine)
    Console.WriteLine("wibble");

Je ne suis pas un expert sur ce sujet, mais je pensais pouvoir donner mes deux sous. Et peut-être que tout cela vaut la peine.

La complexité cyclomatique semble être simplement un raccourci automatisé particulier pour rechercher des extraits de code potentiellement problématiques. Mais le vrai problème à résoudre n’est-il pas d’essayer? Combien de cas de test le code nécessite-t-il? Si le nombre de tests est supérieur mais que le nombre de tests est le même et que le code est plus propre, ne vous inquiétez pas pour le contrôle.

1.) Il n’ya pas de point de décision à cet endroit. Il y a un et un seul chemin dans le programme, un seul résultat possible avec l’une ou l’autre des versions. Le premier est plus concis et meilleur, la complexité cyclomatique soit maudite.

1 scénario de test pour les deux

2.) Dans les deux cas, vous pouvez écrire & "; wibble &"; ou vous ne le faites pas.

2 cas de test pour les deux

3.) Le premier résultat pourrait ne donner rien, & "un &"; ou & "un &"; et " un et deux " ;. 3 chemins. 2ème pourrait ne donner rien, ni des deux, ni des deux. 4 chemins.

3 cas de test pour le premier 4 cas de test pour le second

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top