Posts in category development - page 5

8 Visual Studio debugging tips – debug like a boss

There are so many useful debugging features built into Visual Studio that aren’t well-known. Here are a few of my favourites, including some recent finds in VS 2013.

1. Breakpoint inside a lambda

Clicking the left gutter to set breakpoints, you could easily believe breakpoints happen at line level.

Breakpoints, though, can be set inside parts of the line, such as inside a lambda in your LINQ expression. Just right-click the part of the code and choose Breakpoint > Insert Breakpoint from the context menu.

2. Usable output window

Visual Studio output window filtering optionsThe output window is useful for debugging where breakpoints would be too invasive or interrupt flow but for the noise.

Just right-click in the output window (make sure output is set to debug) and turn off the Module Load, Module Unload, Process Exit and Thread Exit to leave you with information you care about. Now Debug.WriteLine to your heart’s content.

You can also press CtrlS in the output window to save the contents.

3. Attach debugger to client and server (VS 2012)

It’s useful to have both server and client projects in a single solution so that you only need one copy of Visual Studio running. It’s all too easy to get lost alt-tabbing back and forth - especially when they share code such as a data model project.

One disadvantage is that the startup project is the only one to get a debugger attached. If you encounter an exception, it shows in your client, not your server project.

That’s easily solved now. Right-click on the solution, choose properties and choose Multiple startup projects then select the Start action for the projects you need to attach to.

Visual Studio Solution properties dialog

4. Create a repro project template

If you’re responsible for a SDK or API create a simple application that uses your stuff in a small self-contained way. Then use File > Export template… to save it.

Now you can create a new project from your template whenever you need it with a few clicks. Even better, make it available to users and testers so they can send you minimal repros.

5. Use the DebuggerDisplay attribute

By default, the debugger uses ToString() for watch and auto windows which output the class name. Even if you override ToString it’s probably not what somebody debugging wants to see at a glance.

Add DebuggerDisplay to your class with a simple expression to evaluate properties instead. e.g.:

[DebuggerDisplay("Order {ID,nq}")
class Order {
    public string ID { get { return id; } }
}

The nq prevents double-quotes from being emitted. You can also use methods here too, but don’t do anything with subtle side-effects; otherwise, your observation of the subject changes its behaviour and can cause weird hard-to-track-down issues.

6. Manage breakpoints

You set-up some interesting breakpoints. Now you need to switch one off as it’s getting hit too often but you’ll need it again in a minute. If you remove the breakpoint, you’ll have to come back and find it again.

Enter the much-overlooked Breakpoints window CtrlAltB. This will show all breakpoints you have set but crucially lets you disable them without unsetting them by simply removing the check-mark. Check it again to re-enable it.

Visual Studio breakpoints window

This window also provides the ability to quickly:

  • Condition when a breakpoint should occur
  • Hit count to see how often it is hit, and to break only on that count
  • Label a breakpoint to allow toggling on and off in batches
  • When Hit to put a message in the output window instead of actually breaking

7. Break on or output the caller information (.NET 4.5/Windows 8 Store)

There isn’t a global variable for the current method of the caller. Getting the current stack is a slow operation.

One quick and simple trick is to add an extra optional string parameter to the method with the CallerMemberName attribute. e.g.

void MyFunction(string someValue, [CallerMemberName] string caller = null) {
    ...
}

Because it is an optional value, you don’t need to modify any callers, but you can now:

  1. Set a breakpoint condition inside DoSomething based on the caller variable
  2. Output the contents of the caller to a log or output window

You can also use CallerLineNumber and CallerFilePath. Also remember that constructors, finalizers and operator overloads will display their underlying method names (.ctor, op_Equals etc).</a>

8. See the value returned by a function (VS 2013, .NET 4.5.1/Windows 8.1 Store)

Visual Studio autos windowSometimes you want to see what a function returned, but you can’t easily because you didn’t store the value because it was the input to another function.

Support was added in VS 2013 but is incredibly easy to miss as you have to be in the right place at the right time. The right place is the Autos window, and the right time is exactly the step that returned you to where the function was called from. You won’t see this before you call the function or while in the function. It’s there for a single step and looks like this:

The arrow icon indicates it’s a return value, and it lets you know the name of the function alongside it.

Wrap up

I also can’t stress enough how useful having logs are for troubleshooting once the software leaves your machine. But that’s a much bigger discussion than this one.

Am I missing some great debugging tips? Feel free to let me know below :)

PS: Michael Parshin has some great tips on debugging too.

[)amien

Designing a great API

Several years ago I worked on a payroll package developing a core engine that required an API to let third parties write calculations, validations and security gates that would execute as part of it’s regular operation.

We were a small team and I had many conversations with another developer tasked with building a payroll using the API I would provide. Some methods here, classes there, the odd helper function and I had an API and then we had a mini payroll running.

Then he showed me the code he had written and that smug grin dropped off my face. It was awful.

Perhaps this other developer wasn’t as great as I’d thought? Looking at the code though made me realize he had done the best anyone could with a terrible API. I’d exposed parts of this core payroll engine with hooks when it needed a decision. Its job was to run the payroll – a very complex task that involved storage, translation, time periods, users and companies. That complexity and context had leaked out.

Unfortunately it’s not a unique story – many API’s are terrible to use. They’re concerned with their own terminology, limitations and quirks because they are exposed sections of an underlying system developed by those responsible for the underlying system.

If you want others to have a good experience with your product you have to put yourself in their shoes. Whether it’s a UI or an API makes no difference.

You are not the user

That’s the real difference between writing the classes that form your regular implementation and those that make up your public API.

We had time to fix our payroll API. Instead of refining and polishing here and there we took the 20 or so snippets developed for the mini payroll and pruned, cleaned and polished until they looked beautiful. They scanned well and made sense to payroll developers unfamiliar with our package. When a third developer familiar with payrolls but unfamiliar with out package developed the necessary code for a fully-functional jurisdiction in record time with minimal assistance we knew we had hit our goal.

Sure implementing that new API was hard work. Instead of simple methods sticking out of the engine we had a facade over our engine but it was justified. They were two different systems for two different types of user with distinct ideas about what the system was and how it was going to be used.

Code First

Many years later I found myself on a small team of 3 people tasked with putting a brand new API on top of Entity Framework for configuring models with code the .NET world would come to know as Code First. I was determined to use my experience and avoid another complex API surface littered with terminology and leaky abstractions. Parts of EF already suffered from that problem.

So for the first few weeks of that project we didn’t write any of the code that would in fact become Code First.

Instead we decided who our user was – in this case a C# developer who likes writing code, knows LINQ and some database concepts but doesn’t know Entity Framework as people who did were already using Model First or Database First.

Then we wrote tiny sample apps and tried to find simpler and simpler ways to describe them in code. We’d often start on a whiteboard with a scenario and write the complete mapping. We’d then try and find conventions that would remove the need for most of it and then try to write succinct code to configure the rest. As the newest guy to the team I’d fight to keep EF terms away from the main API surface in order to reduce that barrier to entry and help drive adoption.

Finally we’d hit the computer and develop stub classes and methods to make samples compile and let us try the IntelliSense. This isn’t always necessary but if you want to develop a fluent API or provide lots of type-safety such as Code First’s relationship mapping it’s highly recommended.

We’d then revisit the samples later and see if they could be read as easily as they were written and figure out what problems people were likely to run into and whether we could solve them without too much noise. Sometimes this meant having more than one way to do things such as chaining the fluent methods or allowing a bunch of properties to be set (solved with an extension method class providing the fluent API) and how users could manage larger models (solved by sub-classing EntityConfiguration – now EntityTypeConfiguration sigh – and allowing redundant specification for things like relationships that span more than one class).

We finally ended up with succinct code like this with IntelliSense guiding you along the way and preventing you from even being able to specify invalid combinations. The HasMany prompts the properties on Customer and it won’t show you WithRequired unless it is valid. In the case of Required to Required it will ensure that the WithRequired specified which end is principle and dependent. In short it guides you through the process and results in highly readable code.

Entity<Customer>().HasMany(c => c.Orders).WithRequired(o => o.Customer).WillCascadeOnDelete();

This process took a little longer but given the amount of use the API will get that time will be saved by users countless times over.

Code First went down incredibly well with both the target audience and existing EF users and inspired the simpler DbContext interface that became the recommended way of accessing EF.

I think it’s one of the nicer APIs to come out of Microsoft and .NET.

[)amien

PS. Martin Fowler has some great guidance in his book Domain Specific Languages.

Anatomy of a good bug report

Working on the .NET Framework was an interesting but often difficult time, especially when dealing with vague or incomprehensible bug reports.

Look before you file

Head to Bing, Google, official support sites and bug database if you have access to it (Microsoft Connect, Apple Radar, Bugzilla for Firefox etc.) to see if others have run into this issue. Searching for the error message can yield good results but remove elements of the message specific to your project (e.g. class names, property names etc.)

The reasons for this are:

  • you may have made a mistake (likely if the software has seen considerable use)
  • behave differently to your expectations (the dreaded ‘by design’)
  • already be fixed (in the next release and possibly as a patch)
  • have an acceptable workaround (why accept a workaround?)

If you are running into problems with developer tools, also check out:

Consider how likely it is that you’ve discovered a bug given the complexity of what you are doing, how unusual it is and how mature the software is. Attempting something simple on an established piece of software likely means you’ve made a mistake or misunderstood the documentation.

A good bug report

So you decided to go ahead and report the bug (we all need better software after all).

The essence of a good bug report is having just the right amount of information to identify the bug without unnecessary detail.

Let’s break it down.

What happened

The most important element is describing what happened, and there are four major possibilities.

Error message

You told the software to do something, and it displayed an error message instead.

On a good day, the error message lets you know why it can’t do what you asked and lets you know what to do to make it work. Given you’re filing a bug report, it isn’t one of those days.

The error message is likely cryptic, doesn’t tell you how to get what you want or is just plain wrong. We’ll need that message in its entirety so:

  • Copy Windows message box contents as text by pressing control-c when it’s in focus
  • When there is a lot of text take a screen print (Print Screen on Windows, CmdShift3 on Mac OS X)
  • Localized error messages may slow down support responses – switch the app back to their language first

Exceptions

When a piece of a program (called a method or function) can’t do what it claims, it throws an ‘exception’ back up to the piece that asked (called) it. This exception is like an error message but with enough technical detail that travels back up the program until something deals with it (known as a catch).

When you see an exception, then nothing wanted to deal with it.

You see an error message that contains the exception and possibly a list of program pieces that couldn’t deal with it. This is a stack trace, invaluable to the person investigating your report, so include it.

Developers seeing exceptions in their program need to determine if they should be catching that exception or whether it shouldn’t be occurring. Feel free to trim the stack trace to remove your methods if you need to.

Unexpected behaviour

The software should have done what you wanted but did something you didn’t expect instead.

Report what you thought should happen, what the software did instead, how this is different and the reason why you think it should be that way.

Other people may not agree with your change, and in the case of shared programming libraries or frameworks, a fix for you can become a break for others that rely on existing behaviour.

Terminated

The software just vanished from the screen without a trace. Crashed, terminated or unexpectedly quit and perhaps took some of your work with it :(

If you’re really unlucky, the software that crashed is your operating system. This could mean a blue screen of death (BSOD) on Windows, the grey screen on Mac OS X.

Often there are logs left behind that you can examine to identify what went wrong.

On Mac OS X, fire up Console from Application > Utilities and see what you can find. The iPhone, iPod and iPad do this quite often, and iTunes offers to send detailed information to Apple, who may share it with the application developer if it’s not their own.

Windows users should head to the Event Viewer and find the error and any additional messages that appear to relate to it and include these.

Steps to reproduce

Ideally, this is the minimum number of steps to reproduce the error every time. You want this to be as reliable as possible as companies have limited resources and won’t spend days trying to reproduce a low-impact bug.

This repro is a critical step in understanding the scope of the problem and its impact. If you can’t reproduce it in a few steps, there’s always the possibility you’re overlooking some other aspect that could be causing the problem – unexpected data or rogue code elsewhere!

For an application, this may be a data file or manual steps a user must manually perform via the user interface.

For a framework; a small self-contained project with just enough code to reproduce the failing scenario.

Environment

Bugs are often sensitive to their environment, and you should always include the version number of the software you are using as well as pertinent platform details,  including:

  • What operating system, version & service pack
  • What processor architecture (x86, x64, IA-64)
  • What language & locale your machine is running in (e.g. US English (en-US), Brazil Portuguese (pr-BR))

In the specific case of Visual Studio and .NET bugs:

  • What version of Visual Studio you are using (including any service packs)
  • What processor architecture you are compiling for
  • What language and compiler version you are using (e.g. C# compiling for 4.0)

You may need to include details for your desktop or developer machine and details of the server it is connecting to if any are involved.

What you’ve tried

Chances are you tried several things before filing a bug report. Let us know if you tried:

  • Alternate routes through the user interface
  • Entering data in a different format or order
  • A different computer or environment

Letting them know this means they can avoid suggesting things you’ve already tried or waste time trying them too.

[)amien

How did I get started in software development?

Ken Egozi tagged me with the latest meme and this time it’s at least relevant :)

How old were you when you first started in programming?

Some time between 10 and 12 when my father bought home a ZX Spectrum and I ended up delving into the excellent programming manual when I finally ran out of games to play. At the same time my school opened up the computer room at lunchtimes…

What was your first programming language?

BASIC on the Sinclair Spectrum (evenings) and BBC Micro (lunch-times and after school). Multi-platform from the outset ;-)

What was the first real program you wrote?

Probably the MultiFile +3 disk & file management tool for the Spectrum in a mix of assembler and BASIC but I was also creating menu and copy protection for the BBC Micro around the same time.

I also trashed an expensive 3” disk drive at the time with a small bug in my end-of-disk detection code that resulted in the drive trying to step itself beyond the end several times and knocked it out of alignment.

What languages have you used since you started programming?

Well I’ve *used* the following although ones in italics for only brief periods involving one or two small applications.

  • BASICs: Sinclair, BBC, Microsoft, QBASIC, Mallard, QuickBasic, ASIC
  • Assemblers: Z80, 6502, 8051
  • Visual Basic, VBA, VBScript, VB.NET
  • C, C++, Objective-C, C#, Java, JavaScript, ActionScript
  • Turbo Pascal, Delphi, SQL, PHP
  • COBOL, RPG, SmallTalk, Algol, Prolog

I’m not sure if XSLT/XPath or RegEx’s count.

What was your first professional programming gig?

Writing IBM AS/400 (iSeries) banking applications in COBOL age 17 joining a team where the leader was already known as the Kindergarten Cop as everyone in his team was “only 23-25”. I got to delve into the kernel, general ledger and securities systems eventually single-handedly developing intricate multi-base-currency support leaving days before my 19th birthday. (Okay, a little pride there ;-)

If you knew then what you know now, would you have started programming?

Without a shadow of a doubt.

If there is one thing you learned along the way that you would tell new developers, what would it be?

Enjoy the journey, new languages are going to come and go so learn them just-in-time ;-)

It’s a shame computers and languages are more complex now but with the Internet and great books available there is no real barrier to entry.

What’s the most fun you’ve ever had programming?

Any application that brings a smile to a users face :)

Some ‘interesting’ moments have been revisiting school-level physics for a pool game and an on-the-fly domain class construction system for an international configurable payroll package.

Who am I calling out?

I’m not sure any of them are reading my blog any more but you never know ;-)

[)amien