It is a painful thing To look at your own trouble and know That you yourself and no one else has made it - Sophocles, Ajax
Debugging, despite being one of the most valuable engineering skills to have for programmers, is a hard science to master. But what’s the matter with life?
We know that life is just like mountain climbing, filled with all sorts of ups and downs. There are moments or periods of time we are suffering badly that we want to know the reason desperately. The process of figuring out the why of those life struggles is similar to how programs are debugged. To debug effectively, we need to stabilize the error first, or in other word, make it reproducible. Many bug reports mandate reproduction examples. Anthony Fu had a great article explaining the why. Otherwise, we might be fooled by randomness. Equally in life, if the same mental problem consistently drains our motivation, it might be a good time to dive a bit deeper than simply tolerate it.
However, we know that the root cause of a bug may not be on the surface, it could lurk somewhere deep. If we only look at what goes wrong at the moment, which is what people tend to do, we might only catch the surface. If we attempt to fix what’s on the surface, say having a workaround with some hard coded values, it may get the test suites to pass, but it’s a false positive. Instead, we need to understand what brings us to the situation. In program, we get the help from reading stack trace. In life, a series of events or choices we’ve made in the past may give us more clue. To leverage stack trace for debugging, we need some degree of “logging”. This is usually done by searching our memories. The problem with counting on memories is that they aren’t as reliable as we would wish. This is where journaling comes into the scene. It may require a bit extra effort, but it gives a more undistorted view of what had happened before.
Root Cause Analysis
When debugging computer programs, those “Caused by” lines worth more attention. The lowest caused by may often be the root cause, besides they hide deeply that you need a lot of patience to uncover them. Similarly, five whys is a good technique for root causing real world issues, including the struggles we’re dealing with. Patience is the key, don’t panic.
After carefully analyzing the available evidences, we form our assumption. Making the right assumption is critical. For example, assuming it’s my fault is a good assumption while pointing fingers is not. When bugs popup, they’re much more likely caused by application code we wrote rather than framework or language constructs, thus it’s wiser to chop down the stack trace to lines associated with our own code. Jeff Atwood even calls this first rule of programming. When things didn’t work as expected, like when betrayal happens or relationship sinks, it’s always more rational to take the responsibility to reflect on ourselves rather than blaming others. This isn’t easy either, our ego will keep us blind from our mistakes. Self-defense is part of human nature, but true growth often comes from taking the harder road.
Don’t forget to validate our assumptions. It’s usually done by taking actions and reviewing results. Again, journaling helps. It could be a repeated process since we might fail a couple times and our assumptions turned out to be totally wrong. If it happens, which is fair common unless you’re an expert in that domain and you developed unbiased intuition based on previous experiences, we’ll need to take a step back to form a new assumption and validate it accordingly again. This eventually builds up a feedback loop 🔁 from which we obtain better insight and judgments about the original problem through each iteration. Persistence is the key, knowledge compounds as long as we’re heading towards the right direction.
Eventually the bug will be fixed, time to party right? Yes, but hold on for a second. Conducting a post-mortem reflection that summarizes lessons learnt, plus diligently asking ourselves where else in our life the same lesson can be applied, this will curate a long-term thinking that our future selves will be grateful for and save us from making the same mistake again.