Don't Get Stuck: 6 ways to get unstuck and code faster
A lot of my time as a programmer, and maybe yours as well, is spent being stuck. My day often goes like this:
- Write some code.
- Run the tests.
- "It failed."
- "Why did it fail?"
- "I don't know."
- "That makes no sense."
- "Seriously, what?"
- "That's impossible."
- "Lets add a print statement here."
- "And maybe try poking around with the debugger."
- "Oh! That's it!"
- "No wait, it isn't."
- "Ohhhhhhhh there we go."
- Run the tests.
- Tests pass.
- "Time for snacks!"
Given how much time you can end up wasting in this mode, Kaitlin Duck Sherwood points out that not getting stuck is one of the keys to programmer productivity. Imagine how much time I could save if I skipped steps 5 to 13 in the transcript above.
Not getting stuck will make you far more productive. Here are six ways to keep you from getting stuck:
Recognize when you're stuck
If you don't know you're stuck then you can't do anything about it, so the first step is having some way of measuring progress. Whenever you start a coding task you should have a time estimate in mind.
The time estimates should be short, no more than a few hours or a day, so a bigger project should be broken up into smaller tasks. The estimates don't have to particularly accurate, they just have to be in the right range: a task you estimate at a few hours should not require days of work.
Given an estimate of 4 hours, say, you can then recognize whether you're actually stuck:
- If it's 10 minutes in and you have no idea what to do, then that's fine, there's plenty more time.
- If you're 2 hours in and you haven't produced anything, then it's pretty clear you're stuck and need to make some changes.
Comparing actual time spent to the initial estimate tells you if you're making progress, and working in small chunks ensures you recognize problems quickly.
Ask for help
Now that you've recognized you're stuck, the next thing to do is find a solution. The easiest thing to do is talk to a colleague.
This is helpful in multiple ways:
- You're forced to restate the problem in a way someone else can understand. Sometimes this is sufficient to help you solve the problem, even before they get to answering you.
In fact, this is so useful that sometimes you don't need a person, and talking to a rubber duck will do. I like debugging out loud for this reason, so occasionally I use a #rubberduck Slack channel so I don't distract my coworkers.
- Your colleague may have an idea you don't, especially if they're experienced.
For example, recently I was utterly confused why Java thought that
assertThat(0.0, isEqual(-0.0))was a failing test; it claimed
0.0wasn't the same as
Eventually I shared my confusion, and someone noted expression relies on
Double.equals(), and then went and found the
Double.equals() API documentation.
And indeed, the documentation notes that
new Double(0.0).equals(new Double(-0.0)) is false even though in Java
0.0 == -0.0 is true, because reasons.
Use or copy an existing solution
If you or your colleague can't find a solution on your own, you can try using some one else's solution. This can range from the copy/paste-from-StackOverflow fallback (but be careful, sometimes StackOverflow code is wrong or insecure) to copying whole designs.
For example, I built a multicast data distribution protocol. This is not a trivial thing to do, so I found a research paper and copied their design and algorithm. Designing such an algorithm would have been far beyond my abilities, but I didn't have to: someone smarter and more knowledgeable had done the hard work.
Find a workaround
Sometimes you're faced with an important bug you can't fix. Working around it may suffice, however, as you can see in this story shared by reader James (Jason) Harrison:
Several years ago, I was working many late nights on a new Wii game that was going to have gesture recognition. The first part of the game activities went as smoothly as could be expected and then we came to a new level where the player was supposed to bring the Wiimote up and then down quickly. This must have tripped on a bug in the system because this gesture could not be reliably recognized.
Replaying recorded motions demonstrated that the problem wasn’t “just” in the data form the Wiimote or in how the player made the motion but in the system. Instead of being deterministic, the system would work then not work. Looked for variables that were not being initialized, data buffers not being cleared, and all state that could possibly leak from previous inputs.
Unfortunately, all of the searching didn’t find the problem in time. So it was decided to reset the recognition system between inputs. While wasteful, it was the only thing that did fix the system and let us ship the milestone to the publisher. Left a comment in to find the problem later. Never did find it. Game was shipped with this fix.
Drop the feature
If you're working on a feature and it's taking forever, maybe it's time to consider dropping it. Can it wait until the next release? Do you actually need it?
A feature usually lands on the requirements list for a reason, it's true. But a surprising number of features are in the nice-to-have category, especially when it's taking far too long to implement them. If other approaches have failed to get you unstuck, find the person in charge and give them the choice of shipping late or dropping the feature.
Redefine the problem
Finally, another approach you can take is redefining the problem. The way you're approaching the problem may be making it needlessly complicated to solve, so revisiting the problem statement can help get you unstuck.
You can redefine the problem by relaxing some of the constraints. For example, maybe you're having a hard time finding a date picker that matches the website design. If the problem statement is "add a usable, good looking, date picker that matches our website style" then you might spend a while looking and not finding any that are quite right.
Often you can redefine the problem, though, to "find a minimal date picker so we can demo the feature and see if anyone cares." With that more limited scope you can probably use one of the options you initially rejected.
You can also redefine the problem by figuring out the real problem lies elsewhere. Havoc Pennington has a wonderful story about the dangerous "UI team": they will feel their mandate is to build UIs. But software that doesn't have a UI and "just works" is an even better user experience, if you can manage it.
In short, to keep from getting stuck you should:
- Break all your work up into small chunks.
- Estimate each chunk in advance, and pay attention to your progress against the estimate.
- When you recognize you are stuck: ask for help, copy an existing solution, find a workaround, drop the feature or redefine the problem.
I've learned most of this the hard way, over the course of 20 years of being stuck while writing software. If you'd like to avoid the many mistakes I've made as a software engineer during that time, both coding and in my career, sign up for my Software Clown newsletter. You'll get the story of one of my mistakes in your inbox every week and how you can avoid making it.
Avoid my programming mistakes!
Get a weekly email with one of my many software and career mistakes, and how you can avoid it. Here's what readers are saying:
"Are you reading @itamarst's "Software Clown" newsletter? If not, you should be. There's a gem in every issue." - @glyph
"Definitely subscribe if you want to learn some things that Itamar learned the hard way." -- Victor Algaze