Good debugging skills come with a mix of intuition and some mental models on how to approach the problem. The former has no practical actionable steps because it comes from the experience of being exposed to many different problems and you just need to keep going on with your career and learning with every new debug. This blog post is about those mental models that will help you get rid of bugs faster.
First Principles Thinking
Start with the absolute truths about the problem. The idea is to break down the bug into its basic building blocks and then reason from there. Assuming the wrong things can lead you to lose hours down the wrong debugging path.
Raise hypotheses and work towards validating or invalidating them, one by one.
This will prevent you from going down a path you’ve already tried just because you have no other ideas of what to do. This will also help you narrow the scope of your debugging which will make your google searches more specific and helpful.
Don't be lazy about validating any hypotheses because you think that it's not an important hypotheses to validate (or because it's too difficult). Go forward until you can be 100% sure and get rid of any doubt.
Know what you don’t know
There are four stages of competence
- Unconscious incompetence — Ignorant even that some knowledge is lacking
- Conscious incompetence — Knows there is a problem with his knowledge base
- Conscious competence — Understands the problem and knows how to navigate towards de solution
- Unconscious competence — The solution is evident, second nature
Really hard problems in programming are a reflection of lack of knowledge (think “probably there is someone out there that would solve this in an instant’’) so it’s important to bring awareness about your own skill set. If you know you don’t fully understand one of the building blocks of your problem (Conscious incompetence), it’s a good strategy to take a step back and dive into learning about it.
You may be having difficulty solving a problem because you are not aware of the deficiencies in your skill set (Unconscious incompetence) and a mentor or an online forum can help you with that if you ask the right questions (What are the building blocks of this?) instead of just going for the solution.
Good communication when asking for help
Your communication when asking for help should be efficient, which means you communicate the most information with the least amount of words. This requires a lot of mental energy on your part but will increase the likelihood of getting help back (because it will require less energy on the helper part to understand what you’re asking).
You should describe all your hypotheses, the ones already validated/invalidated (and the steps you took for this) and the ones you’re still trying to validate.
Practical real life example
Release build of our react native ios app not building with success after upgrading from RN61.5 to RN63.4
First Principles — What I know is true for sure?
- The debug variant works fine
- It fails to find some node_modules dependencies for one of our modules
- Cocoapods is responsible for copying these dependencies
- Cocoapods in RN 63.4 has changed the way to write the podfille
- The failing dependency doesn't have support for the armv7 architecture and after upgrading to RN63.4, this lib started trying to build for this architecture which is causing the build to fail.
- Hypotheses 1: We messed up our podfile when following React Native update instructions
- Hypotheses 2: the lib causing the problem still is not complaint with the new way cocoapods works with the podfile
- Hypotheses 3: can we force this specific lib to not build for the armv7 architecture?
What I don’t know and should get knowledge?
- I don’t know why the podfile is written in a different way in RN63.4 → actionable: Learn what has changed with cocoapods from version 61.5 to 63.4. → Concludes Hypotheses 1 is false and that our podfile is fine.
- I don’t know exactly what cocoapods does under the hood. → actionable: Learn how cocoapods work. Read it’s documentation. → Concludes Hypotheses 2 is false by checking the podfile from the module and learning about and double checking each configuration in there. Everything was setup correctly.
- I don't know how to customize the build of each dependency with cocoapods. → actionable: Learn how to fine tune the build for each dependency with cocoapods. → Solved the issue by forcing the lib to exclude the armv7 architecture and the build worked.