This post was originally published on my blog The Great Code Adventure
Talking words into someone else's face is hard. Especially when those words are meant to describe a frustrating bug. Developers at any level, but especially juniors, often struggle to communicate clearly about their code to team members, making it hard to solve problems together. Strengthen your debugging communication skills with this handy guide!
Clear and precise communication about frustrating bugs can be incredibly difficult no matter how much engineering experience you have under your belt. As engineers, we're basically a bunch of weirdos! We don't always like talking to people and we get sucked into the problems we're trying to solve. These personality traits and habits can make it hard to collaborate effectively with our team members. This hurts our productivity as a team, our code quality as a team and our own personal growth as engineers.
It's especially tough to acquire and improve on these communication skills as a junior dev. When you feel pressured to contribute or embarrassed to admit that you don't know something, you'll choose to stay silent or to ask for help begrudgingly.
If you choose the later, you're likely to avoid providing all the necessary details and context when reaching out for help. This will only frustrate your team members.
Try to remember that no one expects you to know all the things!
As a junior dev or a new team member, you're going to get frustrated about everything that you don't know. You're going to get trapped in a paper bag. Your teammates don't expect you to describe what you don't know, or to know what is outside the paper bag. Start by describing what you do know, by explaining what's inside the paper bag, it's shape and contours. Once you've provided your team member with the tools they need to help, you'll find your way out of there together.
The guide in this article lays out what to say about our buggy code. But before we dive into what to say, let's take a moment to talk about how we say it.
When you talk about bugs we're struggling with or obstacles you're facing, always be specific and precise. In other words, DON'T say:
"It doesn't work when you do it like that."
"When a user who is an admin clicks 'save', the form does save BUT the whole page reloads, instead of just updating the appropriate portion of the page."
The difference between these two statements is vast. Don't give your listener the benefit of the doubt. Even if they are familiar with the feature you're working on or the bug your struggling with, always provide lots of details and context.
Read on to learn how to provide that detail!
When you're working on a feature, or debugging a production issue, and you've reached the limit of your understanding and your patience, it's time to reach out. You're ready to pull over someone else on your team for help. But how can you explain the problem to them, give them all of the context you've built up for yourself and actually provide them with the tools they need to help? Try the following:
- Understand and communicate the current behavior. Describe the bug that is occurring.
- Understand and communicate the behavior circumstances, i.e. the circumstances under which the bug is occurring.
- Understand and communicate how the current behavior differs from the expected behavior.
- Understand and communicate how the current behavior differs from the desired behavior
In order to follow this guide, we need to have a clear understanding of some of the underlying concepts. Let's take a closer look at some of the terms used above.
This refers to the bug that you are experiencing and struggling with. Be specific when you describe what is currently happening in your feature. Use lots of details and then distinguish it from the expected behavior and the desired behavior in order to show what is wrong.
In the example above, we would describe the current behavior as:
When the form is saved, the record is saved and the whole page refreshes.
The conditions under which the current (buggy) behavior is occurring. In our example, our behavior circumstances are:
When a user who is an admin hits "save"
What we want to happen. In our example:
The page should not do a full refresh. The page should only update the appropriate portion to reflect the saved changes.
This can be different from desired behavior! For example, desired behavior represents the goal of your work on the feature. Think of this as the behavior, design or UX spec laid out for you when you picked up this unit of work.
We can experience bugs or roadblocks at any point in time as we dev on a feature. When we bring in a team member to help us debug, we need to explain to them what we expect to happen under the given circumstances, in light of the current state of the feature.
For example, the "bug" described in our example above isn't a bug if you haven't even built the code to prevent a full page refresh! It's only a bug if you have written that code and it's still not working. We'll gain a better understanding of the difference between desired and expected behavior in the following section.
Let's walk through a specific example of a bug in a new feature and apply our fancy new guidelines.
Let's say you work at some kind of music distribution company and you've been tasked with building a feature onto the new album creation page. Here are your feature specs, i.e. you desired behavior:
A user should be able to upload a song. While the song is uploading, they should see a progress bar. When the upload is done and is SUCCESSFUL, they should see an audio player and the file name of the uploaded song. When the upload is done and is UNSUCCESSFUL, the user should see an error message and a retry button.
We've been hacking away at this exciting new feature and we almost have it working. But we've been stuck on this frustrating bug for a few hours now and we're ready to ask a team member for help. So, we call over our team mate for some debugging help.
"Hey Rick! I'm super stuck on this tough bug in the feature I'm working on. Do you have a few minutes to help me figure it out?"
"Sure thing Jerry! I'm always happy to help out a pal!"
We walk our team mate through the current behavior, i.e. the bug:
When a song is uploading, the progress bar appears, but when the song finishes uploading the progress bar doesn't go away! It stays FOREVER (or until we refresh the page). OMG.
We explain the behavior circumstances:
This behavior occurs when the song DOES NOT upload successfully. When the song DOES upload successfully, the progress bar correctly goes away and is replaced with the audio player + file name.
We explain how this differs from the desired behavior:
The goal is that, for the case in which the upload is NOT SUCCESSFUL, the upload progress bar should be replaced with an error message and retry button.
Then, we explain why our current behavior is a problem, i.e. how it differs from the expected behavior:
I haven't implemented the error message + retry button yet, but I DO expect the progress bar to go away when the upload finishes, even under the condition in which the upload is NOT successful.
And that's it! We provided all of the context that our fellow dev needs to help us debug this frustrating issue. They know how it is supposed to behave, the manner in which it differs from that behavior and the conditions under which this difference in behavior occurs. They are ready to jump in and debug with you!
What do you win when you practice clear and precise communication? Let's revisit our sad path example. When we were frustrated with our bug, we told our teammate:
It doesn't work when you do it like that.
Our helpful teammate then is forced to ask a lot of questions: "What is 'it'?", "What do you mean by 'that'?", "Exactly what conditions lead to it behaving in that manner?", "Well, how is is even supposed to behave?"
This is frustrating and time consuming for both parties. It leaves the teammate who is there to help feeling like they are missing something, and it leads to you being bombarded with questions. In this situation, we have two developers who aren't on the same page or aware of the same goal. The work moves slowly and your relationship with your teammate suffers.
When you follow the guide, on the other hand, our interaction proceeds very differently. We use precise language and we provide the context and details up-front. Our teammate doesn't have to dig for answers or make dangerous assumptions. Both team members are striving towards the same goal––the desired behavior––and understand the same bug––the current behavior and conditions. Your work moves quickly and you eliminate interpersonal tension while you pair.
On top of that, you become an ideal team member. The kind of teammate who does the hard work of uncovering and describing the parameters of a problem––surfacing issues before they become disasters and making it easy for everyone to solve problems together.
Best of all, as a junior dev, you learn faster. You're no longer hesitant to ask questions or reveal what you don't know, because you've learned how to do so in a productive manner that moves the work forward for everyone.