Der Debugger Canvas wurde vor einiger Zeit von Somasegar in seinem Blog angekündigt. Eigentlich aus dem Bereich Microsoft Research wurde er über DevLabs veröffentlicht. Dort findet sich auch eine nähere Beschreibung inklusive einem einführenden Video.
>> mehr…
Was ist “Debugger Canvas”? Laut DevLabs…
“About Debugger Canvas
Debugger Canvas is a new user experience for the debugger in Visual Studio Ultimate. It pulls together the code you’re exploring onto a single pan-and-zoom display. As you hit breakpoints or step into code, Debugger Canvas shows just the methods that you’re debugging, with call lines and local variables, to help you see the bigger picture.
[…]
Debugger Canvas is the result of a collaboration between Brown University and Microsoft, integrating ideas from Brown University’s Code Bubbles project into Visual Studio.” (link)
Ist Debugger Canvas wichtig? Eigentlich nur für Entwickler (oder kurz: JA!) Immerhin war er selbst Mary-Jo Foley (MJF) einen Beitrag wert.
Die Beschreibungen waren interessant genug, das Video machte mich neugierig, also warum das Ding nicht mal ausprobieren?
Der Praxis-Test
Zur Einarbeitung bastle ich gerade mehr oder weniger regelmäßig an einer WP7-Anwendung. Spezielle Plattform, asynchrone Verarbeitung und Multithreading, Debuggen am Gerät. Wenn das keinen Debugger unter Stress setzt. Also die ideale Spielwiese, um den Debugger Canvas einfach mal über eine Zeitstrecke zu verwenden und zu sehen, wie er sich in der Praxis bewährt. Und wie immer: Es gibt Licht und Schatten… .
Licht: Works as advertised!
Was bislang nur im “Call Stack” als Liste ausgegeben wird, wird im Debugger Canvas zum Konzept: Während des Durchsteppens durch den Quelltext öffnet sich jede Methode beim “step in” in einem eigenen Unterfenster und bleibt auch offen. Nach einer gewissen Zeit hat man so schließlich alle durchlaufenen Methoden aus dem Call Stack und die Historie des Kontrollflusses sichtbar.
Zusätzlich kann die Anzeige der jeweils gültigen lokalen Daten in bestimmten Fehlersituationen gute Hinweise liefern, ab wo sich ein Fehler eingeschlichen hat – womöglich schneller als beim klassischen Debuggen.
Gerade Zusammenhänge und Abläufe von Code-Fragmenten werden dadurch besser erkennbar, ein bisschen wie ein “lebendes” Sequenzdiagramm. Und wenn man tiefer in den Call Stack abgetaucht ist, hat man doch den größeren Zusammenhang besser im Blick.
Dazu kommen die Möglichkeiten der Suche und der Annotation…
… und des Exports der Debugging Session als .XPS-Dokument.
Alles in allem eine gute Sache.
Zwielicht: Was mir nicht ganz so gut gefällt…
Wenn man im “Call Stack Window” eine frühere Methode anklickt, wird diese ebenfalls im Debugger Canvas geöffnet. Allerdings gilt das nicht für die Methoden, die zwischen den beiden Methoden im Call Stack enthalten sind; stattdessen wird eine andere Darstellung des Verbindungspfeils gewählt. Das gleiche passiert wenn man über eine Methode springt und dabei an einem Breakpoint tiefer in der Aufrufhierarchie “hängen bleibt”, wie hier dargestellt:
Es ist zwar einerseits sinnvoll nicht gleich den kompletten Call Stack aufzuziehen. Andererseits verschwinden diese Verbindungen aber nicht, wenn man die dazwischen liegenden Methoden öffnet, so dass sie irgendwann zur Verwirrung beitragen. Dazu kommt das Verhalten, dass Debugger Canvas Fenster offen bleiben und bei nachfolgende Debugger Sessions wieder verwendet werden – samt altem Inhalt. In der Summe führen diese beiden Dinge dazu, dass das Canvas Fenster sehr schnell ziemlich überladen wirkt. Der folgende Screenshot entstand nach einer nicht einmal sehr umfangreichen Debugging Session:
Natürlich kann man einzelne Unterfenster gezielt schließen, oder auch das Canvas Fenster komplett schließen, was bei nächster Gelegenheit einen neuen, leeren Canvas erzeugt. Aber irgendwie wünscht man sich eine bessere Lösung. Vielleicht die Unterfenster der vorherigen Session ausgrauen, bis sie angesprochen werden?
Ein anderer Punkt ist, dass man die Übersicht über den Call Stack hinweg gegen die Übersicht im Quelltext eintauscht. Zwar gibt es im Kontextmenü den Eintrag “Navigate to file”, hier wünscht man sich aber eine schnellere Navigationsmöglichkeit. “Go to definition” (F12) funktioniert übrigens und macht den Zielcode ebenfalls im Debugger Canvas auf.
Last not least: Im Zusammenhang mit Threadwechseln springt die gerade aktive Codezeile im Debugger Canvas genauso, wie beim normalen Debugger. Allerdings macht sich das hier schmerzlicher bemerkbar, denn die logischen Abläufe, die der Debugger Canvas ja darstellen will, werden durch Threadwechsel etwas konterkariert. Hier wäre eine Berücksichtigung von Threads in der Darstellung wünschenswert; vielleicht durch unterschiedlich farbige Hervorhebung, oder auch durch getrennte Canvas-Fenster.
Schatten: Ein paar Dinge empfinde ich als echte Bugs bzw. Lücken…
Hält die Programmausführung an einem Breakpoint an, so wird die entsprechende Methode in einem neuen Unterfenster im Debugger Canvas geöffnet. Dieses Unterfenster enthält auch nur diese Methode, keine weitere. Leider ist es so, das das Fenster zwar in der Größe erzeugt wird, die zur Anzeige der Methode notwendig ist, aber oft genug ist die aktuelle Code-Zeile mit dem Breakpoint außerhalb des sichtbaren Bereichs gescrollt. Eine Kleinigkeit aber extrem nervig. (Beim Durchsteppen tritt das Problem nicht auf.)
Zudem ist das Unterfenster zwar in der Größe veränderlich, kann aber nur verkleinert werden, was der Übersichtlichkeit manchmal hinderlich ist. Und definitiv ein Fehler: Der Kommentar über der Methode ist nicht enthalten und kann bei der Editierung auch nicht eingegeben werden. (Editierung muss in den Optionen explizit eingeschaltet werden und wird als “experimentell” bezeichnet.)
Was auch noch nicht ganz rund ist, aber wohl dem momentanen Entwicklungsstand geschuldet, ist die Integration mit dem normalen Debuggen und die Möglichkeit des schnellen Wechsels. Hat man den Debugger Canvas als “Debugger Experience” eingeschaltet, kommt man nicht in das normale Debugging. Verwendet man das normale Debugging kann man zwar den Debugger Canvas zuschalten und dort im aktuellen Call Stack navigieren, das “step in”/”step out” wird aber immer zurück zum normalen Debugging im regulären Source führen. Eine bessere Integration mit schneller, einfacher Wechselmöglichkeit zwischen beiden Ansichten würde das Debugging deutlich verbessern, die Vorteile beider Ansätze vereinen – und es würde die Experimente mit der Editierbarkeit im Debugger Canvas überflüssig machen.
Was kommt nach Licht, Zwielicht und Schatten? Finstere Nacht!
“a new user experience for stepping through code in the debugger in Visual Studio Ultimate.” (link)
Im derzeitigen Stand kann ich die Abhängigkeit von der 15k€-Version verstehen – Debugger Canvas integriert sich mit IntelliTrace, und das ist nur dort vorhanden – aber falls das Einzug in Visual Studio hält, hoffe ich doch, dass das auch für die Professional und Premium Version gilt. (Allerdings enthält Microsoft diesen Versionen auch die Modellierungsmöglichkeiten vor, ich würde hier also keine Wetten abschließen.)
Verdict
Der Debugger Canvas ist zunächst etwas ungewohnt, aber erschließt sich einem – bei ausreichend hoher Bildschirmauflösung – recht schnell. Bestimmte Problemstellungen lassen sich damit besser nachvollziehen als mit dem normalen Debugger, insbesondere wenn es um Probleme mit dem logischen Ablauf geht.
Um sein volles Potential ausspielen zu können, wäre meiner Meinung nach aber eine engere Integration mit dem herkömmlichen Debugger nötig. Und für den Bereich Multithreading ist noch die eine oder andere gute Idee notwendig, in der jetzigen Version ist das eher verwirrend als hilfreich.
Stabilitätsprobleme konnte ich keine feststellen, auch nicht bei den als experimentell bezeichneten Features. Ausprobieren lohnt sich also – wenn man Visual Studio Ultimate zur Verfügung hat.
In diesem Sinne: Happy Debugging 😉