Everyone who has ever coded anything significant (and probably everyone who has ever done anything that requires creativity) will recognise the problem of getting stuck. Most of the time it is caused by lack of information or confidence to move forward. Over time I’ve identified a number of reasons I get stuck and also strategies to deal with this.
Perceived Dependencies
In larger systems, components often have to interact. If none of these components are properly defined or all need changes, it can be hard to get started.
Strategy: Fake a little, build a little.
It’s tempting to start things from the beginning and just write the code sequentially, however if things are not entirely clear it can work very well to start at a very very high level.
I usually just outline everything in 3 to four steps, each being a commented line. For example if I need to classify emails into categories, I might write something like:
// get e-mails
// get defined categories
// classify e-mails
Then write each step as code. This is the time you will need to start thinking about how data is passed around. Whether you will need objects or just lists of strings, etc.
// get e-mails
emails = get_emails()
// get defined categories
categories = get_categories()
// classify e-mails
classifier = new Classifier(categories)
for email in emails:
scores = classifier.get_score(email)
category = get_top_category(scores)
print email.title, category
To test these assumptions you will need to actually implement the functions/components you’ve used. However, key to this strategy is to now fake these functions/components as much as possible.
e.g. I may implement get_top_category as:
def get_top_category(scores):
return scores.keys()[0]
The reason to do this is not because I don’t know yet how to implement this, but because I don’t want to get stuck in details. (e.g. what happens if there is a tie, what if all are zero, etc etc) Things become so much easier when you have an end-to-end solution that just compiles.
Can’t wrap your head around it
You all know this feeling, but the cause is less clear. Ill defined tasks, generic approaches, feeling tired, they all can lead to this.
Strategy: Second Pair of Eyes
Not everything needs to be solved on your own. If you are not clear on the ‘what’, just talk to a coworker, manager or customer. If you are not clear on the ‘how’ just start explaining to a coworker why you can’t move forward on this.
A very important part of this strategy is the need to explain and define your problem. Even the act of just explaining it may resolve the issue. In that case it’s called Rubber duck debugging: the act of explaining your problem to a rubber duck.
Choice
This is probably the biggest show stopper: as soon as you are aware that there are multiple options with various tradeoffs, it’s hard to proceed. I’ve seen bad programmers finish things quicker, just because they were happy with any solution that worked, in their universe there were no trade-offs to be weighed.
Strategy: Writing
If choice and tradeoffs are involved, you need to start writing. Just create a document with bullet lists of:
- Everything that is already given (e.g. API urls, relevant documentation)
- Requirements
- Important conditions (e.g. needs to work when device is offline)
- Potential issues (e.g. there may be too many items to fetch in a single API request)
Then for each of them come up with at least two approaches. Then for each of them also add potential advantages and downsides. And then again for each downside, figure out how to solve it.
For me this usually becomes a nested list of four or five levels.
One of the big advantages is that you can leave this for the next day to refine, without having to start all over again in your mind. Furthermore, you can easily refine this into documentation after the decisions are made.
Boring…
The idea of heaving to spend days to do some boring, semi-repeatable task that could have been avoided when better choices have been made in the past can certainly demotivate you.
Strategy 1: Embrace it
Sometimes you’ve got plenty of energy, but can’t really move forward on an issue (e.g. due to one of the reasons mentioned above) this is the perfect time to do this boring task you’ve been putting off. It is 100% clear and every minute you spend on it will actually move you forward.
Strategy 2: Make it interesting
Boring things are also often the things that are easy to automate. This might be the right time to learn more about:
- advanced find/replace features in your IDE
- find/grep/sed on the commandline
- UI automation
Strategy 3: Delegate
What is boring to you, may be a nice task for someone else to learn a new skill. e.g. writing UI tests might be boring, but it can be a valuable and marketable skill for your intern.
Bugs
Lots of people get stuck on finding and fixing bugs. But remember, in debugging there is always a next step to take.
Strategy: Identify and check your assumptions
At the root of every bug is a bad assumption. This can be an assumption on what your code will do, the contents of a variable or the correctness of an external dependency. Debugging is just identifying your assumptions,
I’ll write a follow up post on debugging strategies soon.