Debugging is a funnel
Most bugs are created by one line of code… many by one character. Debugging is the funnel that starts with your application - sometimes your server / os / or device - and leads you to that one root cause.
Whenever I end up feeling that I spent too much time trying to isolate a bug, as I think back on things, it’s always because I wasn’t constantly narrowing down where the bug could be coming from.
Thinking of debugging as a funnel can make some difficult bugs seem easy to solve. For example a colleague, Greg, was writing a VOD (video on demand) app for Smart TVs. The code worked - showed a browsing page - on the browser, but loaded on to the TV, the app would crash before showing the screen.
Greg had narrowed the problem down to one of context. this.private
was not
available on the TV, but it was available on the browser.
In this case, it seemed like the context should be available. The method was
being called directly - focusFinder.configure()
, and within the configure
method, this.private
was being referenced. It was there on the browser, but
missing on the TV.
Logging out (this TV has no debugger) this.private
on the TV showed that it
was undefined
. Maybe this
was not the right object? Logging out
Object.keys(focusFinder)
logged out all the correct keys except for the one
we wanted. So the question became: what was different about our key? It was
called private
and it was the only key whose value was an object and not a
function. Changing the name of the key to internal
made the app start and is
probably a better if equally broad name. Private is a future reserved keyword
(not yet used for anything but reserved anyway) in JavaScript using strict mode.
The browser and the TV had different implementations for how to handle the
situation.
I feel like the trick here was just getting a handle on the fact that the correct object was being dealt with but the desired key value pair was missing from it. It is often tempting to jump to conclusions, and having the incorrect context is often your first thought when working with JavaScript. The second trick was realizing that changing the name of the key might accomplish anything. That is Occam’s razor at work.
It can be tempting to jump to conclusions, but since debugging is very similar to binomial search, and false conclusions can lead you into thousands of lines of code that have nothing to do with your bug.
In fact binomial search can be an efficient way to find the cause of a probelm
if for code that worked in the past but no longer does. git bisect
is a great
tool for these type of problems.
Sometimes you have to “bisect” the code you are working on. For example Cooper was working on figuring out why an LG TV app was running so slow. He had eliminated many potential causes relating to the running of the code. Finally he decided to just delete the majority of the elements on the page. The app sped up. At this point it’s a binomial search in the dom, and the culprit turned out to be an audio tag. Including it in the page slowed down the app.
Often bugs create errors, and the ability to inspect these errors either speeds
up or makes fixing the bug possible. This is why it’s so important to know the
location of log files and config files for parts of you system… or to have
some mechanism in place to monitor logging output. For node apps that have good
logging, pm2 log
is often enough.
Of course if your error is not being logged, things become much more difficult.