This post is a part of CodeSee's Emerging Developer Track. Learn more and find out how you can participate here.
We've all been there. Coding away, solving a problem when all of a sudden we hit a blocking point. The thing we're trying to do doesn't work, or the problem seems completely out of reach. Heck, sometimes we might not even know how to begin solving the problem!
This might sound familiar, recent, even! After 10 years of working as a software builder, I still find myself getting stuck. I'll run into a bug that I can't reproduce reliably, I'll come up against an API that I can't seem to communicate with, trying to update a dependency will break others, or my CI builds just keep failing.
Let's take a look at a few tips to help you get unstuck!
If you'd like to jump ahead to a specific section, feel free!
- Take a break, step away from the code!
- Reframing the problem
- Looking things up effectively
- Leveraging debugging
- Reaching out for help
- Let's be clear, it's ok to get stuck
This tip has helped me many times in the past, so much so that I gave a talk on this very topic!
When I get stuck in a particularly sticky problem, I tend to get bogged down by it and try and hammer away at it, attempting to push through the frustration and/or exhaustion. It ends up in time not well used, or worse, my solutions might miss the mark.
So as the title implies, it helps to just, leave it for the time being! Depending on the time and looming deadline, this can vary in efficacy, but I find that if I go for a walk, or stop for the day, I can let my mind either work on the problem in the background or even coming back can bring in a fresher perspective that really jumpstarts a better solution!
Oftentimes when stuck on something, it might help to consider looking at the problem differently! Having a different perspective might even make us ask the question of whether the problem we're trying to solve is the right one. As written by Thomas Wedell-Wedellsborg:
Most people are fairly good at solving problems – but they are bad at diagnosing the right problems to solve.
This approach to problem-solving is similar to that applied by Divide and Conquer Algorithms, where, as the name implies, we reframe the problem as a set of smaller problems, whose solutions are smaller by extension. What we can then do is approach each of these in isolation. This frees up our mind space to laser focus on those smaller problems and lets the larger solution build up!
One example of a tool to divide and conquer is
git-bisect. Yep, built into your git tools!
git bisect is a command built into
git with the purpose of helping us find out at which point we introduced a change to our codebase that we didn't want to add. By splitting all of the git history and checking whether the problem persists in each split, we drill down quickly to find out the commit that introduced it! This is also known as a Binary Search:
No matter the skill level, it's super-valuable to look things up! Be it via online search engines or documentation.
There are brilliant technical guides out there for how to look stuff up on Google or DuckDuckGo, such as using quotation marks for terms that have to be included, or gradually making search phrases longer. Beyond that, some tips I've picked up over the years:
- Look up that error message as-is: Loads of folks have likely run into the same problems. Even if they don't match 1:1, you'll likely unlock something!
- Plug in that Stack Overflow solution: I recently learned that Stack Overflow's license allows reuse under Creative Commons Attribution-ShareALike, meaning you can reuse the code providing you add attribution. That said, in order to improve your understanding of a solution, it's encouraged to try and refactor that code, putting it into the best way that works with the style of your codebase. You'll often find that's required anyway!
- Look up that aspect of a library in their Github repository: When something hasn't quite clicked in a library I'm using, it helps me to go into their repo online and see either what issues have been brought up on the topic, or even start trying to diagnose the issue in the library and potentially make a contribution!
Although we have tools to help us debug, this doesn't make all those tools debuggers.
One of my most-used tools is a print statement. It goes by many names in different programming languages, be it
System.out.println(). I've even gone and used
alert in React Native projects!
And this is totally fine. If it helps you drill down to what's causing the problem, why not?
Various platforms will have debuggers on them too, like the web! Most browsers will have their own debuggers built-in, such as Firefox's Developer Tools or those from Google Chrome, both of which are extensively documented. But this isn't just limited to the web, we've also got specific debugging tools, like LLDB for all your macOS/iOS debugging needs, pry for Ruby, and so on!
Indeed, even editors like VSCode have their own debugging tools built-in for several languages!
Also hey, we're actually working on tools to help you with this! If you're keen on checking out our tools for understanding complex codebases in a streamlined fashion, consider signing up for our beta!
The most important part of debugging for me is to leave no stone unturned and try every theory I might have. You never know which piece of the puzzle is faulty!
Sometimes, with our heads buried in a problem, our perspective can get clouded. Having someone else step in with either more experience in the area or with their fresh perspective can be so handy in unlocking the answer!
This is one of the trickiest parts. Spending too little time on trying to solve a problem blocks us from practicing and/or learning problem solving, but taking too long or never asking for help can hold a timeline or team back (I'm definitely in the latter camp myself, (maybe even to this day a little (working on it!))).
One piece of advice I was given early was to be consistent in how long I wait. Of course, this can vary by team, project, and other factors, but my rule of thumb is to give something half an hour before reaching out.
Asking for help involves bringing an outside person into the context you're in. Doing so effectively is critical to maximize the help you're about to get.
This involves things like:
Asking pointed, narrow questions: If you come to someone and open with "this doesn't work, could you please take a look?" is very different from saying "I'm having some trouble logging in since updating to the latest
devisegem, could you please take a look?"
- Sharing what I've tried: To save time, it helps if I share with the person who's helping me what I've already tried, to not spend time on those.
- Reproducing the problem: It's also good to have a set of steps handy so that if this is an asynchronous or remote request for help, that the other person can try it out and confirm that there's indeed an issue. In fact, we're working on tools to help you visualize your code easily and bring up those reproductions. If interested, do consider signing up for our free beta!
If possible, when reaching out for help, it's so helpful to practice pair programming. Most likely, if receiving help, you'll be driving, meaning you'll be doing the coding, but you could also be navigating, meaning you'd be giving tips as your helper as they drive.
Having established the problem, communication is critical to ensure a successful pairing session. More on pair programming coming soon!
In an instance of "do as I say, not as I do": I often panic when stuck. Impostor syndrome sets in, and I start wondering if I've ever been a competent engineer.
As engineers, trying to solve new problems or trying to integrate solutions into existing ones is a tricky matter!
One thing that I try to keep in mind when working on a problem is that it will eventually be resolved, and that patience is key. We will eventually reach that "Aha!' moment where everything will click.
What about you? How often do you get stuck? How long do you wait until reaching out for help? We'd love to hear from you! Hit us up on Twitter or email us