Want to get more articles like this one? Join my newsletter

In Opinion

How debugging can make you a better developer

Whether you’re a WordPress developer or not, you’re always looking for ways to improve yourself. That’s the nature of our profession. We’re always looking for ways to improve ourselves.

That said, it’s not uncommon for developers to hate debugging. They’ll get a bug report and cry in exasperation, “I want to build stuff! Not fix bugs!” But that’s not the right attitude to have towards bugs and debugging in general.

That’s because debugging doesn’t only happen when you’re fixing bugs in bug reports. We spend a lot of time debugging when writing brand new code too. How often have you written code that didn’t work on the first try and that you had to debug? (We’ve all had that happen more often than we want to admit!)

That’s why debugging is such an important skill to have as a developer. We spend a ridiculous amount of time debugging. Yet we never think about how getting better at it might also help us write better code.

The nature of bugs

To better understand why debugging is such a useful skill, we need to look at bugs themselves. What are bugs? And how do they tie to software development?

But first, we’re going to start by looking at the term “bug” itself. Why do that? Because the way we use the term “bug” is interesting in of itself.

When we think of a bug, we more often than not think of something that appeared by itself. That we were somehow not responsible for it. Yet we know deep down that this isn’t true.

The reality is that all bugs are man-made because all software is man-made. (We haven’t reached the singularity quite yet!) So, as much as we don’t want to admit it, we’re the cause the bugs in our software.

So, if we follow this train of thought, we could say that bugs are mistakes that we’ve made. And, if bugs are mistakes that we’ve made, it’s fair to say that we can learn from those mistakes as well. This is a good reason to view bugs and debugging as a learning opportunity.

Example: syntax errors

To view what we mean by this, let’s look at syntax errors. Syntax errors are common early in a developer’s career or whenever they switch programming languages. For example, how many of us spent way too long looking for a missing semi-colon in our PHP code early on? (raises his hand furiously)

Syntax errors are super common when we’re not familiar with a programming language. They don’t tend to make it to production, but we still have to debug them. And, in the process, we familiarize ourselves with the programming language that we’re learning to use.

Fixing bugs is how we learn

In fact, it’s really hard (if not impossible) to learn anything in programming without debugging. You’re not learning anything (except maybe some google-fu) when you’re copying and pasting code from Stack Overflow. But you are learning something when that code doesn’t work and you have to debug it.

That’s why debugging is more often than not a learning exercise. That means that, if you get better at debugging, you’ll get better at learning. The opposite is true as well. The better you get at learning things, the easier it’ll be to fix bugs in your code.

This symbiotic relationship is also the key to improving our debugging skills. If we want to get better at debugging, we have to get better at learning new things. The better we get at one, the better we’ll get at the other.

How do we get better at learning things?

Isn’t that the question we’d all love an answer to!? Of course, we all want to get better at learning things. One of the keys to getting better at learning is to use effective learning strategies.

This is something that’s also important when you want to use teaching as a learning tool. Like with teaching, your goal when using effective learning strategies is to make sure you learn something properly. In one situation, you need to learn it well so you can teach it back. On the other, you need to learn something well so that you can find the problem with your code.

In both cases, you need to go beyond copying and pasting code without understanding it. You need to look at your code and know what it’s doing to an extent. Of course, if you knew exactly what your code was doing, you wouldn’t be trying to fix a bug in the first place!

Some experience required

This brings us to an important side point. Yes, there are steps that we can do to get better at learning and debugging. But some of it is just experience that you have to acquire yourself.

The reason to bring this up is that you have to keep this in mind when you’re debugging. If a bug is in a system or uses code that you’re not familiar with, you won’t have any previous experience to leverage. You’re going to have more to learn.

We’ve all had those bugs that took forever to fix because you had no idea what was going on. But you probably also remember how you thought, “I’m never going to be able to fix this. It’s hopeless.” And then you did.

These are some of the most frustrating and time-consuming debugging experiences. But these experiences also tend to sear the knowledge in our brain. The experience was so painful that we want to make sure it doesn’t happen to us again.

This isn’t scalable

The problem is that these situations don’t scale that well. First, they aren’t always that fun for you. (This is even if you have a growth mindset.) Nor are they an efficient use of your time.

But it’s not like you can prevent these situations from happening either. So it comes down to making sure that you get the most out of them when they happen. That’s where the effective learning strategies come into play.

They’ll help you cut down on how long it takes you to debug something. And they’ll also make sure that you learn as much as possible from the experience. They might even help you cut down the time it takes you to learn something.

Enhancing your learning experience

So what are things that you can do to improve how you learn something? We won’t look at effective learning strategies since everyone has their own way to learn. That said, there are things that you can do regardless of the learning strategy that you use.

Try things first

Let’s say that you have a new bug in front of you. Your first reaction shouldn’t be to open your browser and Google it. Instead, you should always try to solve it yourself first.

The idea is to leverage something called active recall to help you memorize information. Even if you’ve never heard of active recall, there’s still a good chance that you’re familiar with it. It’s the voluntary act of trying to retrieve information from memory. And that’s even though you’re not sure of the answer. (If you ever used flash cards to study in school, that is a way to learn using active recall.)

This contrasts with passive review. That’s when you try to learn something by just rereading your notes or watching a video. This gives you the illusion that you know something well because you can see it at a glance.

Use Google as a last resort

It’s the same thing when trying to learn something while debugging. If you just google the solution to your bug, you might solve it faster now. You might also feel like you learned something in the process as well.

But there’s a good chance that this feeling of having learned something is all illusory. It’s more likely that the only thing that you’ll remember is how you found the solution. In this case, that’s probably the keywords that you used to do your search.

Now, it’s important to not take this to the extreme either. Your takeaway for this section shouldn’t be that “Searching is bad. Don’t do it.” That’s not the point at all.

It’s more that you should always try to solve a bug yourself first. That way you can practice remembering the things that you’ve learned. If that fails, then you can search for a solution online.

Balance persistence with taking breaks

As we alluded to earlier, we’ve all been through a debugging situation where things felt hopeless. But we persevered and managed to solve the problem eventually! And that’s always a great feeling to have at the end.

That’s why it’s important to stick it out even when things get hard. We tend to underestimate how long things will take. So being able to persevere through it all becomes critical to your success.

But we also have tendency to overcommit to a problem when things aren’t working. We think that, if we keep hammering at it, we’ll end up getting it. But that’s more often than not a recipe for wasting time and resources.

You shouldn’t be scared to step away from a bug if you’re spinning your wheels. Taking a break and working on something else is a good way to overcome obstacles. We’ve all had it work for us before, but it doesn’t change the fact that it feels counterintuitive to us too!

Again, this is something that applies regardless of your preferred learning strategy. The goal of taking a break it is to give yourself some space to think and let things settle in your mind. This is just something that you can’t always rush. (As much as we’d like to!)

What about tools?

We’ve talked a lot about learning and how that can help us debug better and becomes a better developer. But aren’t tools important for that too? Aren’t they how you get better debugging?

There’s no question that tools are important. That said, it’s another thing where human psychology comes into play. It’s easier to just start using a tool than it is to learn something new. (Although using a new tool has its own learning curve, there’s an immediate payoff.)

But this gives you a false sense of security. Like we’ve said, bugs are the result of mistakes that we make as developers. These mistakes are more often than not the result of our lack of knowledge. This is something that tools are ill-equipped to help us with. (We’re not in the Matrix so knowledge is sadly not a quick download away!)

Thus, the best tools are the ones that help you acquire knowledge. Or those that can catch common mistakes that we make and that aren’t domain specific. There are a few tools that fit into those categories.

IDEs

Let’s start with IDEs. IDEs are a bit of a touchy subject. Not every developer wants to use one. (And that’s fine!) That said, IDEs are really good at helping you catch these common mistakes that we talked about.

For example, they can highlight syntax errors so that they’re easier for you to spot. This is great because, while you’re writing code, you’re using active recall. And having your IDE show your mistakes right away like that gives you immediate feedback.

Having immediate feedback like that creates a positive feedback loop. This, in turn, helps you learn a language’s syntax faster. (That’s why an IDE is an important tool when learning about regular expressions.)

Debugging tools

Talking about IDEs is a good way to bring up the next set of tools that we’ll look at. Those are debugging tools. (Pretty obvious set of tools considering the title of this article!) Debugging tools also go under the name debugger.

But, in PHP, you don’t often hear either term. Instead, there’s a better chance that you’ve heard of xdebug. That’s because xdebug is the most commonly used PHP debugging tool. Because of that, xdebug tends to be synonymous with debugging for PHP developers.

Inspecting your code

What makes debugging tools so powerful as debugging and learning tools is breakpoints. Breakpoints let you pause the execution of a program or, in this case, a PHP script. This lets you inspect the state of the execution of the PHP script at that specific moment.

What’s powerful about this inspection capability is that you can look at the content of your variables. (Both function/method variables and global variables.) This allows you to create a similar feedback loop to the one with testing. You can make an assumption and then verify it right away.

Stepping through your code

On top of that, debuggers also allow you to step through your code one line at a time. This allows you to test assumptions about the control flow of your code. That’s the computer science term for the order that a programming language will run each line of your code.

Assumptions around the control flow of your code often centre around conditionals and loops. For example, you wrote an if condition which you expected to be true, but wasn’t. Or you wrote a loop that you thought would run three times but instead, ran forever. (Oops!)

Being able to step through your code and test these control flow assumptions is very useful. That said, you don’t have to use it only to test control flow assumptions about your code. You can also use it to make assumptions about the control flow of an application or framework.

This is an underappreciated benefit of using a debugger to step through code. You can use it to learn about the application or framework that you’re using. This can often be more effective than just reading their documentation. (That’s because reading documentation is more like passive review.)

What you do instead is you make a control flow assumption about the application or framework and then you test it. This will result in you having a much better understanding of the application or framework. (That’s how I learned the ins and outs of WordPress when I started off.) That’s because you’re learning how it actually works not just reading about it in the documentation.

So let’s take WordPress as an example. You can test whether the plugin API will call a specific hook or not. And what the context of that call to that hook was. (What function was the hook called in? What was the function doing at the time?)

Web developer tools

Can you imagine being a web developer without Web Developer Tools!? It’s hard to go one day without having to use them in some way or another. That’s because it’s pretty much one of the only tools at your disposal for debugging issues in your browser.

But this is also another tool where you can use active recall and get immediate feedback on your guesses. We’ve all used web developer tools to edit HTML, CSS and/or JavaScript to make a change and observe what happened. We repeat the process until we’ve fixed the issue.

It’s a powerful way to work and learn about how browsers process HTML, CSS and JavaScript. You can even use them to learn about performance issues. That’s why they’re both a powerful set of debugging tools, but also learning tools as well.

Writing tests

This last one is a bit of a weird one. Writing tests isn’t a tool per say. But it does depend on using a testing tool so that’s why we’re seeing it here.

Now, we’re not going to talk about the different levels of testing. Whichever you pick doesn’t matter in the context here. It’s the act of writing tests that’s important.

Now, it’s pretty obvious why tests are good for debugging. They catch any mistake that you might have made before they even make it to bug status. What isn’t as clear is why writing those tests are good for learning.

How does writing tests help you learn?

Well, like every tool that we’ve talked about so far, it’s all about a feedback loop. When we write code, we’re making guesses about its behaviour. (And that’s regardless that we want to or not.) We’re assuming that our code will behave a certain way when we pass it specific parameters.

And, if you’re a pretty good programmer, your guesses are going to be right most of the time! But most of the time isn’t all the time. And that’s how mistakes happen.

That’s why writing tests can be a good learning tool. If you’re not sure about some of the code that you’re writing, just write a test for it. Use that test to verify whether the assumption that you made was right or not.

If you had it right, you’ve reinforced what you’ve learned. And, if you didn’t, you took in a valuable lesson which will help you remember next time. And, in the process, you made your code stronger in the long run as a result. (It’s a win-win!)

Looking at debugging in a new light

No one (or almost no one!) starts off programming with a love for debugging. Instead, it’s often a source of frustration and dread. “How many hours am I going to waste fixing this bug?”, a lot of us wonder. We’d rather go back to building cool stuff. (Because who doesn’t like building cool stuff!?)

Yet it’s hard to find a developer that we admire that doesn’t consider debugging important. That’s because they know that it’s an invaluable source of growth for them. There are few situations that will test your abilities as a developer to the extent that debugging will.

That’s why you should start approaching debugging as a learning opportunity. Sure, sometimes you’ll realize that you made a silly mistake that you shouldn’t have made in the first place. But that’s as much a part of becoming a better developer as learning some cool new language feature.

Photo Credit: Louis Blythe

Creative Commons License