L'analyse statique ne consiste pas seulement à trouver directement des bogues, mais aussi à identifier les situations propices aux bogues qui peuvent nuire à la lisibilité et à la maintenabilité du code. L'analyse statique peut traiter de nombreuses autres propriétés du code :
- Les métriques de code: par exemple, les méthodes comportant trop de boucles et d'instructions if, else, switch et case finissent par être difficiles à comprendre, donc difficiles à maintenir. Les compter grâce à la métrique de complexité cyclomatique est un excellent moyen d'évaluer quand une méthode devient trop complexe.
- Les dépendances: si les classes de votre programme sont enchevêtrées, les effets de toute modification du code deviennent imprévisibles. L'analyse statique peut aider à évaluer quand les classes et les composants sont enchevêtrés.
- L'immutabilité: les types utilisés simultanément par plusieurs threads devraient être immuables ; sinon, vous devrez protéger les accès en lecture/écriture à l'état par des stratégies de verrous complexes qui finiront par être impossibles à maintenir. L'analyse statique peut garantir que certaines classes restent immuables.
- Le code mort: le code mort est du code qui peut être supprimé en toute sécurité, car il n'est plus invoqué à l'exécution. Non seulement il peut être supprimé, mais il doit l'être, car ce code supplémentaire ajoute une complexité inutile au programme. L'analyse statique peut trouver la majeure partie du code mort de votre programme (mais pas la totalité).
- Les ruptures de compatibilité d'API: si vous exposez une API à vos clients, il est très facile de supprimer un membre public sans s'en apercevoir et ainsi de casser le code de vos clients. L'analyse statique peut comparer deux états d'un programme et vous mettre en garde contre ce piège.
- L'utilisation des API: certaines API sont destinées à être utilisées avec précaution. Par exemple, une classe qui détient des champs libérables doit généralement être elle-même libérable, sauf lorsque la durée de vie du champ libérable n'est pas alignée sur celle de l'instance de la classe — ce qui ressemble alors à un problème de conception.
De nombreux outils utiles existent pour détecter les bogues dans votre base de code C++, comme Cppcheck, Clang et l'analyseur de Visual Studio. Mais qu'en est-il de l'identification des situations propices aux bogues ?
Alors que les créateurs d'outils d'analyse statique peuvent décider quelles situations sont considérées comme des bogues, ce n'est pas le cas des situations propices aux bogues, qui dépendent des choix de l'équipe de développement. Par exemple, une équipe peut considérer qu'une méthode de plus de 20 lignes est complexe, tandis qu'une autre fixera le maximum à 30. Si un outil détecte les situations propices aux bogues, il doit aussi offrir un moyen de personnaliser les règles correspondantes.
Considérer le code comme des données : la meilleure façon de détecter les situations propices aux bogues
L'analyse statique, c'est l'idée d'analyser le code source selon diverses propriétés et d'en rendre compte, mais c'est aussi, philosophiquement, l'idée de traiter le code comme des données. Cette perspective nous semble profondément étrange en tant que développeurs d'applications, car nous avons l'habitude de considérer le code source comme des instructions, des procédures et des algorithmes. Mais c'est aussi une idée profondément puissante.
Après l'analyse d'un fichier source, nous pouvons extraire son AST et générer un modèle contenant une mine d'informations utiles sur le code. Nous pouvons ensuite interroger ce modèle à l'aide d'un langage de requête de code similaire à SQL.
CppDepend fournit un puissant langage de requête de code nommé CQLinq pour interroger la base de code comme une base de données. Les développeurs, concepteurs et architectes peuvent définir des requêtes personnalisées pour identifier facilement les situations propices aux bogues.
Avec CQLinq, nous pouvons combiner les données des métriques de code, des dépendances, de l'utilisation des API et d'autres informations du modèle pour définir des requêtes très avancées correspondant à des situations propices aux bogues spécifiques.
Voici un exemple de requête CQLinq qui identifie les méthodes les plus complexes :

Résumé
Il est préférable de combiner plusieurs outils C++ pour détecter les problèmes de votre base de code : certains outils détectent les bogues, tandis que d'autres détectent aussi les situations propices aux bogues. Avec CppDepend, nous cherchons à combiner les points forts de plusieurs outils : nous offrons un moyen simple de définir des requêtes personnalisées, et nous avons récemment ajouté une fonctionnalité permettant d'importer les résultats d'autres outils d'analyse statique pour les interroger avec CQLinq.
