Log in

goodpods headphones icon

To access all our features

Open the Goodpods app
Close icon
Weekly Dev Tips - Debugging Tips

Debugging Tips

01/28/19 • 5 min

Weekly Dev Tips

Hi and welcome back to Weekly Dev Tips. I’m your host Steve Smith, aka Ardalis.

This is episode 37, in which I'll talk a bit about how I debug problems I find in my code.

If you’re enjoying these tips, please leave a comment or rating in your podcast app, tell a friend about the podcast, or follow us on twitter and retweet our episode announcements. All these things help increase the reach of this podcast, so more people can benefit from these tips.

Debugging Tip

This week's tip is by request via twitter from Bernard FitzGerald (@bernimfitz) who wrote "How about an episode devoted to effective debugging? I think that would be interesting to hear your methodology of tracking down a bug." Well, Bernard, this bug's for you. Sorry, lame beer commercial joke. On that note, here's a commercial...

Sponsor - devBetter Group Career Coaching for Developers

If you're not advancing as quickly in your career as you'd like, you may find value in joining a semi-formal career and technical coaching program like devBetter.com. I launched devBetter a few months ago and so far we have a small group of motivated developers meeting every week or two. I answer questions, review code, suggest areas in which to improve, and occasionally assign homework. Interested? Learn more at devBetter.com.

Show Notes / Transcript

Let's talk a bit about debugging. Let me start off with a couple of personal observations. First, I think debuggers are amazing. Having the ability to magically stop time in the middle of your application anywhere you want and see exactly what the state of everything is there is like a super power. It far outstrips using console output and checking a log file or terminal window for logged output like "got here" and "got here 2". Those were dark days.

And second, despite how amazing they are, I almost never use the debugger. One tip I give all the time to students in my workshops is that they learn to use ctrl-F5 instead of F5 to launch their applications because it's so much faster. In my experience, 90% or more of the time you're not actually debugging when you launch your application, and in a recent experiment I ran it took about a second to launch an ASP.NET Core app without the debugger and about 10 seconds to do so with it (running on my somewhat old laptop). Those seconds add up, especially when you remember that after a few seconds you're likely to get distracted and go look at your phone or open a browser and start checking email or twitter or something. Not using the debugger helps keep you in the zone and productive.

So why not use the debugger to, like, actually debug problems? I do sometimes. But more often I'll write tests. If it's my own application, I probably already have a bunch of tests. If there's some weird behavior going on and no existing test is catching it, I'll try to write a new one that fails because of the bug I'm looking for. Going through this exercise forces me to analyze what the program is doing, what classes are collaborating and how, and in general to have a better understanding of what's going on.

If I can't easily write a test to isolate the issue I'm having, then I'll use the debugger. I might even debug from a test, since that's often an easy way to jump right to a particular place in my code that I know is being called with known inputs. From there I'll look at the values of all the relevant variables and arguments and usually that will identify where something isn't set the way I'd thought or assumed it was.

Another approach I take is to use some kind of diagnostic tool within the app framework I'm using to provide me with as much data as possible about how the system is working. That might be using a tool like ELMAH for older ASP.NET apps, or an MVC route debugger middleware that shows me every route and how it's configured. I have some middleware for ASP.NET Core on GitHub that will format and render all of the services the application has registered. Things like this can often help provide additional context and information that can eventually help find the source of a problem.

Tests aren't the only thing that helps avoid the need for a debugger. Using custom exceptions like I described in episode 7 helps make it obvious what went wrong so you don't need to debug in order to figure out that NullReferenceException. Writing short, simple methods with low complexity, perhaps with the help of Guard Clauses that I described in episode 4 is helpful, too. I actually revisited both of these topics in the previous episode, too. When your code is kept simple and small, problems are generally easily detected. If you're writing 1000 line long methods that require multiple levels of nested regions in them to be comprehensible, I can see how you might need the debugger to sort out what the heck is going on when something doesn't...

plus icon
bookmark

Hi and welcome back to Weekly Dev Tips. I’m your host Steve Smith, aka Ardalis.

This is episode 37, in which I'll talk a bit about how I debug problems I find in my code.

If you’re enjoying these tips, please leave a comment or rating in your podcast app, tell a friend about the podcast, or follow us on twitter and retweet our episode announcements. All these things help increase the reach of this podcast, so more people can benefit from these tips.

Debugging Tip

This week's tip is by request via twitter from Bernard FitzGerald (@bernimfitz) who wrote "How about an episode devoted to effective debugging? I think that would be interesting to hear your methodology of tracking down a bug." Well, Bernard, this bug's for you. Sorry, lame beer commercial joke. On that note, here's a commercial...

Sponsor - devBetter Group Career Coaching for Developers

If you're not advancing as quickly in your career as you'd like, you may find value in joining a semi-formal career and technical coaching program like devBetter.com. I launched devBetter a few months ago and so far we have a small group of motivated developers meeting every week or two. I answer questions, review code, suggest areas in which to improve, and occasionally assign homework. Interested? Learn more at devBetter.com.

Show Notes / Transcript

Let's talk a bit about debugging. Let me start off with a couple of personal observations. First, I think debuggers are amazing. Having the ability to magically stop time in the middle of your application anywhere you want and see exactly what the state of everything is there is like a super power. It far outstrips using console output and checking a log file or terminal window for logged output like "got here" and "got here 2". Those were dark days.

And second, despite how amazing they are, I almost never use the debugger. One tip I give all the time to students in my workshops is that they learn to use ctrl-F5 instead of F5 to launch their applications because it's so much faster. In my experience, 90% or more of the time you're not actually debugging when you launch your application, and in a recent experiment I ran it took about a second to launch an ASP.NET Core app without the debugger and about 10 seconds to do so with it (running on my somewhat old laptop). Those seconds add up, especially when you remember that after a few seconds you're likely to get distracted and go look at your phone or open a browser and start checking email or twitter or something. Not using the debugger helps keep you in the zone and productive.

So why not use the debugger to, like, actually debug problems? I do sometimes. But more often I'll write tests. If it's my own application, I probably already have a bunch of tests. If there's some weird behavior going on and no existing test is catching it, I'll try to write a new one that fails because of the bug I'm looking for. Going through this exercise forces me to analyze what the program is doing, what classes are collaborating and how, and in general to have a better understanding of what's going on.

If I can't easily write a test to isolate the issue I'm having, then I'll use the debugger. I might even debug from a test, since that's often an easy way to jump right to a particular place in my code that I know is being called with known inputs. From there I'll look at the values of all the relevant variables and arguments and usually that will identify where something isn't set the way I'd thought or assumed it was.

Another approach I take is to use some kind of diagnostic tool within the app framework I'm using to provide me with as much data as possible about how the system is working. That might be using a tool like ELMAH for older ASP.NET apps, or an MVC route debugger middleware that shows me every route and how it's configured. I have some middleware for ASP.NET Core on GitHub that will format and render all of the services the application has registered. Things like this can often help provide additional context and information that can eventually help find the source of a problem.

Tests aren't the only thing that helps avoid the need for a debugger. Using custom exceptions like I described in episode 7 helps make it obvious what went wrong so you don't need to debug in order to figure out that NullReferenceException. Writing short, simple methods with low complexity, perhaps with the help of Guard Clauses that I described in episode 4 is helpful, too. I actually revisited both of these topics in the previous episode, too. When your code is kept simple and small, problems are generally easily detected. If you're writing 1000 line long methods that require multiple levels of nested regions in them to be comprehensible, I can see how you might need the debugger to sort out what the heck is going on when something doesn't...

Previous Episode

undefined - Exceptions and Guard Clauses

Exceptions and Guard Clauses

Hi and welcome back to Weekly Dev Tips. I’m your host Steve Smith, aka Ardalis.

This is episode 36, in which we'll discuss a question I recently received about guard clauses and exceptions.

If you’re enjoying these tips, please leave a comment or rating in your podcast app, tell a friend about the podcast, or follow us on twitter and retweet our episode announcements so we can increase our audience. I really appreciate it.

Exceptions and Guard Clauses

This week's tip is on the topic guard clauses and exceptions. Specifically, whether and when it's appropriate to throw an exception in response to certain kinds of inputs.

Sponsor - devBetter Group Career Coaching for Developers

If you're not advancing as quickly in your career as you'd like, you may find value in joining a semi-formal career and technical coaching program like devBetter.com. I launched devBetter a few months ago and so far we have a small group of motivated developers meeting every week or two. I answer questions, review code, suggest areas in which to improve, and occasionally assign homework. Interested? Learn more at devBetter.com.

Show Notes / Transcript

As a bit of background, I described Guard Clauses in Episode 4. If you're listening to these shows in most-recent-first order, I suggest you configure your podcast app to let you listen in order and then start back with episode 1. You'll thank me later. In any case, a guard clause is a check you make at the start of a function or method that throws an exception if some input is not valid. For instance, you could have a function that is supposed to send an email to an email address that's provided as a string argument. If the string is null, it might throw an ArgumentNullException or something similar before attempting to create and send the email. If you like the guard clause pattern, I have a nuget package you can use to easily add and extend them in a consistent fashion in your applications - look for the link in the show notes.

Listener Jeremy C. writes:

i discovered your podcast recently, and am going through it. I love the Guard class shortcut for happy path.

What i noticed, is that this behavior relies exclusively on throwing exceptions rather than what I learned (20 years ago) in school that exceptions are for the unexpected, and if you can reliably prevent throwing an exception, like checking for a null and handling it, you should to avoid the execution cost of exception handling.

Is my information just out-dated? :) Perhaps I'm too old of a coder and too many old habits are stuck.

It's true that exceptions should not be used for control flow in your applications. That means if it's a normal condition for a function to get a null as an argument, perhaps because that situation means "create a new thing" instead of "do something with this thing", then you wouldn't want to write code that depended on an exception being thrown for its behavior. For example, you wouldn't want to have a try block that tried to work with the object, and then a catch block that caught the NullReferenceException when it was null and created a new instance there.

There's plenty of reference material you can find about why this is considered a bad practice. In my opinion there are two main reasons. One is performance - exceptions are far more expensive than if statements so you shouldn't use them where an if statement is more appopriate. This is the main one, and because of it, writing code that leverages try-catch statements for something more than error handling is unexpected. Developers will be surprised to see this approach, which violates the Principle of Least Astonishment. You want readers of your code to be able to immediately understand what it's doing, and surprising them by doing things in odd ways is contrary to that goal.

Coming back to guard clauses, the idea is that you're setting up an expectation that under all normal conditions in your application you expect that these arguments will follow certain constraints. If they don't, the program's simply not going to work the way it should. In this case, an exception is the appropriate response and is more elegant than any other solution like returning a boolean value or magic number or null and the caller having to know to check for that result.

Thanks Jeremy for the great question! After I answered, he summed it up like this:

So the Guard Clause is for the situation of, "I told you the expected inputs, and while I'll protect myself from bad data, I'm not going to make a huge mess of if statements to protect myself, I'll pass the mess back to the code giving me crap."

Pretty much.

Show Resources and Links

Next Episode

undefined - How do you get so much done?

How do you get so much done?

Hi and welcome back to Weekly Dev Tips. I’m your host Steve Smith, aka Ardalis.

This is episode 38, in which I'll offer some personal productivity tips.

If you’re enjoying these tips, please leave a comment or rating in your podcast app, tell a friend about the podcast, or follow us on twitter and retweet our episode announcements. All these things help increase the reach of this podcast, so more people can benefit from these tips.

Getting stuff done

Occasionally I get asked questions like this one that came from a LinkedIn connection. He wrote, "how in the world do you accomplish so much? Would love to know the strategy." I'm flattered of course, but it's not the first time someone's claimed to be impressed by how much I get done, so I thought I'd share a bit about my approach.

Sponsor - devBetter Group Career Coaching for Developers

If you're not advancing as quickly in your career as you'd like, you may find value in joining a semi-formal career and technical coaching program like devBetter.com. I launched devBetter a few months ago and so far we have a small group of motivated developers meeting every week or two. I answer questions, review code, suggest areas in which to improve, and occasionally assign homework. Interested? Learn more at devBetter.com.

Show Notes / Transcript

So, "how do I get so much done?" Let me start out by saying that I try to be pretty modest. I don't have superpowers. I'm not Bill Gates or Elon Musk, either, with billions of dollars. I don't even have online following of Scott Hanselman or Robert Martin or dozens of others. But I do alright, and I'm willing to share how that is a bit here.

First, I made a realization years ago that every day I have 24 hours to utilize. No more and no less (except twice a year because of stupid daylight savings time). I used to say "I don't have time" for this or that. I'm sure I still say that sometimes, but at least in my head I try to remember that what I actually mean is "I choose not to make time" for it. It may be that you're in a position where you literally do not have control over your time, such as if you're in the military or in prison for example. But unless someone is directly controlling your freedom to choose how to spend your time, your use of time is a choice. Embrace that.

Next, decide where your priorities are. What do you want out of your life? What does success look like to you. If you're a gamer, you can approach life like a strategy game. What's your strategy? Are you trying to max out income? Optimize for the best possible family? Slide through with as few commitments as possible? For me I'd say I'm following the fairly common strategy of trying to maximize my family's well-being while achieving success in my career. Within that strategy I'm focusing on entpreneurship and maximizing how many others I can help, as opposed to trying to climb as high up a corporate ladder as possible. Not having a strategy just means you're letting someone else choose your moves. Figure out what your strategy is, then figure out if the moves you're making - i.e. the way you're spending your time - is in line with what you think your strategy is. Remember, "How we spend our days is how we spend our lives." (Annie Dillard). Be sure you're spending your time wisely - it's the most precious resource you have.

Ok, so that's the high level strategy side of the equation. At the tactical level, there are a few things I do that probably at least make it look like I'm being super productive. First, I minimize my commute. In the past I've had commutes of as long as an hour into work in some city where I then had the privilege of paying an obscene amount of money to park my car every day. Now, I can work from home if I choose or I have about a 10 minute country road drive to my office, which is also just a few minutes from my kids' school so it's often convenient when dropping off or picking up kids (there's no bus so driving them is one of those things my wife and I "get to" make time to do most weekdays). Not having that commute adds up. If I'm spending 10 minutes instead of 60 minutes twice a day driving, that's 100 minutes per day of bonus productivity. Think about that for a few minutes. Now, if we get self-driving cars maybe that commute time can be used productively (or if you're lucky enough to have decent public transportation). But until then I optimize for minimal time wasted on commuting.

Another thing I do is minimize time spent on TV. I watch some, but pretty much only with family members as we enjoy time together, or occasionally when working out. I'm not perfect on this front, and recently I've been spending more time than I used to on video games which can suck up at least as much time as binging Netflix, but the idea is to be mindful of how much time you're spending o...

Episode Comments

Generate a badge

Get a badge for your website that links back to this episode

Select type & size
Open dropdown icon
share badge image

<a href="https://goodpods.com/podcasts/weekly-dev-tips-155124/debugging-tips-8360116"> <img src="https://storage.googleapis.com/goodpods-images-bucket/badges/generic-badge-1.svg" alt="listen to debugging tips on goodpods" style="width: 225px" /> </a>

Copy