Recently I’ve had the honor and luck to be a mentor for two of my junior colleagues. We have been talking a lot about problem-solving in software, and a lot of interesting points were made. This inspired me to think about this topic and compile a list with the pros and cons of various techniques.
As developers, we depend on feedback to produce great software in reasonable time. When we are facing a bug or trying to implement the next awesome feature we tend to fiddle with the program. We add, remove, comment and uncomment lines of code. We play with undo/redo, toggle switches or use Git version control to navigate between different versions of the software.
To determine the next step to take, it’s crucial to reliably and quickly get feedback from the previous experiment. Even if we have a Big Plan to move forward it’s good to know that we are still on the right track.
These experiments are mental tools to triangulate the problem: we use various techniques to get a better understanding of the issue at hand as well as the current state of the software. We are trying to know more facts and narrow down uncertain elements.
There are numerous ways to get closer to the solution, like the classical debugging, experimenting in the REPL, or simply restarting the application after each change to name a few.
They can even be combined. For example, it’s quite common in the JS world to start a debug session and invoke functions from the REPL.
One recurring problem I often see is sticking to a single strategy when it’s not working. Although it’s also a matter of preference, there is no single “right” way of doing things, each strategy has its advantages and disadvantages.
Even if you work on a single project, usually you can’t stick to a single strategy the whole time. Various parts of a codebase have different constraints regarding how you can interact with them, requiring constantly adapting mindset when it comes to solving problems.
Make sure you use the right tool for the job by continuously monitoring your workflow and choosing your approach consciously. It’s not easy to take a step back and recognize that the problem requires a different method.
In the following posts, I am planning to dive in and focus on the individual options a programmer can choose from when he faces a problem, for example:
- Manual verification through the UI
- Log internal state
- Debugging with breakpoints, conditional breakpoints, and tracepoints
- Read-Eval-Print-Loop (REPL)
- Tests and TDD
I hope that these posts will be helpful for beginners who are just joining the programming community and are looking for clues on how to approach problems in general.