← InExtremis

Audit de Code: Efficacité

Vous héritez d'un projet de plusieurs centaines de milliers de lignes ou même de plusieurs projets d'un coup dans une constellation d'arbre git aux commits peu évocateurs ou juste un .zip...

Pas de documentation, peu de commentaires, un gestionnaire de version pas super bien utilisé. Voici une méthode outillée pour en comprendre la structure en quelques heures.

L'objectif n'est pas de tout lire: c'est de cartographier, détecter et prioriser.

Vue d'ensemble

Avant de plonger dans le code, il faut en mesurer les contours:

Quelques outils permettent d'avoir cette vue en quelques secondes sans tout ouvrir à la main, heureusement !

Détection des redondances

Le code dupliqué est le premier ennemi de la maintenabilité. Cela montre aussi que pour apporter des définitions d'un endroit à l'autre le projet a été peu habile et les fichiers ont été copiés manuellement ou automatiquement, ce qui démultiplie d'autant les sources de vérités pour les définitions gérées par ce fichier (souvent un .h qui se retrouve copié dans chaque projet depuis un n-ième projet...).

Pour trouver ces duplicatas sans lire une ligne:

Code mort et dépendances inutilisées

Le code mort est souvent plus dangereux que le code vivant: il trompe le lecteur sur l'intention du développeur d'origine et fait perdre un temps fou de gestion lors des analyses et refactorisation alors qu'il n'a aucun impact et ne reste là souvent que pour des raisons sentimentales !

Si vous avec la "chance" d'avoir un projet en Rust, cargo-udeps liste les dépendances non utilisées dans Cargo.toml. L'on peut aussi citer cargo-bloat qui montre quelles fonctions pèsent le plus dans le binaire final.

Pour les projets C/C++ avec CMake, iwyu aka What You Use détecte les en-têtes superflues qui allongent les temps de compilation sans raison.

En Python, vulture identifie les fonctions, classes et variables jamais appelées.

En Go, deadcode de l'équipe Go officielle utilise un graphe d'appels complet depuis main ; bien plus fiable qu'une simple analyse syntaxique.

Complexité: trouver ce qui est dur à lire

Un fichier long n'est pas forcément difficile à comprendre. Un fichier court peut être un enfer cognitif. La complexité cognitive pénalise les imbrications profondes, les ruptures de flux (goto, break labelisé) et les opérateurs booléens enchaînés: c'est elle qui prédit le mieux le temps de compréhension d'un humain.

Cartographie des dépendances

Comprendre qui appelle qui est essentiel avant toute refactorisation. Voici quelques outils bien utiles permettant de cartographier les sources:

Et pour voir et exploiter correctement tout cela:

Hotspots: croiser complexité et historique git

C'est l'analyse la plus rentable d'un audit: un fichier complexe et fréquemment modifié est une bombe à retardement. Un fichier complexe mais stable peut attendre. Cette approche vient de l'ouvrage Your Code as a Crime Scene d'Adam Tornhill.

Analyse sémantique légère

Quand les outils automatiques ne suffisent plus, une lecture ciblée s'impose. L'objectif est de lire moins de 20% du code et d'en comprendre 80% (hello pareto):

Synthèse

Aucun outil ne remplace le jugement humain, mais tous ensemble ils permettent de réduire grandement le champ à auditer améliorant la valeur ajouté de l'auditeur. La méthode:

En deux à trois heures sur n'importe quelle base de code, vous pouvez avoir une idée de la structure, définir des pistes à analyser et envisager l'emplacement des zones à risques qui vont nécessiter plus d'attention.

← Retour à l'accueil InExtremis