The 10 commandments of fixing any code issue

Bogdan Protsenko
6 min readOct 16, 2021

--

You’re freshly caffeinated, in the zone. You’ve been coding for a bit and have just confidently hit the save button to re(compile/fresh) the app. You test your feature and… it’s fucked.

Fixing code issues is a little bit of an art — starting out, it’s not clear how it should be approached. You find yourself tripping up over some silly stuff — typos, wrong URL’s, rabbit holes in entirely the wrong direction. As time goes on you develop a sense for what you should be doing, a framework for dealing with your hiccups of sorts, and the process becomes a little less painful. Eventually you know exactly what to do and in what order to resolve an issue.

This article aims to provide an informal list of the questions that make up that framework. These are things that are applicable to any codebase, bug, or instance of you trying to weed out an annoying behaviour in your code. By no means comprehensive, it is a high level overview of what I’ve found myself doing every time I approach an issue over the years. Without further ado:

1. Relax

As Frank Herbert said, “Fear is the mind killer”. Studies have shown that stress significantly reduces cognitive function. Solving problems is easiest done with a cool demeanour, letting reason and intuition work in tandem to build up the full, untainted picture of what you’re dealing with. Take a deep breath and…

2. Check you’re in the right place

It’s a surprisingly strong feeling of shame realising you’re on the staging website instead of localhost after 15 minutes of frantic refreshing. This is the least effort/highest reward thing you can do. Make double checking that you are in the right place to be viewing your changes (be it browser tab, dev tool instance, or terminal window) second nature and you will save yourself a fair bit of frustration down the line.

3. Check the tests for signs of red

If what you’re working with has tests, perfect — their main purpose is to catch your foolishness and help you figure out where exactly you’ve dropped the ball. If not, seriously consider writing them as part of your task.

4. Scour the logs

It may sound obvious, but in the practical heat of the moment it may not be the first thing you do. Exceptions, errors, warnings and other logs are the first line of defence of software against code that isn’t playing nicely.

Ensure errors are being reported correctly (I’ve tripped up more times than I care to admit having filtered out errors in spammy codebases) and that there isn’t anything unexpected there. If there is — great you have a solid starting point as you inspect the error’s stack trace. If the exception is being thrown by an external lib even better, you can easily Google the issue. Otherwise, you can safely move onto the next step.

5. Carefully read your code

The collective developer hours spent debugging silly misspelings probably amounts to a length of time not far from the age of the universe. With the advent of linters, intellisense and strict typing this is not as much of an issue as it used to be. Even so, these defences are not foolproof, and you will find yourself tripping up:

function makeItemsList(items) {
return items.map((item) => items.toString()).join("\n");
}

items.toString() would not be considered invalid code by a linter and maybe even a typing system, and assuming you intended to convert item to string it would definitely net some very unexpected behaviour.

Get into the habit of reading what you’ve just written, line by line, character by character all the while referring to #6:

6. Make sure you understand what you’re working with

We’ve all dropped in code from Stack Overflow without fully understanding what it does. Chances are your app doesn’t really understand what it does either. Utilising step #5, dive deep into what it is you’re working with, understanding it preferably before you make and test changes.

  • Make sure you 100% know what each bit of syntax does — don’t leave anything down to assumption.
  • Get your head around what’s happening at the micro scale (e.g. the flow of logic in a block as each line executes) as well as the macro (e.g. what the class you’re operating on does in the context of the rest of the app)
  • Scrape through any relevant documentation, in code or outside you can find. Try your best to fill in the gaps within reasonable time.

The deeper you understand the code you are working with and the less you leave up to assumption, the higher the chance that you understand issues with your work as they come up.

Of course, if we sought to fully perceive everything that happens in our products we wouldn’t get any work done. This is why it’s important to learn how to identify individual “units” of code (functions, classes, modules etc), and draw boundaries around them, building up a mental modal of how the moving, interconnected parts of the language based machines we build fit together.

7. Make sure your environment is configured correctly

So, the tests are passing. You’ve checked the logs and haven’t found anything suspicious. You’ve read and reread your code, actually understood the stack overflow question you plagiarised and double checked that bit of syntax does what you think it does. Everything checks out, but the issue still persists.

Application code is merely a template defining some operations to execute in a given context — around it exists an interchangeable environment in the form of OS, network, compiler, browser, framework and so on. If incorrectly configured it will yield unexpected results. There are many questions you can ask, depending on what you’re working with. Some examples are:

  • Are the correct env variables in place?
  • Are the correct URL’s whitelisted?
  • Are the right ports exposed?
  • Are 3rd party dependencies installed and correctly versioned?
  • Have I got the right permissions?
  • Is my VPN experiencing outages?
  • Is my browser up to date?
  • and so on…

8. Try a reduced test case

Can you identify what the key components of the code you are trying to write are? Arranging a simple, isolated example of the functionality you are trying to implement outside of the codebase you’re working on is a great way to quickly validate your ideas about how a particular piece of code should operate.

9. Is it someone else’s fault?

3rd party code is much less often the culprit than you or someone else on your team. However it does happen, which is why if you’re here you need to be prepared to inspect some libs. If you suspect that an external lib is not doing what it should, you can:

  • Check for conflicts with other 3rd party libs, particularly across different versions
  • Crawl docs to ensure you understand what that 3rd party does in your code properly
  • Scrub through issues and forums for users reporting issues similar to yours, particularly on specific versions that match yours
  • Failing everything else, dive into the library’s code and try make sense of what it’s doing

10. Call in the cavalary

If you’re this far without a solution then it’s time for a fresh set of eyes. Unceremoniously yank a coworker with relevant domain knowledge, or spouse or even pet away from whatever it is they are doing and explain to them what you expect to happen, what is actually happening and your understanding of the problem to the best of your ability.

Rubber ducking is a very real phenomenon and you will often find that you will realise what the problem is and how to fix it as you are spelling it out to somewhere else. Or your coworker will have an idea of what’s happening and can work through the problem with you together. At the very least you will be further along in your understanding having solidified it with out loud reasoning.

11. Take a break

OK I lied, there’s 11. Technically this isn’t you debugging your code, but it certainly contributes significantly to the problem solving process.

You’ve tried everything and have not resolved your issue. You’re tired, the coffee is wearing off, and the sun is hitting your windows just right. It’s time to take a break.

The mechanisms responsible for the strange phenomenon of sitting down in the morning and making more progress in 10 minutes than in 2 hours the evening before are reusable throughout the day. The brain stashes away what it knows and continues to work on the problem as you’re wandering down the street or making idle small talk.

--

--