Having the ability of problem solving is fundamental for a programmer. Useful for debugging, but not only for that, is one of the most researched qualities among recruiters of this profession. There’s nothing more important than knowing there’s a problem, identifying it and then finding a solution. That doesn’t mean you’ll be the one to practically solve it: before having technical skills, you need to be smart.
Some of us are naturally born with optimized thinking, but that doesn’t mean that anyone can’t practice and develop this skill. For those of you who wrote “Problem solving skill” in your résumé but do not have it – don’t worry: we’re here to teach you how to achieve it.
The 5 foundations of problem solving
Problem solving can be used for different purposes. Usually you need to think about a method, an algorithm to optimize a process, or you’re looking for the cause of a complex bug to solve it. The first, fundamental requirement is obviously to understand the problem. Only after you completely understood the purpose and the starting point, you can proceed to resolve the problem.
1 – Divide and conquer
The first and most important lesson we receive at a programming course. By addressing a problem in its entirety, we often don’t reach good results, or we even find it impossible to solve. A good problem solver is capable to identify the sub-problems or steps that are necessary to achieve the solution. When facing a bug, it’s better to isolate classes or parts of code, and evaluate little by little the logic and the evolution of the bug, until reaching its origin.
From here on, in case of a complex resolution, e.g. that requests a rethinking of the logic of the program, you need to proceed step by step, resolving one sub-problem at a time, adding complexity gradually to include everything. The same principle is used when a design of a software is needed. It’s very useful to write down a list of tasks or sub-goals, that has to be ordered, and give each entry a description. If needed, all the dependencies between tasks have to be explicitated.
2 – Parallel thinking
After considering what has to be done and all the dependencies, you need to think if there are some operations that can be done concurrently. If two tasks are independent from each other, it’s better to conclude them at the same time. This means optimizing: this reduces downtimes, and the saved time can be used for more complex tasks. At this point, it’s better to revise the list and maybe organize the tasks in a diagram, to better understand the dependencies.
3 – Abstract
When facing a problem, a common mistake is finding a solution that is good for that specific case. It would be more convenient to find a generic solution that can be adapted for all the problems of the same type. You first need to categorize the problem and find the family of problems to which it belongs, so to find a general algorithm that can be reused when needed.
4 – Reuse solutions
This principle is related to the previous one. Once you’ve found all the sub-problems and you’ve identified the dependecies, there is one question to ask yourself: “Is there a solution already?”. Why wasting time and energy when someone has already resolved our problem? To achieve this, it’s necessary, as said earlier, to understand what we’re trying to solve, otherwise we can end up choosing the wrong solution. Also, it’s ok if we can’t find the whole solution. In that case, we proceed by looking for a already-made-fix for each sub-task.
5 – Thinking in terms of data-flow
This last concept is necessary to master all the others. A single piece of information doesn’t live just where the problem has showed up, but it has an origin, a destination, and a series of steps and transformations. If when we identify the tasks we don’t consider that, we limit the solution to a single part, risking not to find the best one. It’s fundamental to consider the whole path of the data, past and future, so that we can frame the perfect piece in the bigger puzzle.
How can you obtain this skill?
Problem solving can be taught, but not entirely. Understanding the fundamentals it’s the starting point, but you need to practice a lot and face many problems of different kind. It will be hard at the beginning, but by understanding the errors it will become easier and easier, until it will be natural.
This ability can be used in every aspect of our everyday life. When facing a problem, if you’re able to analyze it and identify the steps, it will be harder to fail and easier to not giving up soon.
Thanks to Coderhood