Jouons un peu avec Ozcode, un outil de déboguage pour Visual Studio

Il arrive fréquemment de se battre avec le débogueur de Visual Studio pour avoir une vue vraiment nette de ce qui se passe dans le code. Et puisqu’un développeur passe une partie non-négligeable de son temps à déboguer (parfois plus qu’à développer), c’est important. Même lorsque l’on est un adepte des démarches TDD et BDD. Ozcode est un plugin qui vise à simplifier le processus. Voyons voir de quoi il est capable.

Avoir une vue claire sur l’état du code à l’instant T

Considérons le code suivant :

using System;
using System.Collections.Generic;
using System.Linq;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main()
        {
            IEnumerable<BlogPost> postsFromDatabase = GetPostsFromDatabase();
            IEnumerable<BlogPost> postsFromCache = GetPostsFromCache();

            if (GetPostsFromDatabase().Any() && GetPostsFromCache().Any() && postsFromCache.Count() < postsFromDatabase.Count())
            {
                Console.WriteLine("We have data.");
            }

            foreach (var post in postsFromDatabase)
            {
                string printLine = string.Format("BlogPost #{0} - Name : {1}", post.Id, post.Name);
                if (!postsFromCache.Contains(post))
                {
                    printLine = printLine + @" - /!\ is not cached !";
                }
                Console.WriteLine(printLine);
            }

            Console.WriteLine("Hit enter to exit.");
            Console.ReadLine();
        }

        #region Privates
    }

    internal class BlogPost : IEquatable<BlogPost>
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public bool Equals(BlogPost other) { return other.Id == Id; }
    }
}

Le but est simple : nous voulons afficher tous les blogposts d’un blog, et mettre en valeur lesquels n’ont pas été mis en cache. Le résultat à l’exécution est le suivant :

output

Je ne sais pas pour vous, mais moi, j’ai l’habitude de parsemer mon code de variables en vue de faciliter le déboguage. Et même si dans sa dernière version, Visual Studio permet de voir la valeur de retour d’une méthode, tout n’est pas encore parfait. OzCode a une réponse à ça : sa fonction Simplify.

Nous allons maintenant poser un point d’arrêt sur la ligne suivante :

IEnumerable<BlogPost> postsFromDatabase = GetPostsFromDatabase();

Passons à la ligne suivante avec F10. L’icône Simplify apparaît maintenant. Lorsque l’on clique dessus, nous voyons les informations suivantes :

Simplify1

Au survol de l’appel la méthode GetPostsFromDatabase, nous avons accès au détail :

Simplify2

Ca ressemble beaucoup au débogueur natif de VS, avec un ajout non-négligeable : une zone de recherche. Sur de grandes collections, ça permet de chercher rapidement un élément précis. On peut d’ailleurs envoyer un élément précis vers la fenêtre Watch native de VS. Pratique.

Search1

Il est également possible de filtrer le contenu d’une liste :

Filter1

Notons que l'Intellisense est de la partie, ce qui facilite grandement l’écriture d’expressions.

Mieux, lorsque l’on passe sur la ligne suivante if (GetPostsFromDatabase().Any() && GetPostsFromCache().Any() && postsFromCache.Count() < postsFromDatabase.Count()), on peut facilement voir le détail de l’évaluation :

Simplify3

Les flèches permettent de faire du drill-down et d’identifier facilement le membre de l’expression qui pose problème. Ca, c’est pratique.

Il est également possible à partir de créer un point d’arrêt conditionnel très facilement via l’interface.

En revanche, plusieurs points vraiment pas pratiques et quelques interrogations :

  • Si je pose un point d’arrêt directement sur la ligne suivante (l’appel à GetPostsFromCache), pas de bouton Simplify. Il faut absolument être dans un contexte de debug, et donc mettre un point d’arrêt sur ou avant la ligne à étudier et faire F10 ou F11. Déroutant.
  • Le survol de l’appel de GetPostsFromDatabase affiche exactement les mêmes informations que le survol de la variable postsFromDatabase. L’intérêt s’en retrouve très limité.
  • Nous sommes toujours obligés de stocker le résultat de GetPostsFromDatabase dans une variable, sinon, pas de bouton Simplify. Il n’est pas possible d’écrire directement foreach (var post in GetPostsFromDatabase()) par exemple. Il s’agit sans doute de défauts de jeunesse du plugin, mais c’est embêtant.

Comparaison d’instances d'objets

OzCode permet facilement de comparer des objets en mémoire. Dans notre cas, nous avons un bug car un des blogposts n’est pas en cache. Nous souhaitons donc comparer postsFromDatabase et postsFromCache.

Compare1

OzCode affiche l’ensemble des objets en mémoire de même type que postsFromCache.

Compare2

Il est possible de n’afficher que les lignes qui diffèrent :

Compare3

Cette fonctionnalité peut être d’une assistance non-négligeable dans la recherche d’un bug.

Enfin, il est possible d’afficher la ou les propriétés que l’on souhaite sur une liste d’objets, plutôt que leur type :

Reveal1

Retour vers le futur

OzCode a une killer feature : sa fonction Foresee. L’objectif est de prévoir un peu mieux ce qui va se passer dans le code. Pour en bénéficier, il faut passer OzCode du mode Standard au mode Enhanced :

Options

Relançons maintenant l’application et plaçons-nous sur la ligne foreach (var post in postsFromDatabase :

Foresee1

OzCode affiche maintenant un indicateur de là où nous en sommes de l’itérateur foreach sur postsFromDatabase. Et l’on peut également voir le détail de la liste, mais surtout se rendre directement à l’occurrence en question. Couplée à la recherche, cette fonctionnalité se révèle puissante et efficace.

… et tout le reste

Nous venons de voir les fonctionnalités principales de OzCode. Il en reste quelques unes :

  • la possiblité d’afficher toutes les instances d’une classe, ce qui peut se révéler utile quand on recherche l’origine d’une fuite mémoire par exemple
  • un raccourci vers les derniers process pour lesquels on a fait un “Attach to process”. C’est tout bête, mais tous ceux qui ont travaillé sur le déboguage d’applications hébergées dans IIS se demanderont pourquoi ça n’a jamais été fait avant.
  • une fenêtre d’exploration des exceptions : utile lorsqu’on travaille sur des Exceptions imbriquées ou des AggregateExceptions
  • de l’instrumentation dynamique : il est possible de tracer les passages sur une ligne de code précise, avec les valeurs des paramètres, la callstack, etc. Et aussi d’exporter les traces en CSV. Du log non-intrusif, tout compte fait.

Conclusion

Le plugin OzCode pour Visual Studio est loin d’être parfait. Espérons que ce sont des erreurs de jeunesse. Mais en l’état, il peut se révéler très pratique. Les fonctionnalités de comparaison d’instances d’objet, de recherche et de foresee sont réellement intéressantes. Certains comportements sont un peu étranges, mais j’aime bien l’outil !