Share via


Examen du code managé

 

John D’Addamio
Microsoft Corporation

Février 2007

S’applique à :
   .NET Framework

Résumé: Ce document décrit les meilleures pratiques pour l’examen du code managé. Certaines pratiques sont universelles pour examiner le code managé et non managé. D’autres sont propres à l’examen du code managé. Bien qu’il soit supposé que vous êtes familiarisé avec au moins un langage managé, il n’est pas supposé que vous êtes un réviseur expérimenté du code managé. (6 pages imprimées)

Contenu

Introduction
Recommandations associées
Méthodes recommandées
Conclusion

Introduction

L’examen du code managé est un peu différent de l’examen du code non managé. À certains égards, l’examen du code managé est plus facile que l’examen d’un autre code. Le compilateur vérifie les types, ce qui empêche l’affectation accidentelle de données incompatibles à un objet. Le compilateur vérifie également l’utilisation de variables qui n’ont pas été initialisées. Ces vérifications et d’autres vérifications de compilation empêchent toute une série de bogues que nous avions l’habitude de rechercher lors de l’exécution de révisions de code. En outre, les vérifications au moment de l’exécution détectent d’autres problèmes courants et contiennent les dommages en lisant une exception. À d’autres égards, le code managé ajoute certains problèmes qui n’existent pas dans d’autres langages, tels que les fichiers de ressources et les éléments XML dans le fichier source lui-même.

Ce document présente les meilleures pratiques pour l’examen du code managé. Bien qu’il soit supposé que vous êtes familiarisé avec au moins un langage managé, tel que C# ou Visual Basic.NET, il n’est pas supposé que vous êtes un réviseur expérimenté du code managé.

Il existe de nombreuses recommandations connexes sur MSDN. Bien que plusieurs soient conçues comme des recommandations de conception, elles s’appliquent évidemment également aux révisions de code. En voici quelques-uns :

  1. Instructions de conception .NET
  2. Directives de nommage
  3. Instructions pour les types de cast

Utilisation de FxCop pour appliquer vos normes de codage

FxCop est un outil d’analyse du code qui vérifie la conformité des assemblys de code managé .NET aux instructions de conception .NET référencées précédemment. FxCop fournit des règles d’analyse de code standard et vous permet de personnaliser les règles de votre projet. La suppression des avertissements FxCop est également autorisée dans le code source. Vous pouvez obtenir plus d’informations ou télécharger FxCop et sa documentation gratuitement à partir de la page d’équipe FxCop.

Exécuter FxCop sur le code en cours de révision

Définissez une configuration de build standard qui exécute l’analyse du code FxCop que chaque projet doit implémenter. Dans le cadre d’une révision du code, vérifiez que le projet a correctement implémenté votre configuration de build FxCop standard et que le code en cours d’examen réussit l’évaluation de FxCop en créant la configuration FxCop.

Vérification de la suppression d’erreurs FxCop dans le code source

Recherchez le code en cours de révision pour la suppression des messages FxCop. Vous pouvez utiliser Ctrl+F pour rechercher « SuppressMessage » dans le projet actuel. Si vous trouvez des suppressions FxCop, vérifiez qu’elles sont légitimement nécessaires et que la raison de la suppression est clairement expliquée dans les commentaires. Parfois, vous pouvez constater que la suppression n’est pas nécessaire, mais que la personne qui écrit le code ne savait pas comment corriger l’erreur. Par exemple, la suppression suivante est inutile.

// FxCop doesn't like the "\n\n" so we suppress the error message here.
[System.Diagnostics.CodeAnalysis.SuppressMessage
("Microsoft.Globalization", "CA1303:DoNotPassLiteralsAsLocalizedParameters", MessageId = 
"System.Windows.Forms.TextBoxBase.AppendText(System.String)")]
this.resultsTextBox.AppendText ("\n\n" + Strings.contextErrorMessage);

Une simple modification du code, comme illustré ici, empêche l’erreur FxCop.

this.resultsTextBox.AppendText( Environment.NewLine + 
Environment.NewLine + Strings.contextErrorMessage);

Examen de la logique

Bien sûr, les points main de l’examen du code sont de rechercher des défauts dans la logique (bogues) et d’appliquer les normes de codage de l’équipe. L’utilisation de FxCop pour appliquer vos normes de codage vous permettra de passer plus de temps à examiner la logique du code.

Le .NET Framework a de nombreuses classes, et chaque classe a de nombreuses méthodes. Par conséquent, utilisez librement les descriptions IntelliSense pour les classes ou méthodes.

Si vous ne pouvez pas comprendre ce que fait le code à partir des commentaires existants et des descriptions IntelliSense des classes ou méthodes, le code n’a pas suffisamment de commentaires. Si vous pensez que la logique ne fait pas ce que prétend l’auteur, la logique est défectueuse ou le code n’a pas suffisamment de commentaires pour le rendre clair.

Création de celui-ci

Il est recommandé de générer le code dans toutes les configurations du projet. L’auteur a peut-être oublié de le générer dans toutes les configurations. S’il n’est pas généré dans toutes les configurations, vous devez demander à l’auteur de corriger les erreurs avant d’envoyer le code.

Par exemple, il est courant de définir la configuration release pour exclure les tests unitaires. Si des modifications sont apportées à la signature d’une méthode mais que les tests unitaires ne sont pas mis à jour, le code est généré correctement dans la configuration Release, mais pas dans la configuration Debug.

Recherche des tests unitaires

Lors de l’examen du nouveau code, attendez-vous à ce que les tests unitaires soient présentés en même temps que le code fonctionnel. Il est trop facile de tergiverser !

Lors de l’examen des modifications de code, des tests unitaires nouveaux ou révisés peuvent être nécessaires. Exécutez les tests unitaires existants et ceux qui sont envoyés avec la révision de code. Si les tests unitaires ne réussissent pas, demandez à l’auteur de mettre à jour le code fonctionnel et/ou les tests unitaires, afin qu’ils réussissent.

Recherche de validation de paramètre

Il est recommandé pour une méthode de valider ses paramètres d’entrée. Si un paramètre n’est pas valide, la méthode doit effectuer une action appropriée. Par exemple, un paramètre de chaîne doit être vérifié comme étant un objet null ou égal à String.Empty. Une action appropriée dans une situation où String.IsNullOrEmpty retourne true peut être de lever une exception (par exemple, une exception ArgumentException ou ArgumentNullException), mais, dans une autre situation, la méthode peut simplement revenir à l’appelant sans effectuer aucune action.

Lors de l’examen du code, recherchez les valeurs de paramètre susceptibles de provoquer un comportement indésirable. Les valeurs « incorrectes » peuvent être aussi évidentes que dans l’exemple de chaîne illustré, mais elles peuvent être moins évidentes. Par exemple, considérez une chaîne censée représenter des données numériques comprises entre 0,0 et 100,0. Le code peut souhaiter effectuer une certaine validation en plus de la case activée Null, comme la suppression des vides de début et de fin, la conversion de la chaîne au format numérique et la validation que la valeur se trouve dans la plage attendue.

Commentaires

Éléments XML requis

Chaque définition de classe et tous les membres publics doivent avoir des balises récapitulatives XML pour décrire la classe ou le membre. Cela permet aux utilisateurs de la classe de voir la description lors de la modification du code. La balise de paramètre XML est également requise, lorsqu’elle s’applique. Dans Visual Studio 2005, les éditeurs de code C# et Visual Basic insèrent automatiquement les balises de résumé et de paramètre , si vous tapez /// et « '' » (respectivement) sur une ligne vide au-dessus de la définition de la classe ou de la méthode. Cela est extrêmement utile, car vous n’avez pas besoin de taper correctement les définitions de balises XML. Vous n’avez qu’à taper les descriptions !

Si votre équipe utilise des en-têtes XML plus élaborés pour les définitions de classe ou de membre (par exemple, certaines équipes nécessitent des en-têtes XML qui décrivent l’historique des modifications, y compris la description des modifications, l’auteur et les informations de date), vérifiez que les en-têtes sont présents et que les données appropriées ont été entrées.

Valider tous les éléments XML

Assurez-vous que tous les éléments XML sont bien formés. Cela est important, car les outils qui gèrent les commentaires XML dans le code source nécessitent un code XML bien formé pour fonctionner correctement.

Supprimez tous les éléments XML générés automatiquement qui sont vides, s’ils ne sont pas requis par votre équipe. Par exemple, Visual Basic génère automatiquement des éléments qui peuvent être supprimés dans de nombreux cas.

Commentaires supplémentaires

Vérifiez que le code contient suffisamment de commentaires supplémentaires pour décrire l’utilisation, la logique ou le comportement des éléments de code.

Qualité des commentaires

Les commentaires doivent être clairs et décrire avec précision le code associé. Il existe plusieurs situations courantes dans lesquelles les commentaires ne correspondent pas au code. Surveillez-les ! Par exemple, si le code existant est modifié dans un module, la mise à jour des commentaires est parfois ignorée. Ou, si une section de code d’une autre application est adaptée à un objectif actuel, les commentaires du code d’origine peuvent ne plus être appropriés ou exacts.

Constantes de chaîne

Fichiers de ressources de chaîne

Les littéraux de chaîne doivent être empaquetés dans un fichier de ressources de chaîne. Cela collecte les chaînes en un seul emplacement, afin que les modifications apportées au texte de chaîne soient plus faciles. L’utilisation de fichiers de ressources de chaîne permet également la localisation et la globalisation. La création et l’utilisation de fichiers de ressources de chaîne auparavant légèrement fastidieux. Toutefois, l’outil de refactorisation des ressources peut vous aider à résoudre ce problème, au moins pour les projets C# et Visual Basic. Par exemple, les littéraux de chaîne dans l’instruction suivante :

private static string snippetSchemaPathBegin = 
Path.Combine(Environment.ExpandEnvironmentVariables("%ProgramFiles%"), 
@"\Microsoft Visual Studio 8\Xml\Schemas");

peut, à l’aide de l’outil de refactorisation de ressources, être rapidement remplacé par les éléments suivants :

private static string snippetSchemaPathBegin = 
Path.Combine(Environment.ExpandEnvironmentVariables( 
Strings.ProgramFiles), Strings.MicrosoftVisualStudio8XmlSchemas);

Noms de fichiers et chemins d’accès

Lorsque vous examinez le code, recherchez les littéraux de chaîne ou les références de fichier de ressources de chaîne qui contiennent des chemins d’accès de fichiers codés en dur. Utilisez toujours des variables d’environnement, des API .NET qui fournissent un nom de chemin d’accès (par exemple, System.Windows.Forms.Application.ExecutablePath, qui retourne le chemin d’accès de l’exécutable qui a démarré l’application) ou une entrée de fichier de configuration pour référencer les chemins d’accès. Personnes installer fréquemment des éléments sur des lecteurs autres que C, et de temps en temps personnaliser l’emplacement d’installation d’autres manières !

De même, les noms de fichiers de l’application ne doivent pas être définis dans un littéral de chaîne ou une référence de fichier de ressources de chaîne. Les alternatives acceptables sont un fichier de configuration, des variables d’environnement ou une entrée de l’utilisateur, comme un paramètre dans une application console ou une boîte de dialogue de fichier dans une application WinForms. L’une de ces alternatives permet à l’utilisateur de bénéficier d’une plus grande flexibilité dans l’utilisation de votre application.

L’exemple suivant montre plusieurs mauvaises pratiques, notamment un chemin codé en dur et une variable publique.

     public static readonly string SnippetSchemaPathBegin = 
@"C:\Program Files\Microsoft Visual Studio 8\Xml\Schemas\";

L’instruction peut être réécrite à l’aide d’une propriété publique et de la variable d’environnement SystemDrive, comme illustré ici.

        public string SnippetSchemaPathBegin { get { return 
snippetSchemaPathBegin; } }
        private static string snippetSchemaPathBegin = 
Environment.ExpandEnvironmentVariables("%SystemDrive%" + @"\Program 
Files\Microsoft Visual Studio 8\Xml\Schemas");

De même, on peut utiliser la variable d’environnement ProgramFiles, comme illustré ici.

        private static string snippetSchemaPathBegin = 
Path.Combine(Environment.GetEnvironmentVariable("ProgramFiles"), 
@"Microsoft Visual Studio 8\Xml\Schemas");

Conventions d'affectation de noms

Noms

En général, les noms doivent être lisibles et doivent décrire clairement l’élément. Par conséquent, recherchez des abréviations dans les noms, les noms courts ou les noms non descriptifs lors de l’exécution de révisions de code. Il est recommandé de commencer les noms de fonction et de méthode avec un verbe, pour désigner l’action qu’ils effectuent sur leurs objets. De même, les noms de variables et les noms de propriétés doivent être des noms, car il s’agit d’objets. Par exemple, si vous écrivez une classe pour des objets de géométrie de plan, comme un cercle, vous pouvez définir des propriétés nommées CenterPoint et Radius. Les noms de fonction d’une telle classe peuvent inclure CalculateCircumference et CalculateArea.

Conventions de casse dans les noms

Vérifiez que le code source suit les conventions de cas recommandées dans la section Styles de majuscule de la documentation Naming Guidelines qui a été recommandée précédemment. En d’autres termes, utilisez camelCassing (la première lettre du nom est en minuscules et la première lettre de chaque mot suivant dans le nom est majuscule) pour les paramètres, les variables locales et les variables privées ou protégées d’une classe. Utilisez PascalCasing (la première lettre de chaque mot dans le nom est majuscule) pour pratiquement tout le reste, y compris les noms de classes, les méthodes, les propriétés, les déclarations de type et les valeurs d’énumération.

Notation hongroise

La notation hongroise n’est pas recommandée pour le code managé. La notation hongroise est difficile à utiliser correctement, ainsi que difficile à lire. Les difficultés de lecture de la notation hongroise peuvent également obfusquer la logique.

Exceptions

Levée d’exceptions

Si le code lève une exception, assurez-vous que le type d’exception est approprié et que le message identifie clairement le problème qui a provoqué la levée de l’exception par le code. Placez autant d’informations de débogage que possible dans le message d’exception. Cela vous aidera lors du diagnostic du problème, qu’il s’agisse d’une trace de pile ou d’un fichier journal.

Exceptions d'interception

Si le code que vous examinez appelle une méthode susceptible de lever une exception, vérifiez que le code gère l’exception et fait quelque chose de raisonnable lors de sa gestion. Par exemple, File.Open lève plusieurs exceptions courantes, notamment FileNotFoundException et UnauthorizedAccessException. Il serait raisonnable d’intercepter ces exceptions et d’afficher un message d’erreur à l’utilisateur.

Définition d’exceptions

Si le code d’un assembly définit des exceptions, définissez les types couramment utilisés dans une classe d’exceptions globales pour l’assembly. Définissez des exceptions propres à une classe dans la classe elle-même.

Mise en forme

Utiliser des régions pour organiser le code

Lorsque vous examinez le code, recherchez une bonne utilisation des régions pour améliorer la lisibilité du code. Les régions sont souvent sous-utilisées, mais parfois surexploitées.

Les régions permettent d’organiser logiquement le code et d’améliorer la lisibilité des fichiers volumineux, car vous pouvez réduire les régions inutiles et voir uniquement la partie du code dont vous avez besoin actuellement. La réduction des régions facilite également le défilement de fichiers volumineux pour trouver une région d’intérêt. Toutefois, soyez prudent quant à la façon dont les régions imbriquées sont utilisées. L’effondrement d’une région externe pourrait masquer les régions internes et rendre plus difficile la recherche d’une région d’intérêt.

Les endroits courants d’utilisation des régions incluent les données privées, les constructeurs, les propriétés publiques, les méthodes privées et les méthodes publiques d’une classe. Dans un projet de test, les régions sont couramment utilisées pour regrouper les tests. Par exemple, une région peut regrouper les tests unitaires pour l’une des méthodes d’une classe.

Utiliser des lignes vides pour séparer les définitions

L’utilisation de lignes vides entre les définitions du même niveau améliore la lisibilité. Toutefois, n’utilisez pas plus de deux lignes vides consécutives.

Divers

Aucune variable publique

Vérifiez que les variables de données d’une classe sont déclarées comme privées. Si vous choisissez d’autoriser l’accès aux données, définissez une propriété publique ou protégée pour accorder à l’utilisateur l’accès.

Valeurs de retour

Les méthodes qui retournent une valeur doivent utiliser l’instruction return, au lieu d’affecter une valeur au nom de la méthode.

Aucune instruction GoTo

Les instructions GoTo ne sont pas nécessaires. On peut parfois faire valoir leur utilisation dans des circonstances particulières, mais ils doivent activer des alarmes lorsque vous les voyez dans une révision de code.

Constantes numériques

Par défaut, presque tous les outils de débogage affichent des constantes numériques en hexadécimal. Par conséquent, définissez des constantes numériques en hexadécimaux pour les ID de fenêtre, les ID de contrôle, etc., afin de ne pas avoir à les convertir de décimales en hexadécimaux pendant le débogage.

Conclusion

Ce document présente les meilleures pratiques pour l’examen du code managé. Certaines pratiques sont universelles pour examiner le code managé et non managé. D’autres sont propres à l’examen du code managé.