Sometimes it’s worth stepping back and asking yourself, “Is the problem I’m trying to solve really the problem I want solved?”

For example, “I can’t connect to this coffee shop’s wifi” may be worth trying to fix for a couple of minutes, but the real goal is connecting to the internet. The coffee shop just happens to be the most convenient/obvious means of doing so. If you have another way of connecting — say, by tethering to your phone connection — you’re better off switching methods instead of continuing to chase what may be a dead end.

Similarly, with software design, whenever you begin with a set of parameters and start off down a path that seems to be getting more and more complicated, it’s worth taking a step back and asking: what am I really trying to solve here? Are the constraints real, or can I drop some of them and take a different, more effective approach?

If the problem is presented as: How do I use these tools to accomplish this task, sometimes you’ve got to use those tools — but sometimes another set of tools will do the job better.