Bug Hunt: Part 1

Debugging is one of those skills that is commonly not taught as a skill, but described as one. Schools don’t (necessarily) offer a course in debugging and it’s not taught as a unit in a curriculum. It’s sprinkled in between learning several basic skills, sometimes included as a single exercise when learning an operation syntax, where the student is given some code written incorrectly and told to find where the problem is and fix it. This isn’t a bad thing exactly. Debugging is a necessary skill but also a frame of mind that involves patience, curiosity, and an ability to accept things not working.

Debugging can involve removing errors but also doesn’t have to. Sometimes it involves restructuring the program because it doesn’t behave the way you intended it to and the way you thought it would, until you ran into a problem. It’s the practice of making your code behave the way you intended it to, and that can cover quite a number of bases.

The briefest of them are syntax and output errors. Syntax errors are easy to fix, but can be hard to spot. In hundreds, thousands of lines of code across many different files, where did you miss out the semi-colon, the backslash, the parentheses? The error doesn’t always tell you.

The easiest way to track it down is to save and test early, test often. This is where version control comes in; a lot can be said of version control but for the purposes of this discussion version control means we can work on one small part of our application at a time, and that narrows down the potential errors from thousands of lines of code to hundreds. And once you’ve narrowed the scope of what you’re working on, you can introduce some test code.

An example of test code in JavaScript

This block of test code, which I have liberally sprinkled in my Project SEEDs application in development, tests two things. It should show the phrase “Mr. Hammond, the phones are working.” on whatever component or page I have loaded, and it should log the same phrase to the console whenever a component including this function is loaded. If I see it, I know that the component loaded correctly even if the output is null or is otherwise not what I expected. If I don’t, I know the component isn’t loading.

That gives me two possibilities for where the error is located: either in the section of code that calls the component, or the component section itself is giving me the wrong output. Hopefully both of these sections of code are short enough that I can look through them and take it line by line, testing each, first noting down how it should work in comments and then if it doesn’t work as expected, noting down how it does behave. I also try to note the input given/output expected while I’m debugging, to keep it straight and to remind myself if I need to take a break.

An example of a piece of JavaScript that adds a button to a div

Recently I was adding a button to the div (podCard) that the above code writes to. I created the variable and element, gave it some inner HTML, added the click event listener and wrote out the function it called, and appended it to the div. It appeared on the div, but it didn’t perform the function when clicked. Nor, when I tested it as above, did it log anything to the console. By doing this I knew that the problem was most likely in the function call, for whatever reason, especially as when I put the whole function into the event listener it worked properly. And I could have left it like that, but the code was cleaner when abstracted out. So what was going wrong with the function call? We won’t discuss how long it took me to realize that I’d forgotten to append the parentheses that make it a function call. (About twenty minutes.)

A simple syntax error, but all told it took me a good thirty minutes to track down, including those twenty minutes it took me just to realize that I hadn’t typed the function call correctly. And yet because the whole thing worked as directed, i.e. the event listener listened and obeyed the commands when clicked and the component loaded correctly, I didn’t have an error message to point me to line 113 and say “this is not a correct function call.” Sometimes you have to narrow it down by trial and observation.

An example of a piece of JavaScript that creates a button to render a number of items

Output errors, when your code isn’t returning the result you expected and needed for it to work, often happen because of syntax errors but not always. In the example code above, I put in the event listener what I thought was the correct function call to render all the seedling pods. I clicked the Render All Pods button, and it rendered nothing. With some trial and observation as I’ve described, I realized that the renderPods function takes an argument: the fetch data. The fetch function, on the other hand, automatically calls the render function with the fetch data at the end of the chain on the fetch request. I put in the fetchPods function instead, and it worked … well, mostly properly. Again, we have an example of the code doing exactly what you told it to do, even though it might not be quite what you wanted. This time I knew why, though, and I left myself a note for another day’s work.

Trial and error, more broadly described as trial and observation, is one of the two main underpinnings of debugging code. Whether you use a debugger or endless print statements, you’ll need to repeat your operation several times to figure out where it’s going wrong and in what way, and how best to fix it. And because of this you will also need a generous helping of patience and a healthy sense of self-awareness. Sometimes the problem isn’t only with the code, it’s the fact that you’ve been working on the application for six hours straight and you need a break, a drink of water, a meal, a nap, or some combination of those.

When I began turning towards web development as a career rather than a hobby, my mother reminded me at the outset to remember to step away from the keyboard every so often. Get a snack, go outside for a walk, take a few deep breaths. Regardless of what tools or procedures you use to debug your code, it always helps to first clear the bugs out of your biological systems and approach your work with a clear and well-fueled mind.