DEV Community

Jeriel Ng
Jeriel Ng

Posted on

Solving Problems Methodically: How to tackle the impossible task

We’ve all been there: You’re tasked with implementing a feature or fixing a bug, and it sounded doable at first, but the more you looked into it, the more you realized you have no idea what’s going on. Or maybe you simply had no idea what to do even from the beginning. In either case, you find yourself three days into the task with no progress to show for it, and now you’re wondering if you’ll be able to figure it out by the end of the sprint, if ever.

At some point, you may reach out for help, which is definitely a right thing to do. But, before you do, what if there are simply some things you haven’t tried yet?

Challenging your assumptions

It’s important to take a step back in situations like these and reassess the scope of the task because, very often, digging deeper and deeper into a problem leads to tunnel vision and solidifies assumptions that may have been wrong to begin with.

When we’ve decided that we have the solution to a problem, we anchor to it. If our approach was correct, we finish our task and everything works as expected. But if it wasn’t—or if it was an incomplete design—we can often hit a dead end and find ourselves stuck.

The longer this goes on, the more we start to lose sight of the initial task. It’s like when someone asks you a question, and you go down a series of tangents. At some point, you forget what the original question was and have to ask them to repeat it.

Knowing what the end should look like

Very often, we flounder in our task because we don’t even know what we’re aiming for. How exactly do I know when I’m done? Maybe your ticket already has clear acceptance criteria, but even if it does, your job is to figure out what that looks like technically.

If you can determine what your end goal should be, this means you can come up with proper checklist of test scenarios. You know you’re done when your deliverable fulfills each of those test scenarios.

To do this, spend some time sketching out your thoughts. Think about edge case scenarios and how you might plan to tackle those. Think about what sub-bullets might live under each of those scenarios. For larger tasks, there will certainly be plenty. You’ll quickly find that this has a side effect of rubber ducking the problem, and by uncovering your edge cases, the shape of your problem starts to become clearer.

Setting up the right tools for the job

If you’re going to challenge your assumptions, as we discussed above, you’ll need a way to keep coming back to square one, and you do so by having all your tools in the right place. We need a proper understanding of the problem to be able to separate the core facts from what we’ve wrongfully assumed.

Oftentimes, it’s simply not your inability to solve the problem. In such cases, you may not have all the information available or the tools to get that information.

For example, if you’re trying to debug a pesky network issue, it will be almost impossible to figure out what’s going on without using a network proxy tool like Charles or Proxyman. Similarly, have you ever tried figuring out the root of your bug without a debugger connected?

If you don’t have all the necessary tools to do the job, you’re only working with part of the whole picture. When we only think we know what the problem is, we can be wrong, and when we’re wrong about the problem, we’ll often struggle to come up with the solution.

The reason why developers insist on having reproducible examples in bug reports is because you can’t properly diagnose someone’s illness with just a fraction of the actual symptoms.

Additionally, having all your tools will allow you to not only root out bad assumptions but also experiment with new ones through trial and error. Simply speaking, trying to work through something without the proper tools is as good as doing it blindfolded.

Remember, then, that if you ever find yourself banging your head against the wall, maybe it has nothing to do with your abilities and more to do with a lack of information. Stop and think about what other tools you may have at your disposal rather than trying and re-trying the same things. Even if it may take some time getting set up, that time spent might quickly become worth it. Plus, if you ever run into a similar issue again in the future, you’ve already got your environment set up—or at least you now know how to repeat it.

Breaking down your problems

One of the most common pieces of programming advice people give is to break a large problem down into smaller pieces. I’ve never been a fan of tidbit one-liners like this because, while they are certainly true, they don’t typically give insight into what that means practically. So what exactly does that mean?

It’s important to remember that code usually boils down to a series of steps, moving data from one end of a pipeline to the other. This can be true for your CI/CD pipeline and its environment variables. It’s also true for your signup form that spans multiple web pages. Along the way, your data can be read or even transformed into something else, and your best bet to figuring out what’s wrong is to pinpoint where your data no longer looks like what you expect.

If you’re able to figure out where your data flow has deviated from its course, it’s pretty safe to assume that every other part of your code before that is not the problem, and most likely, every part after it is also not the problem either. Now you’ve narrowed down the problem into that “smaller chunk.”

Looking in a different corner

This may be more of a bonus section because it’s less methodical, but it’s still worth noting. When you’re wondering what other tools you could be using, it helps to think outside the box.

Sometimes, Google, Stack Overflow, and ChatGPT aren’t the only places to find information. You can get creative with finding new pieces of the puzzle:

  • GitHub search: Search for usages of an API you’re using and pattern-match off of that. The nice thing about searching through source is you’ll get exact matches for it, rather than vague matches in documentation or Stack Overflow posts.
  • Your company’s Slack: Chances are, someone else in the company has had a similar question before. Slack is by no means a replacement for proper documentation, but it often provides historical context behind previous decisions and solutions to old problems.
  • Old pull requests or commits: Sometimes a problem you’re facing isn’t entirely new. Your teammates might have an answer, but maybe you don’t even need to ask because they’ve already pushed something similar two years ago. It helps seeing if there’s been a similar pull request, especially since it’ll contain all the relevant code changes for that piece of work.

Do you have another source you normally consult for information? Feel free to share in the comments!

Final thoughts

Of course, knowing and practicing all the above is a lot easier said than done. Some problems are very much so impossibly large. But the important thing to remember is to take a step-by-step approach. I’ve gotten into situations where the panic has settled in, and it’s hard to think straight because my process is clouded by emotions. In times like these, being methodical helps to ground you with the facts and get you back on track.

Top comments (0)