Whenever I’m debugging an issue, I try to model it mentally, hypothesize what could be wrong, and then conduct controlled experiments to narrow down the issue. I trace execution carefully and inspect values.
That usually works well. When it doesn’t work or when I just don’t have many ideas, I often simply smash everything with a hammer (metaphorically speaking).
Essentially, I do something in my code that will force an error. Then how (and if!) the error shows up will tell me a lot about my problem. Here are a few examples.
Canary in a Coal Mine
If your algorithm isn’t working as you think it should, or your tweaks aren’t having much of an effect, a simple obvious test to try is to just return some fixed value. It’s not always easy to figure out by hand that a certain set of inputs should produce a particular value and updates to complicated functions can be tricky sometimes. I’ve found it useful to stub out portions of my code to return a fixed value like 0 or 42, which I can then look for in my interface. If I am not seeing it, then I know I am majorly misunderstanding something.
h2. Throw a Wrench into It
One tool is to throw an exception in your code. This is an escalation of the above. Exceptions are typically quite visible, resulting in error messages on the screen or the application dying altogether. This makes it a useful tool for debugging if you aren’t seeing the effects of your changes. If this still isn’t giving you much insight, then try:
h2. Hit it with a Hammer until it Does Something Different
If it still doesn’t look like your changes are having any affect, it’s time to bring out bigger and more invasive changes. Try to force a syntax error in your code. It should be very very obvious by then if you are editing the wrong thing, or if there’s a build system issue that is causing your code to not compile, or if something is cached.
I’ve also found this quite useful for application-specific configuration files, which often will ignore anything they don’t understand.
h2. Burn Everything in Sight
Worst case, try just starting to delete code and files wholesale. This should always change something at least, and it makes it useful as a simple smoke test to ensure that you’re testing against your local environment and not the production deploy (for example).
As with the previous, this is also useful for things like making sure an application or server component is actually looking at the right configuration files on disk.
h2. Other Tools
None of this is to say that debuggers, unit tests, and other tools are the wrong way to debug things. All our other tools are great, and I think this strategy is another useful tool to have in one’s toolbox for diagnosing issues. Many of the tools out there are very nuanced and will let you gain great insight into the operations of your code. But when you are struck by things that seem inexplicable, strategies like this can help shed some light on the shape of the problem and quickly narrow down what your misunderstanding might be.