Nous proposons, au travers de notre démarche d’audit de code, d’apporter au client un regard extérieur et technique sur la qualité de réalisation de leur application. Les raisons qui amènent un client à demander une telle mission sont diverses :
- Dette technique à évaluer
- Problématiques récurrentes (Performance, régressions)
- Qualification en vue d’un investissement
- Etc.
Pour retrouver toutes les problématiques auxquelles répond un audit applicatif, nous vous invitons à télécharger ce livre blanc : Les différents usages de l’audit applicatif.
Le besoin est donc protéiforme en fonction du client, mais le livrable reste le même dans le fond et dans la forme, à savoir apporter une vue synthétique et vulgarisée de l’état d’une application.
Ce type de mission est relativement court, il faut donc s’appuyer sur l’expérience de l’auditeur, mais aussi sur des outils qui fournissent à la fois des indicateurs synthétiques, facilement interprétables, et des infographies utiles pour une prise en main rapide du projet et pour étayer, voire embellir, le livrable final. L’objet de cet article et de vous présenter l’un de ces outils : NDepend. Cet outil est particulièrement efficace. Il offre tout un ensemble de fonctionnalités permettant d’analyser structurellement une application .Net rapidement. C’est cette efficacité que nous recherchons dans ce type de mission, d’autant plus que la dernière version 2020.1 offre un nouveau moteur de génération des graphes encore plus performant.
Notre démarche d’audit applicatif et ses contraintes
Avant toute chose, précisons ce qu’est un audit technique au sens SoftFluent et sa particularité. Une telle mission ne s’inscrit pas dans la durée, elle est plutôt de l’ordre de 10 jours (en moyenne) tout compris. Sur cet intervalle, il y a le lancement de la mission, la prise d’information, d’éventuels entretiens avec l’équipe technique, l’analyse approfondie de l’application, la rédaction des différents livrables et, enfin, la restitution. Le temps est donc précieux et compté, et même sur une mission de 10 jours il y a peu de place à la compréhension technique de ce qui est réalisé.
Mais nous ne nous contentons pas d’un passage mécanique du code source dans un automate qui délivrerait des indicateurs difficiles à interpréter. Nous nous focalisons en grande partie sur l’analyse visuelle du code source : Il est littéralement pris en main, et le contenu des livrables rend compte de cette approche. A savoir :
- 1 document au format Word qui contient l’analyse détaillée des anomalies avec des exemples issus du code source et les recommandations associées. Il s’agit en quelque sorte de la démonstration
- 1 document au format Excel regroupant l’ensemble des recommandations permettant de servir de base d’un chiffrage et / ou pilotage des chantiers de remédiation.
- 1 document au format Excel définissant les diagrammes araignées relatifs aux conclusions de l’audit dans chaque axe d’analyse
- 1 présentation au format Powerpoint à destination des décideurs. Document synthétique vulgarisant les notions servant de support à la réunion de restitution finale.
Tous ces livrables sont organisés autour d’une nomenclature nous permettant à la fois de classer les recommandations et de fournir une cohérence globale à la mission. Chaque axe principal (au nombre de 4 : « Architecture, Implémentation, Cycle de développement et Documentation ») est découpé à son tour en sous-catégorie, et tous les chapitres et recommandations se retrouvent associés à une de ces branches :
La couverture technique est donc vaste avec une très forte contrainte de temps. Une telle dynamique nécessite d’être le plus efficace et productif possible. C’est dans ce cadre qu’un outil tel que NDepend apporte un réel support. Les chapitres suivants décrivent l’usage de cet outil dans notre démarche d’audit.
L’utilisation de NDepend lors de l’audit de code
La matière première de ce qu’il faut auditer est avant tout le code source, et il n’est pas systématique de pouvoir compiler l’intégralité du projet sur le poste de l’auditeur. La plateforme .NET compile les sources dans des fichiers exécutables (les Assemblies) qui contiennent une bonne partie des données consommées par l’analyse de NDepend. En conséquence avec seulement un simple répertoire contenant l’ensemble des Assemblies du projet NDepend produit déjà beaucoup de retours utiles. Toutefois l’intégration de NDepend dans Visual Studio et les facilités de navigation dans le code source sont plus importantes lorsque l’on peut regénérer l’application.
L’étape de définition du périmètre à analyser étant faite, il suffit de lancer l’opération d’analyse pour obtenir très rapidement un tableau de bord avec tout un ensemble de métriques et d’outils permettant de naviguer dans le code source. Le chapitre suivant présentera un exemple issu d’un cas réel d’audit d’une application présentant de nombreux symptômes.
Mais avant tout, nous allons présenter les fonctions majeures de NDepend que nous utilisons. La première d’entre elles est, bien évidemment, le tableau de bord regroupant toutes les métriques. Ces dernières représentent la projection du résultat de tout un système de requête intégré à NDepend nommé CQLinq ( Code Query Linq). Il est tout à fait possible de créer ses propres requêtes, mais les requêtes prédéfinies sont largement suffisantes dans le cadre de notre démarche d’audit. Ci-dessous un exemple de synthèse globale d’une analyse :
Et un exemple de requête pré-intégrée permettant d’obtenir le détail des anomalies critiques. Nous remarquons que cette requête est parfaitement éditable et qu’elle est accompagnée de tout un ensemble de commentaires fournissant des éléments d’interprétation du résultat, et le cas échéant des conseils de remédiations.
Nous avons donc très rapidement un moyen de naviguer de façon pertinente dans le code source en ciblant directement la ou les fonctions qui posent problème, et cela directement depuis l’environnement de développement Visual Studio.
Mais l’approche relève toujours de l’échantillonnage, et ne permet pas d’avoir une vue globale de l’architecture applicative. Pour cela nous utilisons différentes formes du diagramme des dépendances. Il s’agit ici d’une des principales évolutions de l’outil pour 2020. Il offre une présentation claire avec beaucoup de moyens d’ajustement du mode de représentation. Ci-dessous un exemple réel :
Au premier regard nous prenons connaissance de l’ensemble de l’architecture applicative au travers du prisme de la décomposition par Namespace. Cela est bien entendu paramétrable, mais la représentation par défaut propose une proportionnalité des cadres liée au poids en termes de lignes de code, et la largeur des flèches représente le niveau de couplage entre ces Namespaces.
Enfin le 3eme outil permettant d’avoir une vue globale des métriques liées aux dépendances, et offrant aussi un moyen infographique pour appuyer un propos en cas d’anomalie est la matrice de dépendance. Elle fournit des éléments chiffrés liés aux interdépendances des différents Namespaces/Classes.
Les valeurs fournies permettent directement de comprendre le poids d’un espace de nom NameSpace par rapport aux autres, et donc d’orienter plus efficacement l’auditeur sur ce qui est important sur le plan technique et fonctionnel.
Le chapitre suivant présente un cas réel d’une application auditée et comment au travers de NDepend nous pouvons dès le premier passage avoir une vue précise sur l’architecture applicative, et établir tout un ensemble de constations et recommandations pour alimenter le livrable final.
Retour d’expérience sur un cas réel d’audit :
Nous allons prendre un cas réel d’analyse sur la globalité du projet au sens .Net (Les captures écrans précédentes sont basés sur une sous-partie de ce projet). Les éléments identifiant le client et le projet en particulier ont été masqués. Après avoir compilé avec les PDB, nous pouvons lancer l’analyse proprement dite, dont voici les premières métriques :
L’application est donc particulièrement conséquence avec près de 2000 Types. Impossible donc de contrôler chaque détail de ce qui a été réalisé : il va falloir échantillonner. La navigation au hasard permet de prendre en main la Solution, mais NDepend fournit directement un graphe de dépendance dans lequel il est possible de naviguer :
Nous pouvons faire plusieurs remarques à ce niveau :
- La génération du graphe est rapide
- La navigation en zoomant à la souris est efficace et ne souffre pas de la taille du projet
- Les 2000 Types ne sont pas représentés. Le moteur agrège les notions en fonction de leurs importances et via la notion de Cluster (
). Le graphique est donc lisible malgré le nombre d’objets sous-jacents.
Des éléments d’anomalies émergent déjà grâce au code couleur des flèches représentant les dépendances. Un rapide Zoom sur un des cadres en haut à droite montre ces relations :
Des Namespaces se retrouvent mutuellement dépendant sous forme triangulaire. Nous sommes manifestement devant un problème de structuration du code source et de définition des responsabilités. Une telle interdépendance rend à coup sûr la maintenabilité plus compliquée car la relation entre les objets ne sera pas évidente à appréhender.
En survolant la souris sur le graphe initial, nous pouvons voir une vision instantanée des dépendances d’un espace de nom par rapport aux autres par le biais du jeu des couleurs. Ci-dessous un exemple en survolant en cadre relativement petit (en orange).
Nous voyons en vert les appelants directs. Nous voyons bien que cet espace de nom, qui représente un poids relativement modeste au regard de l’application, se retrouve être en relation avec beaucoup d’autres éléments du code source. Il s’agira donc d’analyser de façon approfondie ce passage du code source par une lecture directe du code source. Si la qualité de l’écriture du code à cet emplacement n’est pas au rendez-vous, nous nous retrouvons ici avec un fort niveau risque.
Un autre exemple dans lequel cette fois un cadre encore plus petit se retrouve en relation avec l’ensemble des niveaux de l’application :
Nous voyons ici aussi en vert les appelants directs et en bleu les éléments directement appelés (indirectement en bleu plus clair). Cette fois cette partie est moins exploitée que précédemment, mais tout travail de refactoring de l’application risque d’impacter ce cadre. Ici aussi nous avons une représentation simple qui montre comment une petite partie impacte l’ensemble du projet.
Comme expliqué plus haut, NDepend intègre aussi tout un système de requêtage du code source sur lequel s’appuient les métriques remontées lors de l’analyse. Ces requêtes peuvent être ré-exécutées spécifiquement et fournir l’emplacement du code. Cela se révèle très pratique dans la démarche d’un audit technique, car nous allons pouvoir mettre le doigt directement sur des problèmes de fond.
A partir du tableau de bord, un simple clic sur le nombre d’anomalies nous redirige sur la liste des problèmes rencontrés. Voici un extrait sur le nombre d’anomalies « High » au nombre de 1306 :
Nous remarquons donc des problèmes récurrents quant à la séparation des responsabilités entre l’UI et l’accès aux données. Et nous retrouvons aussi des anomalies manifestement en lien avec des carence en termes de structuration et d’architecture tel que le nombre de paramètres trop grand pour une méthode. Un double clic sur l’application nous redirige sur une arborescence représentant l’organisation en termes de Namespace (avec le nombre de cas détectés) jusqu’à la méthode proprement dite :
Le code source nous montre effectivement une vraie problématique de conception et de complexité liée à ce passage (La combinatoire des paramètres est évidement gigantesque) :
Visual Studio nous retourne à son tour une information précieuse, à savoir le nombre de références vers cette méthode : 10 (indiqué juste au-dessus de la méthode). A cela s’ajoute l’usage d’une langue qui n’est pas en anglais et nous avons de façon évidente une réelle problématique à ce niveau : Modifier le comportement de cette méthode débouchera sur des régressions si un soin tout particulier n’est pas apporté aux tests.
Tous ces éléments (graphiques, extrait de code source) se retrouvent classés et projetés dans le principal livrable au format Word. Pour reprendre l’exemple juste au-dessus, voici un exemple de projection dans le constat d’audit :
a) Trop grand nombre de paramètres Nous observons à de nombreuses reprises des passages de paramètres complexes de façon littérale, et non pas au travers d’un objet. Cela rend à la fois le code difficile à lire et l’ajout d’un nouveau paramètre modifie la signature de la méthode. Voici un exemple symptomatique où cette méthode qui est référencée 10 fois présente 30 paramètres : Il s’agit donc dans un premier temps de retravailler ces passages de paramètres en passant par un objet, et dans un second temps d’analyser la raison pour laquelle une telle fonction à besoin de 30 paramètres. Le concept présent ici est surtout Procédural, et non pas objet.
|
Nous gardons ce formalisme tout au long du document afin d’avoir une cohérence globale, tout particulièrement si l’audit est mené par plusieurs personnes, chacune pouvant être affectée à une partie du projet.
Aller plus loin:
NDepend contient d’autre vue graphique très pertinentes tel que le Code Coverage qui représente graphiquement la couverture des tests sur une cartographie où la proportion des éléments de ce graphique sont proportionnels à une métrique qui peut être le nombre de ligne de code où la complexité cyclomatique. Ci-dessous un exemple (Source : https://www.ndepend.com/docs/code-coverage )
Ce type de représentation fournit très rapidement une vision globale et synthétique de la couverture des tests, et elle est très facilement compréhensible même par des profils peu techniques. Ce qui est particulièrement intéressant quand il faut appuyer un argumentaire auprès des décideurs.
Bien entendu cela n’est possible qui si le rapport des tests unitaires est mis à disposition de l’auditeur. Il n’est pas nécessaire de savoir rejouer les tests, NDepend est en mesure d’importer le fichier généré par les principaux Frameworks de test tel que Visual Studio, Ncover, DotCover.
Et après ?
Cet article présente NDepend dans une démarche nécessitant une compréhension rapide de la structure d’une application sans aucune connaissance préalable du contexte technique et métier. Mais cet outil n’est pas limité à un tel usage, il est même particulièrement pertinent dans une analyse continue de la qualité du code source, ce dernier s’intégrant parfaitement dans une chaine d’intégration continue. Il offre notamment des notions de seuil d’alerte pouvant bloquer une livraison (notion de Quality Gates : https://www.ndepend.com/features/quality-gates#QualityGates ) et des graphiques d’évolution de certaines métriques.
L’outil est donc pertinent pour une utilisation au quotidien par les chefs de projets qui veulent avoir une vue de l’évolution de la dette technique, et éventuellement observer des ruptures quant à la qualité de la réalisation. A noter que ce rapport peut être généré sous la forme d’un simple site web qui peut être facilement déployé pour être visible de l’ensemble des équipes techniques ( Voir https://www.ndepend.com/sample-reports/ ).
De lus il permet aussi d’apporter une analyse différentielle en comparant l’état actuel de l’application avec une version à une date bien défini. Ce type d’analyse permet d’avoir une vision non plus statique, mais bien dynamique en ne ciblant que ce qui a changé. Cela permet par exemple de contrôler la bonne application des recommandations dans le cas où m’audit se poursuit par une mission d’assistance technique.
Enfin, nous observons une tendance de plus en plus forte quant à l’intégration des processus de développement sur des plateformes tierces comme Azure Dev Ops, et NDepend s’intègre aussi dans ce type d’environnement .
Notre démarche d’audit applicatif s’appuie sur notre expertise du développement logiciel et sur des outils nous permettant d’accélérer le processus d’analyse. Avec un outil tel que NDepend, la productivité et la pertinence sont au rendez-vous dès les premières heures d’analyse : Nous avons à la fois une vue globale de la structure et tout un panel d’anomalies détectées à contrôler. Nous obtenons aussi directement un support graphique pouvant directement être intégré dans le livrable final. Ces mêmes graphiques offrent aussi un moyen efficace de navigation dans des solutions conséquentes.
L’expertise d’audit de code est un moment court dans la vie d’un projet, un outil tel que NDepend intégré en amont permet d’avoir des éléments objectifs liés à la qualité des développements et son évolution.
L’outil ne fait pas tout, et l’expérience de l’auditeur est primordiale pour bien interpréter les résultats. Avec plus de 200 audits à son actif, SoftFluent dispose de l’expertise IT pour vous faire bénéficier d’une analyse critique et objective et vous transmettre des recommandations pragmatiques par ordre de priorité.