Visual Studio : Comment améliorer son efficacité
Bien programmer est une des facettes du métier de développeur ; être capable de comprendre les besoins du client en est une autre. Aujourd’hui je vais vous parler d’une troisième facette tout aussi importante : bien maîtriser les outils de développement utilisés quotidiennement, et en premier lieu, l’IDE dans lequel vous passez certainement plus de 80 % de votre temps.
A travers mes précédentes expériences, j’ai souvent constaté que lorsqu’on présente au développeur l’IDE sur lequel il va devoir travailler dans sa nouvelle équipe, il cherche à être efficace immédiatement et se concentre donc sur les 3-4 actions primordiales (édition, compilation, exécution). Pourtant de nos jours, les IDE sont devenus des outils extrêmement puissants et très complets (ce que l’on peut malheureusement juger par la lenteur accrue à laquelle ils se lancent à chaque nouvelle release).
J’estime que la majorité des (jeunes) développeurs n’exploite que 10 % des capacités de leur IDE. Alors bien sûr, toutes les fonctionnalités de l’IDE ne sont pas forcément utiles pour le travail de tous les jours (par exemple, si vous ne faites pas de développement de base de données, ou d’interface graphique). Pourtant, en tant qu’outil principal de développement, l’IDE mérite qu’on passe un peu de temps à apprendre certaines de ses fonctionnalités, et si cela vous ralentira un peu initialement, vous serez gagnant à la longue.
Dans cet article, je vous invite donc à découvrir quelques fonctionnalités très utiles de Microsoft Visual Studio qui vous permettront d’accroître très vite votre productivité et améliorer votre capacité à déboguer efficacement vos programmes. Notez que même si vous n’utilisez pas Visual Studio, on retrouve bon nombre de ces fonctionnalités dans les principaux IDE.
Optimiser son environnement de travail
Le premier conseil que je donne aux jeunes développeurs, c’est d’optimiser leur environnement de travail. Et je ne parle pas ici seulement des réglages de leur fauteuil ou de la position du pot à crayon, mais bien de la disposition des fenêtres de l’IDE. En anglais, on utilise de terme de « Screen Real Estate », inspiré du marché immobilier, qui souligne bien que l’écran est une ressource limitée.
C’est d’autant plus vrai que nous sommes de plus en plus équipés d’écrans au format 16:9, qui tend à réduire l’espace de travail vertical. C’est pourquoi une des premières actions à entreprendre dans votre IDE est de masquer tout ce qui est superflu pour laisser un maximum de place aux informations importantes.
Les barres d’outils : vous pouvez masquer les nombreuses barres d’outils par défaut sous la barre de menu pour n’en garder qu’une, voire aucune, car il est tout à fait possible de placer les quelques icônes d’outils tout en haut à droite dans la barre de menus.
Je recommande donc de ne garder que des outils essentiels tels que la sélection de la plateforme et de la configuration de build, un bouton pour arrêter l’exécution du programme, et le champ de recherche rapide de texte (voir plus loin).
Les panneaux d’affichages : Autour de votre code se trouve tout un tas de panneaux d’affichages, certains très utiles, et d’autres moins utiles. Ces panneaux sont rétractibles, vous pouvez donc masquer ceux que vous n’utilisez jamais, et réduire sous forme d’onglets en bord d’écran ceux que vous utilisez rarement.
Pour les panneaux restants (ceux qui vous sont régulièrement utiles), je vous encourage à vous poser cette question : lesquels présentent une information plutôt horizontale, et lesquels présentent une information plutôt verticale ? Par exemple, les résultats de recherches sont plutôt horizontaux car cela affiche souvent des lignes longues, et le navigateur de solution est plutôt vertical car il contient une liste de courts noms de fichiers. Vous pourrez alors réserver les 3/4 de votre écran à l’éditeur de code, et disposer ces panneaux suivant une bande horizontale en dessous de votre code, et une bande verticale à gauche de votre code.
J’en entends qui me disent « pourquoi à gauche et pas à droite ? ». Elémentaire mon cher Watson : la fatigue oculaire ! Votre œil n’est pas fait pour faire une gymnastique permanente et pour aller chercher tout à gauche de l’écran le début des lignes de code. En plaçant des outils à gauche du code, vous disposez d’une marge naturelle afin que vos lignes de code occupent essentiellement le centre de votre vision
N’oubliez pas que vous pouvez également superposer certains panneaux qu’il n’est pas utile d’avoir en parallèle. Autre remarque importante : Visual Studio sauvegarde 2 dispositions de panneaux. Une en mode d’édition classique, et une lors du débogage du programme. Vous pouvez ainsi afficher/masquer et agencer les panneaux adéquats suivant le mode.
Quelques réglages initiaux (menu Tools/Option)
Revenons un peu sur la fatigue visuelle.
Historiquement, la police de caractère par défaut de Visual Studio et des éditeurs de textes a toujours été « Courier » car il s’agit d’une des rares fontes à espacement non-proportionnel présente depuis les débuts de Windows. Mais cette police de caractère est une aberration de nos jours, avec des traits trop fins, et plusieurs caractères ambigus (zéro / lettre O, chiffre 1 / L minuscule, etc.).
De nombreuses études ont été menées pour mettre au point une police de caractère spécialement à destination des informaticiens : cette police s’appelle Consolas et est installée en standard dans Windows depuis plusieurs versions déjà. Elle dispose de traits plus épais, de caractères bien définis et reconnaissables.
Je vous invite donc à vous rendre dans les Options de Visual Studio > Environment > Fonts and Colors, et changer la police du code et des panneaux de code pour Consolas.
Attention : cette police nécessite que le lissage ClearType de Windows soit actif (en Remote Desktop, celui-ci risque d’être désactivé). Pendant que vous êtes dans les Options, je vous invite à vous rendre sous Projects And Solutions et cocher la case qui affiche le panneau des erreurs en cas d’erreur de build. Ce panneau vous permettra de parcourir aisément les Warnings et Erreurs de la dernière compilation.
Un autre réglage à activer se trouve sous Debugging > Symbols : Use Microsoft Symbols Servers. Cela indique à Visual Studio de télécharger automatiquement auprès des serveurs de Microsoft sur Internet, les symboles de débogage associés aux DLL de Windows qui sont utilisées directement ou indirectement par votre programme. Ce réglage est primordial pour avoir des piles d’appels correctes. En effet, sans les symboles de débogage, Visual Studio n’est pas toujours en mesure de comprendre les enchaînements d’appels et peut faire des erreurs dans sa compréhension de la pile d’appel.
Attention : le premier lancement d’un programme après activation du réglage peut prendre jusqu’à 5 minutes. Ceci est dû au possible téléchargement des informations d’une quarantaine de DLL (ces informations sont conservées en cache pour ne pas les récupérer à chaque fois).
Cette option peut également s’avérer utile si vous déboguez un Crash Dump obtenu sur une machine différente de la vôtre (notamment avec une version de Windows différente).
Les raccourcis clavier
Vous connaissez certainement quelques raccourcis clavier de base. Pourtant Visual Studio dispose de nombreux raccourcis clavier qui vous permettrait d’être encore plus efficace. Mais plus encore, vous pouvez complètement personnaliser les raccourcis clavier et utilisez ainsi ceux que vous souhaitez, via le menu Environment > Keyboard
Parmi les raccourcis clavier classique à connaître afin d’éviter de cliquer à tout va :
F9 Breakpoint
F10, F11 Step Over, Step Into
Shift F11 Step Out (jusqu’à la sortie de la fonction)
F12 Aller à la définition du symbole
Shift F12 Aller aux références du symbole
Ctrl Num+ Référence suivante
Ctrl Num- Référence précédente
Ctrl Num* Revenir au contexte précédent F12/Shift F12
Ctrl L Couper la ligne courante
Ctrl Alt Q Quick Watch
Ctrl K-K Poser/Retirer un signet
F2 / Shift F2 Aller au signet précédent / suivant
Ctrl D Activer le champ de recherche rapide
(Certaines touches peuvent différer suivant votre configuration)
A propos du champ de recherche rapide
Ce champ accepte aussi des commandes spéciales pratiques :
<a href="https://rebirth.devoteam.com/wp-content/uploads/2015/11/d2si_blog_image_visualstudio6.png"><img class="aligncenter size-full wp-image-5822" src="https://rebirth.devoteam.com/wp-content/uploads/2015/11/d2si_blog_image_visualstudio6.png" alt="D2SI_Blog_Image_VisualStudio6" width="405" height="66" /></a>
Note : les dernières versions de Visual Studio proposent aussi le raccourci Ctrl-$ pour rechercher rapidement un fichier ou un symbole par son nom dans le Solution Explorer
Les panneaux Watch
Ceux-ci sont très utiles pour afficher les variables, membres et expressions en cours de débogages. Mais saviez-vous que vous pouvez demander à Visual Studio d’afficher certaines structures sous une forme plus pertinente suivant vos besoins ?
Ce système s’appelle « autoexp.dat » dans les versions antérieures et « Natvis » dans les versions récentes de Visual Studio. Il est extensible avec vos propres structures et peut s’avérer complexe à maîtriser, mais si vous étudiez les définitions par défaut fournies avec Visual Studio, vous comprendrez alors comment ce panneau peut afficher par exemple les conteneurs de la librairie standard C++ sous une forme intelligente et utile (avec la valeur des objets contenus) plutôt que les pointeurs bruts des nœuds du conteneur.
Avec ce système :
Sans ce système :
Suffixes :
Les panneaux Watch acceptent également quelques suffixes en fin d’expression :
toto,! affichage brut de l’objet (désactive le système précédent)
toto,5 affichage des 5 premiers éléments pointés (pour un tableau)
toto,m toto,md affichage de la mémoire à cette adresse (cf. aussi le panneau mémoire)
toto,x toto,d affichage du nombre en hexadécimal / en décimal
Pseudovariables :
$err,hr dernière erreur Windows sous forme lisible (= GetLastError)
$eax registre EAX. (correspond souvent à la valeur de retour d’une fonction)
$env=0 affiche les variables d’environnement du programme dans Output
$cmdline=0 idem pour la ligne de commande d’appel du programme
Changement de contexte :
Si un symbole (ou sa structure précise) n’est défini que dans le PDB d’une DLL et pas dans le code en cours d’exécution, cela permet de mieux visualiser ce symbole:
Ex: {,,msvcr120d.dll} _crtBreakAlloc
(permet de visualiser/modifier la variable interne de la DLL runtime de Visual C++ qui interrompt l’exécution au nième appel à malloc)
Appel de fonction :
Il est tout à fait possible d’appeler une fonction du programme débogué. Celle-ci n’est appelée qu’une seule fois au moment où vous appuyez sur Entrée. Pour forcer une réévaluation, il vous faudra cliquer sur l’icône de flèche circulaire à droite de la valeur.
Fonctionnalités permettant de réduire le cycle de développement
Precompiled Headers :
Ils réduisent les temps de compilation en regroupant les headers les plus utilisés dans vos programmes et épargnent au compilateur la tâche de les recompiler à chaque source .cpp.
Ils s’activent via les options du compilateur C++ :
Sur le projet: « Use Precompiled Header »
Sur un fichier stdafx.cpp qui ne contient qu’un #include « stdafx.h » : « Create Precompiled Header »
Et enfin, mettre #include « stdafx.h » en haut de chaque fichier source .cpp du projet.
Edit and Continue :
Ils réduisent les temps de débogage en vous permettant de modifier un source en cours d’une session de débogage.
Très utile notamment lorsque vous avez passé des jours à traquer/reproduire un bug rare et que vous voulez vérifier que la correction de votre code résout bien le problème (vous modifiez et vérifiez le code à la volée dès que vous avez reproduit le problème)
Le système s’active via les options
du compilateur C++: Debug Information Format: /ZI
du linker: Enable Incremental Linking: Yes
Les dernières versions de Visual C++ autorisent aussi ce système sur cible 64 bits, et nécessitent de cocher une option sous Debugging > General.
StepOver :
Ce système permet d’éviter de rentrer dans certaines fonctions quand vous déboguez en pas-à-pas. Ainsi, même si vous utilisez la touche F11 pour « rentrer dans les fonctions », certaines fonctions inutiles seront passées d’un coup et vous entrerez que dans les fonctions qui vous intéressent.
Cela s’exprime par une liste d’expressions régulières identifiant les fonctions à éviter. Celle-ci est stockée dans une clé de registre (pour les versions anciennes de Visual Studio) ou dans un fichier XML « Natstepfilter » (pour les versions récentes).
Ex: std::.* pour ne pas rentrer dans les fonctions de la librairie standard
Symboles de débogage en release :
Il est tout à fait possible de générer les informations de débogage en Release. Ça ne prend pas de place dans l’exécutable distribué car ces informations atterrissent dans le PDB que vous n’êtes pas obligé de distribuer.
En cas de crash, il vous est alors possible de dumper la mémoire du processus et d’analyser en post-mortem le contexte du crash en bénéficiant de tous les symboles, pile d’appels, variables locales.
Bien sûr, à cause des diverses optimisations du compilateur en mode Release, certaines variables locales ne seront pas accessibles aussi facilement qu’en mode Debug.
Astuces avec les breakpoints :
Si vous placez un breakpoint sur la dernière accolade fermante d’une fonction, il s’activera quel que soit la façon dont votre fonction se termine (même via un return anticipé).
Pendant le débogage, on peut créer un Data Breakpoint qui stoppe le programme si cellule mémoire est modifiée, pratique pour comprendre qui modifie une variable globale ou un objet alloué.
Il est possible :
- d’associer une expression conditionnelle aux points d’arrêt.
- de compter le nombre de passages sur ce breakpoint et arrêter au n-ième.
- d’afficher un message et la valeur de certaines variables dans la fenêtre Output, et continuer l’exécution (c’est ce qu’on appelle un Tracepoint).
Ex: début fonction $FUNCTION, param={arg1}
Autres trucs et astuces Visual Studio
Clic droit sur un projet puis Project Dependencies : cela permet d’identifier rapidement les dépendances (cases cochées) d’un projet, mais aussi les autres projets qui utilisent ce projet (cases grisées).
Property Manager (menu View) : ce système puissant permet de gérer des calques de propriétés communes à plusieurs projets (ex: defines, chemin d’includes, etc…). Vous pourrez les définir une fois dans un calque puis appliquer ce calque à plusieurs projets.
Le menu Window|Windows est pratique pour faire le ménage dans les documents ouverts quand vous en avez trop d’ouverts.
N’hésitez pas à décharger (Unload) les projets gênants de vos solutions (ex: ceux qui ne compilent pas, ceux qui sont rarement utilisés ou qui ne sont pas vraiment maintenus par vous).
En debug, vous pouvez passer la souris sur un symbole pour voir en popup sa valeur, pouvoir la modifier (double-clic sur sa valeur), et dérouler le [+] pour détailler les membres. Maintenez la touche Ctrl pour rendre ces popups semi-transparents
Saviez-vous que toutes les versions de Visual Studio (même les plus basiques) viennent accompagnée d’un système de profiling de votre code, nommé PGO ?
Initialement ce système sert à instrumenter votre code pour mesurer vos fonctions afin d’optimiser le travail du linker pour qu’il génère un exécutable plus performant. Mais vous pouvez détourner le système pour qu’il produise un rapport textuel indiquant après chaque session le nombre d’appels à chaque fonction, le temps passés dans chaque fonction et sous-bloc des fonctions. Ce rapport n’est pas des plus user-friendly, mais avec un peu d’entrainement, vous aurez une idée des parties de votre code à revoir.
Voilà, avec toutes ces astuces, vous êtes paré pour devenir la personne de référence sur Visual Studio dans votre équipe !
Bien sûr, ces informations ne sont qu’une initiation et il vous faudra creuser l’aide de Visual Studio ou les nombreuses ressources du net pour vous familiariser plus encore avec les nombreuses fonctions peu connues mais puissantes de cet IDE.