Debugging is a skill with several learning plateaus. Anyone can fire up the debugger in Visual Studio, set a few breakpoints, and step through various code modules while using watches. The climb up to next plateau might involve learning how to use other aspects of the debugger such as the immediate window, or better understanding how to dig through various data types to find pertinent information. Higher levels of might involve full understanding of Visual Studio’s debugging capabilities, and how to best make use of the features during a debugging session.
Skilled software development professionals have climbed up these plateaus already, their experience honed in the school of hard knocks, and if they’re lucky, via good mentors. They’ve built up a list of tricks and methods to best use the tools available to them, tune their debugging environment, and quickly locate problems.
In this article several highly accomplished developers discuss their tricks for debugging in for Visual Studio .NET. Respondents for this article are:
- James Avery, Principal of Infozerk, Inc., author of Visual Studio Hacks, and host of this website.
- Ben Carey, Senior Consultant at Statera Consulting in Denver Colorado
- Kate Gregory, founding partner of Gregory Consulting Limited
- Scott Hanselman, Chief Architect at Corillian Corporation, a leading provider of eFinance solutions
- Josh Holmes, principal and senior software consultant with SRT Solutions
- Drew Robbins, Developer Evangelist for Microsoft’s Heartland District
- Roy Osherove, Principal of Team Agile located in Israel, and a consultant for Agile software development and .NET Specialist
- Bill Wagner, Founder/Consultant with SRT Solutions and author of “Effective C#”
Gregory’s a fan of screen real estate when debugging. “I kill dynamic help and stack my properties window in with everyone else instead of taking up half of one side vertically. Then I unpin pretty much everything…. I love screen real estate.” She also tends to switch profile types and her environment settings often. “I use the ‘Visual Studio Developer’ layout most of the time. I flip to the ‘Visual C++ Developer’ layout if I’m about to do a C++ presentation, for the audience’s sake. I use import/export settings a lot.”
Gregory also gets a lot of use from various windows, saying “I make sure that autos, locals, and call stack are all visible when I’m at a breakpoint, and I LOVE the new Quick Console in 2005. I am also a longtime fan of the immediate window. Partly because, when I’m working in VB, it lets me show off my way-cool-can-you-believe-I-remember-this skills from my BASIC days of almost two decades ago, like ‘?’ for print.”
Practical use of various VS features is high on Gregory’s list of tricks: “Use the data tips. Drill into things and see what all the values are. Set conditional breakpoints. I just cringe when I watch people hit F5 over and over and over so they can get to the time through the loop when i is 15 or whatever. Use the call stack to figure out how you got here in the first place.”
Many, but not all, pros use various tools to help them in debugging. Avery counts two tools as helpful in his work. “I am a big fan of the new Visualizer model in Visual Studio 2005. One of my favorites is the Cache Visualizer from Brett Johnson. It gives you a great view into the ASP.NET cache, what dependencies are there, and more.”
Breakpoints are central to any debugging session, but sometimes they don’t function as you’d expected. Avery’s second helpful tool is ControlAV’s BreakPoint Helper http://www.controlav.com/bphelper/. “It’s great for figuring out why your breakpoints aren’t working.”
TestDriven.NET http://www.testdriven.net/, a Visual Studio plugin written by Jamie Cansdale, gets lots of attention from Carey, who uses “TestDriven.net as a harness for my debugging. I’ve usually written a test before I write the code so I almost always have a starting point for my debugging. The ‘test with… debugger’ functionality is a great starting point for debugging. When I have my tests defined with deterministic inputs, I always have a way to repeat the situations that I am debugging. The tests that accumulate while debugging provide me with good documentation if I ever need to come back to the code that is in question.”
Hanselman is also a fan of TestDriven.NET. He’s emphatic about writing good tests first, though, saying “Use Test Driven Development along with TestDriven.NET. It may be hard to believe, but the better your tests are the less often you’ll need to use the Interactive Debugger. I debug less when I have good tests.”
Hanselman’s blog reveals his fascination with gadgets. Hanselman carries this over into his debugging work: “I use the Ergodex (http://www.ergodex.com) to create custom debugging keybindings so things like QuickWatch are one keystroke instead of two.” More information on this setup can be found on Hanselman’s blog.
Debugging-specific addins aren’t part of Hanselman’s toolkit, but he does recommend “Zanebug http://www.adapdev.com/zanebug/, a free test runner (think NUnitGui on steroids), when I want to do Testing along with integrated performance counters.”
Holmes casts a third vote for TestDriven.NET, noting the ease of writing “a small unit test that will create the scenario that I’m trying to test and then I can debug that by running just that test. These unit tests are also compatible with NUnit so it makes it easy.”
Watches and breakpoints are the workhorses for Holmes. “The watches allow me to quickly see what all of the data is when I enter a particular function. This is an immense help when trying to track down an issue. The breakpoint functionality in VS.NET is fantastic because it allows me to not only set a break every time I hit a line, but to only break there when certain conditions are met. For example, I can hit a break point in a loop every 10th time that it runs through or only break on a certain line if a Boolean variable is true and so on.”
“One of the coolest unknown features in VS 2005 is the ability to set ‘Trace Points’,” says Osherove. “You set them either by right clicking on a breakpoint and selecting ‘When Hit’, or right clicking on the user pane and selecting ‘Add tracepoint’ from one of the submenus.” Osherove finds these very helpful since “they do automatic tracing by method name, module and various other ‘macros’ without breaking when the code is reached. So you get effortless tracing in debug mode.” He hopes they’ll be developed further, maturing “into a more configurable and extensible feature which will allow you to trace even in release mode, at the client’s site, based on configuration.”
Osherove also points out a useful attribute, DebuggerStepThrough, which “allows you to ’skip’ pieces of code you’re not interested in stepping through using the debugger (like get-set properties for example). It makes debugging faster and less annoying.”
Debugging multiple threads can be a difficult task. Osherove offers up a useful tip for this situation: “When debugging multiple threads its good to know that you have the ability to step through a specific thread’s execution path by selecting the thread you want from the ‘threads’ combo. You can add that toolbar to the VS toolbars by rightcliking on the main toolbar.”
Osherove casts yet another vote for TestDriven.NET as an invaluable debugging tool. “Jamie Cansdale rocks.” He also has a terrific trick for use in the Immediate Window: “Add a debug method to your code that does something like iterate through all the objects in a collection. Then you can call that method from the immediate window while in debug mode and it will enumerate various things for you. Think of it like a command-line-debugger-helper. You can write as many of those as you like.”
Fancy functionality and tools are great, but sometimes simplicity rules for usefulness. Robbins is a fan of the ease of debugging web services in the newest release of Visual Studio. “Visual Studio 2005 makes it real easy to step into Web Services. You no longer need to attach to the Web Service host process and set a break point to get the debugger to stop in the Web Service code. When you are debugging your client application and get to the Web Service method call, simply choose step-into and Visual Studio 2005 does the rest. Just make sure both projects are loaded in your solution.”
Wagner usually sticks with defaults for his debugging environment; however, he has two configurations for specific scenarios. “If I’m working on any code that uses large arrays (typically numerical analysis), I’ll dock the watch windows to the side of the workspace, rather than the bottom. Also, if I’m debugging drawing code, I’ll set the debugger and the debuggee side by side so I can see the effects of the drawing code, and not generate new paint messages by laying the VS window over the debuggee.”
Wagner also offers a suggestion for working in the debugger. “Create an object ID for tracking an object quickly. I’ll use this in many scenarios, but the overriding reason is when I’m looking data that is buried inside some container: For example, when I need to keep track of one particular object in a collection. By right-clicking on a data object when a breakpoint is hit, you can assign an object ID to the object. Then, you can refer to that object in the watch window. It’s much easier to type ‘1#’ rather than myCollection.GetAt( rowIndex*rowLength + colIndex ).”
Wagner’s most important tip? “Subscribe to Jim Gries’s blog: http://blogs.msdn.com/jimgries/default.aspx He’s always got an incredible amount of information on tips you never know you could do with the debugger.”
Visualizers are one of the greatest new features in Visual Studio 2005. They enable developers to actually understand data in the debugger instead of having to struggle through undecypherable information when viewing something like a DataSet via the Watch window. Developers can write their own visualizers for VS2005. I wondered what visualizers these pros were hoping someone would come up with.
Gregory would like to see a DataAdapter visualizer, and also has an idea for a fun, if not overly useful visualizer. “Wouldn’t it be cool if you could play streaming audio or video? But I wouldn’t use it in real life.”
Exceptions are something Avery would like to see someone write custom visualizers for. “I want to see an improved view for Exceptions. While the new dialog is nice, it doesn’t help you when dealing with inner exceptions. I would love to see a visualizer that allows you to easily dig through the inner exceptions and perhaps even some better styling on the stack trace.”
Hanselman would like to see “An XmlSerializer visualizer that takes any object and displays what it will look like when serializer. DotNetDan has a nice visualizer for Data up on http://www.codeproject.com/csharp/DataDebuggerVisualizer.asp and up on Project Distributor http://www.projectdistributor.net/Projects/Project.aspx?projectId=91 but he hasn’t updated in a while. Maybe he can be pressured by his peers.”
Wagner’s looking for better graphics support: “I’d want to be able to examine image data much more effectively. I want to look at a bitmap like the zoomed mode in the image editor, and roll over a pixel to get the RGBA values.”
“In-memory representation of an object model (with reference counts)” is a visualizer Osherove would like to see. He’s added his own contribution to the mix: “I’ve created my own collection of Debug Visualizers for Regular Expressions. You can download them here: http://regex.osherove.com.”
Osherove also points out a useful DataSet Quick Watch for Visual Studio 2003 which functions much like a DataSet visualizer in VS2005. The addin can be downloaded from Code Project: http://www.codeproject.com/csharp/DSWatch.asp.