How not to ace the debugging interview

Ian Marshall
5 min readJun 9, 2022

For better or worse, the majority of programming is not spinning up a fresh application from scratch, but trudging through code written by others to track down unexpected behaviors, add new features, and repair any incorrect logic. Recently, I completed a two part technical interview for a support engineer position that required me to create a basic Ruby app from scratch in part one and debug a similar app in part two: while part one went well enough, I struggled to recreate the same success in part two, despite the similarities between the goals of the projects.

More often than not, the goals of technical interviews are not to wow the interviewer with your encyclopedic knowledge of every shortcut and piece of syntactic sugar you can invoke on the fly, but to face challenges where you don’t have all the answers. The way that you approach questions where you don’t have an answer is much more telling of the rhythm of how you work: do you jump around and try to reason out why things aren’t working by reading the code line-by-line? Or do you work through the problem methodically, testing the behavior of individual blocks of code? Everyone should strive for the second scenario, but having recently (briefly) forgotten my best practices, I wanted to share some tips for how to put your best foot forward for the debugging interview.

Start small and move to bigger problems

It’s tempting to look at the big picture when working on a coding problem — why isn’t the output exactly the way it should be? You can always start here, but eventually you will need to drill down to the ancillary functions to check that they’re working the way you expect. For example, in my interview I was debugging a simple piece of software that dealt with stock trades. If the overall goal of a piece of software is to take a series of inputs (like initializing stocks, changing the value of stocks, trading stocks, and so on) and output a summary of everything that’s happened (total spend, total earnings, return on investment, etc), you should always start with how the smallest pieces of information are being interpreted. If there is a single function for calculating a percent change, for example, start there by including a statement to print out the results to make sure that the building blocks of your application are behaving as expected. Once you’re confident all of the small pieces are working well, you can move onto bigger functions that call on each of those smaller functions.

Use your own inputs

While a block of code can run many different functions, you can always simplify the problem by changing your inputs. Try simplifying the inputs to test a specific function — like instantiating a user — rather than running every single part of the application to test just one component. If the values that are being inputted are creating the desired output, try it with a slightly different value to make sure that you don’t have any blind spots in your thinking.

Punch the biggest bully in the yard

One of my biggest mistakes in my recent debugging interview was to focus on simple functions that I was familiar with (like the value of stocks going up by some percent) rather than jumping into totally new challenges. I was intimidated by a new question and thought that I could get more points by solving a handful of (seemingly) easier questions in the same amount of time. While this is a good strategy for a multiple choice test, you might actually earn more points (and understand the problems with the code you are debugging faster) if you jump in the deep end. For me, this was figuring out how an unfamiliar feature, splitting a stock by increasing the number of shares outstanding and lowering the individual value of each share, was supposed to work. By the time I started working on this specific question I realized that I was running out of time, so I felt rushed and anxious. Once I started digging in, I realized that the issues with the code block were more obvious than I had anticipated, and I was able to add some bonus logic that fulfilled all of the desired outcomes of the function. If I had started with this problem first, it would have become a known and trusted component of a larger program rather than a black box to avoid until the last second.

Google early and often

You are almost always allowed to google things you’re unfamiliar with. Searching for answers is an essential part of being an engineer, and while certain things are more embarrassing to google than others, if you don’t know the answer to something you should definitely not hesitate to find it out! Some of the things i googled during this recent interview include:

  • what does “/=” mean in ruby
  • how does splitting a stock work
  • how does ruby hash use each
  • ruby [0..-2]

Some of these searches might be evidence of temporary amnesia — I know (I really do!) that in Ruby you need to include parentheses when you iterate with each() — but in the moment, you might not remember every single thing you’ve ever learned. Getting the answers to the exact problems you’re working on is more valuable than guessing different syntax in front of your audience to try and get the result you need.

Think out loud (really)

Almost always, this is an explicit instruction for technical interviews: talk through your reasoning and what you’re trying to do so your interviewer can learn more about how you approach a problem. Even though it’s a direct request from your interviewer, you might forget from time to time to explain exactly why you’re doing something in a certain way. If it helps, think of this as rubber duck debugging — by explaining things as if you were talking to yourself (or an inanimate object), you might even hear yourself explaining the solution.

Remember: you do this all the time

I was tempted to include this piece of advice first, but it’s too good of a final takeaway: if you made it this far, you might know what you’re doing. You de-bug your own code all the time, and have your own strategies in place to work efficiently. Just because you’re working on a shared IDE under the watchful eyes of two senior engineers following your every move doesn’t mean you should do anything differently than what you normally do. You might even ask them “what’s the best way for me to check this individual function?” in case it isn’t obvious. Sometimes there’s a “run code” button that you can miss, or if there’s a special CLI command you aren’t familiar with, it will always be better to ask those questions at the beginning before you spend too much time just guessing what the outputs might be. For me, the biggest hurdle was remembering that I could just as easily throw a puts <variable> into a code block to check the value of individual variables — something I do all the time, but forgot to do because of the unfamiliar setting.

--

--