Examiner les caractéristiques des grandes fonctions
La possibilité de reconnaître de grandes fonctions est une compétence importante pour les développeurs visant à maintenir une qualité de code élevée. Les fonctions volumineuses peuvent entraîner différents problèmes, notamment une lisibilité médiocre, des difficultés de maintenance, une faible réutilisation et des problèmes de test. Les développeurs capables d’identifier les fonctions qui présentent ces caractéristiques peuvent prendre des mesures proactives pour les refactoriser en composants plus petits et plus gérables.
Note
Il est important pour les développeurs de comprendre comment repérer manuellement les grandes fonctions plutôt que de s’appuyer exclusivement sur des outils d’intelligence artificielle. Connaître les caractéristiques des fonctions volumineuses qui les posent problème aide les développeurs à prendre des décisions éclairées sur le moment et la façon de refactoriser le code efficacement.
Odeurs de code et symptômes
Le terme « odeur de code » désigne des schémas dans le code qui indiquent des problèmes plus profonds. Dans la terminologie de l’odeur de code, une grande fonction est un « gonfleur » qui enfreint généralement le principe de responsabilité unique. Les grandes fonctions sont souvent un indicateur de mauvaise qualité du code.
Voici les indicateurs courants qu’une fonction est trop volumineuse ou qu’elle fait trop :
- Longueur excessive : Plus de 30 lignes indiquent une anomalie. Un nombre de lignes de plus de 80 est presque toujours trop long.
-
Imbrication profonde : Plusieurs niveaux d'indentation (boucles imbriquées, blocs imbriqués
if/else/try). - Trop de paramètres : Plus de 5 à 6 paramètres peuvent indiquer que la fonction agrége trop de logique.
- Niveaux d’abstraction mixtes : Des opérations de haut niveau et des détails de bas niveau entrelacés.
-
Sections commentées : Les commentaires tels que
// Step 1,// Step 2suggèrent plusieurs responsabilités. - Répétition des modèles de code : Logique en double ou blocs répétés qui peuvent être extraits.
Note
La présence de commentaires ou de blocs de région à l’intérieur d’une fonction est un indicateur rouge. Si vous voyez une fonction qui inclut une série de commentaires tels que // validate inputs, // do X, // clean up, etc., il s’agit d’un signe que la fonction a plusieurs sections distinctes de logique. Chacune de ces sections pourrait probablement être une fonction de sa propre.
Outils et approches pour rechercher des fonctions volumineuses
Il existe plusieurs façons d’identifier les fonctions volumineuses dans une base de code :
- Inspection manuelle : Parcourez les fichiers et recherchez des blocs repliables longs.
-
Recherchez des commentaires ou des TODO : Les développeurs quittent souvent des indices comme
// this is doing a lot. - Fonctionnalités de l’IDE : « Analyser les métriques de code » dans Visual Studio ou les extensions Visual Studio Code.
- Outils d’analyse statique : Linters ou analyseurs (par exemple, StyleCop, Roslyn).
- Outils d’intelligence artificielle : Les outils qui utilisent l’intelligence artificielle, comme GitHub Copilot, peuvent aider à identifier les fonctions volumineuses et à suggérer des opportunités de refactorisation.
- Commentaires de révision du code : Recherchez des commentaires passés sur la complexité ou la facilité de maintenance.
- Métrique: Les métriques de code, telles que la complexité cyclomatique et les lignes de code, peuvent aider à identifier les fonctions volumineuses.
- Rapports de couverture du code : Les grandes fonctions sont souvent difficiles à couvrir entièrement avec les tests.
Formes courantes de grandes fonctions
Les fonctions volumineuses suivent souvent certains modèles. Voici quelques « formes » courantes à rechercher :
- Script séquentiel : Effectue une série d’étapes l’une après l’autre.
-
Logique à base d'indicateurs : Utilise des chaînes
switchouif/elsepour manipuler plusieurs modes. - Logique lourde en méthodes d'assistance : Contient des blocs qui peuvent être des méthodes d’assistance.
- Blocs répétés : Logique similaire répétée pour différents jeux de données ou conditions.
Note
Utilisez le test « imagination d’extraction » : si vous pouvez nommer un bloc de code en tant que fonction, il doit probablement en être un.
Mesures à surveiller
La complexité cyclomatique, les lignes de code et le nombre de paramètres sont des métriques mesurables qui peuvent aider à identifier les fonctions volumineuses.
Voici quelques seuils courants qui indiquent une priorité élevée pour la refactorisation :
| Unité de mesure | Seuil | Pourquoi cela se produit-il |
|---|---|---|
| Lignes de code | 80+ | Indique la complexité et le risque de maintenance |
| Complexité cyclomatique | 20+ | De nombreux chemins indépendants = plus difficile à tester |
| Paramètres | 6 + | Peut indiquer une mauvaise encapsulation ou un dépassement des limites. |
Qu’est-ce que la complexité cyclomatique ?
La complexité cyclomatique est une métrique logicielle qui mesure le nombre de chemins indépendants par le biais du code d’une fonction. Considérez-le comme le nombre d’itinéraires différents que l’exécution peut prendre par votre fonction. Il existe plusieurs outils et fonctionnalités IDE qui peuvent calculer la complexité cyclomatique pour vous. Par exemple, dans Visual Studio, vous pouvez utiliser la fonctionnalité « Analyser > les métriques de code de calcul » pour obtenir des valeurs de complexité cyclomatiques pour vos méthodes. Dans Visual Studio Code, vous pouvez utiliser des extensions telles que « CodeMetrics » pour analyser votre code.
Calcul de la complexité cyclomatique
La formule de base est : Complexité cyclomatique = E - N + 2P
Where:
E = arêtes (transitions entre nœuds) N = nœuds (blocs de code séquentiels) P = composants connectés (généralement 1 pour une fonction unique)
Si vous n’avez pas accès à un outil, il existe une approche manuelle simple que vous pouvez utiliser pour estimer la complexité cyclomatique :
- Commencez par 1.
- Ajoutez 1 pour chaque if, else if, cas (dans switch).
- Ajoutez 1 pour chaque boucle (for, while, do-while).
- Ajoutez 1 pour chaque opérateur logique (
&&,||) dans les conditions. - Ajoutez 1 pour chaque bloc catch.
Utilisation de la complexité comme guide pour identifier les fonctions volumineuses
Lorsque le document mentionne « La complexité cyclomatique supérieure à 10-15 est un indicateur rouge », cela signifie :
- 1-10 : Simple, faible risque
- 10+ : Commencer à envisager la refactorisation
- 15+ : a certainement besoin d’attention
- 20+ : Priorité élevée pour la refactorisation
La complexité cyclomatique est utile, car elle est objective et mesurable, ce qui en fait une excellente métrique pour identifier les fonctions qui ont besoin de refactorisation.
Comment réduire la complexité
Il existe plusieurs stratégies pour réduire la complexité des grandes fonctions :
- Extraire des méthodes : décomposer la logique complexe en fonctions plus petites.
- Utiliser le polymorphisme : remplacez les conditions complexes par des modèles de stratégie.
- Retours précoces : quittez tôt au lieu de l’imbrication profonde.
- Simplifier les conditions : Extrayez une logique booléenne complexe pour des variables bien nommées.
- Supprimer les arguments d’indicateur : fractionner les fonctions qui se comportent différemment en fonction des indicateurs.
Toutes les grandes fonctions ne sont pas du mal
Certaines fonctions volumineuses sont acceptables dans des contextes spécifiques (par exemple, du code critique pour les performances). Faites preuve de jugement. L’objectif est de faciliter l’utilisation du code.
Note
Si une fonction est difficile à fractionner parce que tout est étroitement entrelacé, c’est un signe de couplage élevé. Le mode de demande de Copilot peut vous aider à le démêler.
Résumé
Les grandes fonctions peuvent entraver le processus de développement en introduisant différents défis. Ils entraînent souvent une diminution de la lisibilité, une complexité accrue et des coûts de maintenance plus élevés. En reconnaissant les signes des fonctions volumineuses et en comprenant leur impact, les développeurs peuvent prendre des mesures proactives pour les refactoriser en fonctions à usage unique plus petites et plus faciles à utiliser.