La création de ses propres métriques dans un outil d’analyse de code présente-t-elle vraiment un intérêt ? Quel bénéfice peut-on en espérer ? Quels inconvénients, quels obstacles va-t-on rencontrer ?
Il est frappant de voir que ces questions sont la plupart du temps ignorées lors d’un choix d’outil. On préfère mesurer la facilité ou la difficulté à personnaliser le logiciel et à créer ses propres règles plutôt que de se demander si l’on en a vraiment besoin.
Cette série d’articles a donc pour objet de clarifier ces questions afin de vous aider à poser les bons critères si vous souhaitez acquérir un outil d’analyse de code. Si vous êtes un consultant Qualité qui doit assister un client pour un tel choix, vous pouvez aborder ces questions avec lui afin de l’aider dans sa sélection.
Après avoir vu les métriques les plus simples et les plus faciles à créer avec un outil d’analyse de code, nous allons aborder dans cet article des métriques beaucoup plus complexes et même, certains standards ou bonnes pratiques que j’ai rencontrés chez certains clients, et qui sont tout simplement impossibles à implémenter.
Les métriques complexes
La plupart des métriques réellement utiles sont complexes parce qu’elles reposent sur des syntaxes ou des bonnes pratiques de programmation complexes, sinon à mettre en œuvre, mais en tout cas à identifier. Par exemple :
- Toutes les instructions conditionnelles (type ‘IF … THEN … ELSE … ENDIF’) ou de boucle (type ‘While … EndWhile’ ou ‘Loop … EndLoop’) sont structurées en blocs multiples : ‘IF’ ou ‘While’ suivi de plusieurs lignes de code (parfois sur plus d’une page) avant le ‘ENDIF’ ou le ‘EndWhile’ de fin d’instruction. Essayer d’identifier ces instructions avec une unique RegExp (voir le post précédent sur les Expressions Régulières) devient un vrai casse-tête. C’est une source assez répandue de falses-positives pour nombre d’outils d’analyse de code.
- Certaines instructions peuvent être gourmandes en mémoire ou en temps d’exécution, sans présenter pour autant un risque pour la performance … sauf si elles sont inscrites dans une boucle. Là-encore, essayer d’identifier la présence d’une telle syntaxe au sein d’une instruction de boucle est très complexe et requiert une maîtrise très pointue des expressions régulières.
- La plupart des règles en matière de lisibilité et de compréhension du code, donc de bonnes pratiques de maintenabilité, sont basées sur l’imbrication de telles instructions : IF imbriqués, boucles au sein de boucles, le tout généralement sur plusieurs pages de code. Risque important d’erreur et au minimum, coût de maintenance élevé car toute modification de ce code nécessite un effort de programmation plus élevé. Lá encore, ces règles sont complexes ou très complexes à implémenter avec des expressions régulières.
- D’autres bonnes pratiques de programmation dépendent du type d’objets. Le meilleur exemple d’une telle règle, présente dans toutes les technologies et languages, est celle qui interdit tout appel à la base de données depuis la couche de présentation. Probablement la première règle en matière de sécurité. Il ne suffit donc pas d’identifier une instruction mais toutes les differentes instructions accédant potentiellement à la base de données, de vérifier que celles-ci sont utilisées dans un écran (la couche de présentation) et qu’elles exécutent un traitement en bases de données. Notez bien que c’est plus subtil et compliqué que cela : exécuter une requête SQL depuis une JSP est strictement intedit mais passer cette même requête à un objet de la couche logique de données qui effectuera lui-même ce traitement peut être admis. La bonne pratique consiste bien sûr à ne passer que les données nécessaires à l’exécution de cette requête SQL à un objet spécialisé dans l’accès à la couche de données, mais la programmation incorrecte de celui-ci constitue la source la plus importante des ‘SQL injections’ si chères aux hackers.
Il devient très difficile et même impossible de concevoir et implémenter de telles métriques à l’aide d’expressions régulières. Il faut généralement que l’outil d’analyse de code permette d’analyser l’arbre syntaxique des instructions, ce qui n’est pas le cas de tous les outils. Et il faudra des compétences assez avancées dans la compréhension de cet ‘Abstract Syntax Tree’ ainsi que des outils et un langage spécifiques pour parcourir cet arbre et programmer votre métrique. Débutant s’abstenir.
Les métriques impossibles
Plus une métrique est complexe, plus elle est difficile à implémenter, parfois à la limite de ce qu’il est possible de faire. Mais certaines bonnes pratiques ‘personnalisées’ sont tout simplement impossible à réaliser.
Une des premières questions que je pose à un client qui souhaite implémenter ses propres règles consiste à lui demander s’il dispose d’un cahier de règles ou tout autre document décrivant ses ‘best practices’. Ce n’est pas toujours, voire même rarement le cas, mais je suis content lorsqu’il me répond par l’affirmative car cela signifie que sa demande – la ‘facilité d’implémentation de métriques personnalisées’ – est justifiée, et qu’à partir de là, nous allons pouvoir travailler sérieusement.
La lecture d’un tel document va cependant révéler qu’une proportion importante des ces règles est tout simplement impossible à implémenter. Cette proportion est plus ou moins élevée selon la technologie concernée (nous verrons cela dans le prochain post sur ce sujet). Exemples :
- « Une classe, une méthode, une fonction, une procédure, un paragraphe (Cobol), etc. doit être documenté » selon un template ‘maison’. Essayez déjà de définir une RegExp qui vérifie si un commentaire est présent en tête de classe, de méthode, de fonction, etc. Maintenant construisez une RegExp qui vérifie que ce commentaire correspond à un format précis, sur plusieurs lignes bien sûr, avec au minimum l’auteur, la date, une description de l’objet, etc. Bon courage.
- « L’en-tête de chaque programme doit comporter une description de la fonctionnalité implémentée ». Cette règle est une variante plus avancée de la précédente : non seulement vous devez vérifier que le commentaire d’en-tête répond à une certaine forme mais que sur le fond, il présente le traitement fonctionnel objet de ce programme. Impossible.
- « Les messages d’erreur doivent être traduits en espagnol, en catalan, et en basque ». Vive le pluralisme.
- Identification de code mort. J’aime bien les outils d’analyse de code qui prétendent identifier le code mort. Un truc de programmeur (un peu avancé) pour mettre en commentaire tout un bloc de code :
IF 1=0
… code mort
ENDIF
Ah bien sûr, il est assez facile de définir une RegExp qui va trouver toutes les occurrences de ‘IF 1=0’. Combien de RegExp pour identifier les occurrences de ‘IF A=B’ ou de ‘IF 1=2’ ? Laissez tomber.
La prochaine fois qu’un vendeur vous dit que son soft sait identifier le code mort, donnez lui cet exemple (et essayez de ne pas sourire).
Et je ne vous parle même pas de règles générales et imprécises comme :
- « Contrôle de sytaxe : corriger les erreurs critiques et justifier les exceptions aux règles non critiques ». Débrouille-toi avec ça.
- « Il est interdit de développer une fonction s’il existe déjà une fonction réalisant le même traitement ». Ah ben oui bien sûr, c’est logique, mais merci quand même de le rappeler.
- « Vérifier que le programme appelé existe bien ». A tout hasard, au cas oú, cela peut servir. Remarque : en fait, cette règle peut être implémentée facilement en vérifiant le code retour de l’appel à la fonction … quand il existe.
Je veux simplement montrer à quel point certaines règles sont complètement impossibles à implémenter et elles sont plus nombreuses que vous le pensez (si, si, j’ai des exemples).
Plus sérieusement, si votre client vous présente un cahier avec de telles règles, évitez tout commentaire moqueur car au moins, l’existence d’un tel document prouve qu’il se soucie de la qualité de ses applications. Simplement, la plupart de ces cahiers de règles sont destinés à des vérifications manuelles du code, et vous ne pouvez tout simplement pas automatiser toutes les règles manuelles.
Lorsqu’on vous demande si tel outil permet de créer des règles personnalisées, la première réaction consiste à exposer ce que tel outil sait faire, et généralement pour des règles reposant sur des syntaxes simples, comme celles que nous avons vues dans le post précédent. Votre client s’en contentera mais ce n’est pas la bonne réponse. Ce que je fais :
- Je lui demande s’il a défini les règles en question, c’est-à-dire s’il dispose de bonnes pratiques qu’il souhaite implémenter à travers l’outil.
- Si c’est le cas (réponse affirmative) : je lui demande si ces règles sont formalisées à travers un document.
- Si ce n’est pas le cas (réponse négative) : je lui rappelle que 100% des clients qui souhaitent acquérir un outil d’analyse de code posent cette même question, mais que 90% n’utiliseront pas cette fonctionnalité. Et 90% des 10% restants abandonneront la gestion de métriques personnalisées au bout de 2 ans parce que c’est trop lourd à gérer.
- Dans tous les autres cas – bredouillement indistinct du genre ‘on y pense’, ‘cest pour savoir’, ‘au cas oú’, ‘éventuellement’, etc – je traite sa réponse comme négative (point précédent) ou je passe à la question suivante :
Règles personnalisées : pour quelles technologies ?
Ce sera l’objet de notre prochain post.
Cette publication est également disponible en Leer este articulo en castellano : liste des langues séparées par une virgule, Read that post in english : dernière langue.