Rubber duck debugging is one of those things that sounds completely ridiculous and is actually really helpful. To summarize the wikipedia page quickly, rubber duck debugging is when you figure out what’s wrong with your code by explaining it very carefully to an inanimate object.

You’re probably wondering why you would bother explaining your code to an object like a rubber duck or a teddy bear if you work as part of a team and you could just ask one of the other devs for help. Sometimes you should go directly to another developer. If there’s a serious bug in production that affects a lot of users, worrying about interrupting someone would be silly, it’s much more important to get production working again than to let Hypothetical Amy finish off her refactoring task before you bother her.

In other situations, it’s more important to give it a try yourself before interrupting anyone. The reason interruptions are such a big deal is that context switching is expensive and it’s even worse when switching to a programming task because of the number of details programmers have to “reload” into their working memory before they can get back into their work. Numbers on exactly how long it takes to get back up to speed after you’ve been interrupted vary, this Fast Company article says it takes a little over 23 minutes to get back on task but this New York Times article says it’s more like 25 minutes. If you ask someone to help you for just five minutes, it’s really not just five minutes, it’s also the time it takes for them to get back into what they were doing. That’s why programmers tend to get so cranky when you interrupt them :)

One way you can try to solve your own problem without interrupting anyone is rubber duck debugging. Having to explain all of the context around your problem, like what you’re trying to accomplish, what your code is supposed to do to get to that end result, what seems to be going wrong, where you think the problem is, what you’ve already tried, etc is one of the most useful parts of asking another person for help, and often the only part you need to solve your problem. Something about the process of explaining a problem to someone else helps you see parts that you missed before, whether it’s a log file you didn’t check or a logic error you didn’t catch. That explaining process doesn’t actually require a person to explain things to, it can work just as well if you explain it to the rubber duck, or the teddy bear, or a voice recording app on your phone or whatever works for you.

Personally, I like to write an email to the person I would ask for help if I really couldn’t figure it out myself. Putting a name at the top seems to help me get into the mindset of thinking about what that person would ask me about the problem and what they would likely suggest I try next. Most of the time I figure it out before I finish the email, but when I don’t, hey, I already have a nice tidy explanation of the problem that I can send to the person I would’ve asked for help anyway :)

If you’re stuck and don’t have anyone around to ask or just want to try everything you can before you ask for help, give rubber duck debugging a try. The worst case scenario is you end up with a good description of your problem that you could send to a friend of post in a forum.

You know what’s incredibly helpful? RequestBin! Why is it so great? Because testing webhooks sucks and RequestBin makes it easy. Logging your output is a good start but that can’t tell you which IP your request is actually coming from. RequestBin can, which is awesome when you’re trying to figure out whether the Elastic IP you set up in AWS is working correctly. It also shows you all of your output (in a nice human-readable format, no less), which is handy if you really want to know exactly what your client receives.

It’s also free! On the downside your destination url only lasts for 48 hours and your data may be wiped out at any time (if you need a permanent solution look at Runscope’s Request Captures – seems only fair to plug the paid version when I’m talking about how helpful the free one is), but the price is right :)

It’s amazing how helpful just turning up your log level can be when you’re working on a weird bug. If something you can’t immediately explain is happening, try turning up your log level. In java, where I have the most experience, it’s unusual to run your production logging at a level above warn or debug. Normally you wouldn’t want extremely verbose logs, which are what you get when you turn up the log level, but sometimes you really need that extra information.

I wouldn’t normally think of turning up the log level, but we happened to have some trace level logging in our code and when I ran into a weird bug. I thought it would be easier to turn up the logging than to change all the .traces to .debugs, and it turned out the debug level exception gave me much less information than the trace level exception which had been swallowed because we were logging at the debug level. The trace level exception pointed me at the real bug, which turned out to be an obscure issue to do with my particular version of java having a weird interaction with a couple of libraries we’re using. Just because there’s no good reason for it to break doesn’t mean it won’t break :)

The moral of the story is that your log doesn’t necessarily tell you everything and you should turn up your log level until you get answers.

There’s no way I can possibly say everything about debugging in just one blog post, but I can certainly share a few useful tips.

First, let’s talk about what debugging fundamentally is. It’s the art of seeing what actually is, not what you meant or what you thought. It’s going to be uncomfortable, and if you get too tied up in your own ego you won’t be able to do it at all. Years ago one of my teachers at Camosun told us (I’m paraphrasing heavily here because I don’t remember the exact words) that there’s no point insisting you didn’t change anything. If it used to work and now it doesn’t, you obviously changed something. Just accept that you broke it and start trying to fix the problem.

One of the first things you need to do when you’re debugging is to make sure you can reproduce the problem reliably. If you can’t do that, then you don’t really know what the problem is (or you’ve got some sort of unholy race condition bug and you’re beyond my help :) ). If you’re not the one who found the bug, ask the person who did if they can show you, or ask for more information if it came through a helpdesk and you don’t have direct access to the user who found the bug.

Once you can reproduce the problem, you’ll be able to track down what’s going wrong and figure out whether a fix actually… fixes the problem. The first step I recommend after reproducing the issue is double checking all of your inputs, even the most stupid simple stuff you’re sure you couldn’t possibly have gotten wrong. Last week I thought I had broken staging when I actually just hadn’t chosen the right value in a dropdown box. Garbage in, garbage out, as they say.

After that, you’re going to be very tempted to just read through your code and hope you can spot the problem. Resist this temptation! I’m always pretty sure I know where the problem is or that it’ll jump out at me right away, but it almost never does unless it’s an extremely simple bug. Read over the code once if you really want to, but then move on to narrowing down exactly where the bug is. Believe me, it’s faster than staring blankly at your code and feeling dumb.

If you have a particularly chatty log, you may be able to start narrowing things down while you reproduce the issue. Start looking after the last log message you see before the bug happens. If you’re very lucky something will be obviously wrong close to the log line you were looking for.

If you’re not quite as lucky, you’re going to need to run the code locally and start commenting things out. Assuming you have some idea where the problem is happening, start dividing the method it could be in, in half. Either comment half of it out or add a log line half way through and see if you see that log line before or after you reproduce the problem. Keep narrowing it down until you know exactly where the problem is. Once you know exactly where the problem is, you should now know what’s going wrong if not exactly why. It’s not unusual to have to trace back through your code to find the place that set up the issue that wasn’t triggered until later. Bad config, for example, may not cause an actual bug until long after it’s saved.

The most important things you can remember when you’re debugging are to be systematic and to not make assumptions. Don’t assume that your input is good. Don’t assume that a certain piece of code can’t be the problem because it hasn’t been changed in ages/just passed testing/doesn’t seem to be related. Don’t assume that your config is what you think it is. Don’t assume that you know what’s going on – if you did, you wouldn’t have written a bug in the first place :)