Problem solving tactics for software engineers
I do love summertime. The weather is warm and the view outside my London-apartment window is bright and joyful with our solitary tree in full leaf. As people go on summer holidays (even during the covid-era) I find I get drawn into some of the noodly problems that crop up. Once a problem is solved, I typically reflect on how we could have prevented the issue. A problem that cropped up recently though made me consider the nature of problem-solving itself.
Finding good problem solvers #
When I evaluate candidates for job-roles, their problem-solving ability is very important. It's difficult to assess during an interview. If you pose a typical FAANG question e.g. "how many beach balls can you fit in a school bus", it can mislead you. Interviews are stressful enough. Asking questions like that can result in good candidates not making the cut and the whole goal of interviews is to try help excellent people make their way onto the team.
The approach I've taken thus far is to ask a candidate to come in prepared to talk about any CS topic that they're comfortable with. The hope is that if it's an area they're confident in the usual interview nerves won't be as troubling. With some gentle questioning we can set the good candidates up for success. A selection of questions are typically pre-formed. As the interview continues they're slotted as naturally as possible into the flow of conversation.
It's not a perfect approach by any means. One problem is coming up with questions that aren't too contrived, and is interesting enough to show if a candidate can identify and exhibit the problem solving strategies that we typically deploy. Showing new problem solving strategies that we can learn from is even better!
Problem solving strategies #
I thought it might be useful to jot down some of the strategies I employ, or I've seen employed. Hopefully this will help excellent people find their way to the job I have for them.
It all starts with mindset. Any problem can be solved provided you can extract the right information at the right time.
Divide and conquer #
This is useful for giant problems if you aren't sure where to start. In mathematics you'd break the problem into smaller pieces and solve each piece independently. Once solved, bring those pieces together to form the solution.
The way I use divide and conquer in engineering is to break down the different areas that a problem can occur in e.g. client side, CDN, infrastructure (load balancer, servers, etc.), backend, etc. For each area consider the flow of data and construct your hypothesis, and method. Writing down your method is important if you're working in a team because it means that others can look at your work and check for errors.
Tackle each hypothesis, one at a time. Breaking down problems in this way is good for ruling out areas and narrowing focus. This is especially useful in problems that are difficult to reproduce. If you are able to find someone who can reproduce an issue you have a good idea of what questions to ask and things to test.
Rubber duck #
The rubber duck approach is to explain the problem to a (real or imaginary) rubber duck. Explain the problem in as much excruciating detail as you can. Getting all of that information out of your mind helps it catalise and you can begin to see connections between things that you can try.
Stack Overflow #
No, I don't mean post on Stack Overflow (SO) and hope for others to solve the problem for you :) This is somewhat related to the rubber duck approach. If you look at the best SO posts they are easy to understand. Problems are broken down in a way that is easily digestable. From what I've seen those are usually constructed in the following way:
- Start with a brief explanation of the issue you're facing
- Then explain the variables at play (inputs and outputs)
- Then write down what you've tried and what the outcome was
Pictures and arrows and things #
Some problems are complex. The difficulty with complex problems is that understanding them and following the threads becomes complicated. When this occurs I typically break out my crayons and draw out the flow of data / operations so I can have a better visualisation of how things fit together. This also helps with abstraction - hide away the (hopefully) irrelevant detail so you can focus on the most important elements.
Work backwards #
Assume your system is working perfectly. If you wanted to inject the problem with the characteristics you're seeing, how would you do it?
Oblique strategies #
Oblique strategies are approaches developed to help artists break creative blocks. I've long-enjoyed a blog post written on the topic by former Etsy engineer Kevin Lawler where he has put together programming-specific strategies e.g.
- Zoom in. If a tricky piece is causing issues, focus on it exclusively—come back to it the next day if necessary. Let it take up the whole frame.
- List dependencies to determine order of completion. Order work (in the absence of other order) by most likely to inform later work.
There are too many to list here - check out Kevin's blog for more goodness. I've found these to be more useful in day-to-day work and they may be a little difficult to deploy in an interview exchange.
Shower driven development / Sleep on it #
Take a walk. Take a shower. Get some rest. This is really a last resort after struggling with a problem for a while. For some reason the brain uses the time to tackle the problem in the background and presents you with something like a solution when you least expect it. This is not terribly useful in an interview situation though...
I do not have a CS background so I also see it as a nice way to learn something new. Most of my learning is done before the interview via Wikipedia. Wherever possible I have someone with an actual CS background and ideally a good understanding of the topic sit in the interview with me :) ↩︎
I do love rubber duck approaches to problem solving. For one, it actually helped in relationships - when people say you're a "good listener" I've learnt that really it means that you're good at being a rubber duck. ↩︎