Advanced JavaScript Debugging

Advanced Debugging Techniques in JavaScript – Part 1

by on January 6, 2014 1:36 pm

Introduction

I was a terrible debugger when I first started programming. I could tell an issue was happening, but it always took me a long time to track down where and why it was happening. Even in a strongly-typed language like C++, it took me hours to find simple bugs in my code.

Debugging is one of the hardest parts of being a programmer. There are as many classes and books on programming as stars in the sky, but next to nothing on formal debugging. When an issue occurs, it could be in code you’ve written, code someone else has written, code another company has written, an issue in the user’s browser, a network hiccup, or any other number of issues. Figuring out where and why something is broken takes time even for the best programmers.

I’ve been writing code for a long time, and have picked up some tricks along the way. In this blog series, I’ll go over some strategies I use to diagnose and fix bugs. Some techniques and strategies I discuss are specific to JavaScript while others can be applied to any programming language.

Validating Assumptions

All of the techniques I will discuss are different flavors of the same idea: validate your assumptions.

As I said before, I was a terrible debugger when I first started programming. It was in my third programming class in high school that I started to really ask myself why debugging was so hard. I made a conscious effort to analyze and dissect the things I was doing to fix my bugs. A pattern emerged after a while. I found that I was spending much more time than I needed to on peripheral issues than trying to address the issue itself. My effectiveness increased tremendously when I would first identify my assumptions then formulate how they could be validated.

The best way to focus on the issue itself is to validate your assumptions. Lets say a user has reported that clicking an Add button isn’t bringing up the Add form. A list of assumptions immediately comes to mind:

  1. A controller bound the Add button’s click event to a method.
  2. The method will open up the Add form when executed.
  3. The Add form will open up correctly when told to do so.

Each assumption should then be validated. If it turns out the assumption is valid, then the bug more than likely isn’t there. If it is invalid, then the bug is more than likely there. Some ways to validate the assumption are:

  1. Ensure that the method is actually getting called on click.
  2. Make sure the click event is spelled correctly.
  3. Check that the event is bound to the correct method.
  4. Test other click listeners to be sure they’re getting called.
  5. Is the Add form able to actually open?

Debugging an Enterprise-level application can be a ting task. There are so many different files and classes that it can be overwhelming to debug something like the issue above. The best part about validating assumptions is that it is actionable and concise. It limits the scope to just what is relevant, and provides real tests that can be ran to identify a problem quickly. Its effectiveness is only limited to how well the assumptions are defined, and how direct the validations are.

There’s no real trick to figuring out what the assumptions are. It’s something that takes time and practice. There are, however, several different techniques I use to validate my assumptions.

Binary Search

Most people, even if they aren’t programmers, use binary searches on a regular basis. When someone guesses a number and is given feedback of “higher” or “lower,” they are using a binary search to narrow down the solution. The idea behind a binary search is simple: split a data set into two, and find which half contains what you’re looking for.

The same concept can be applied to debugging. Assume I have a really long, complicated method that produces a bug. I need to find out where in the method the bug starts occurring. Rather than checking each and every line, I comment out the second half of the method. If the bug no longer happens, then I know it must be caused by something I commented out. I then comment out the first half, uncomment out the second half, and comment out the last fourth. If it still happens, I know the issue is in the beginning of the second half. This process can be repeated until the culprit line or expression is found. Imagine how much time would have been wasted had the first half been checked line by line. It may have yielded some results, but since the bug was in the second half there’s no reason to really consider the first.

The binary search technique is one that can be applied to any language. One disadvantage is that it makes the naive assumption that all methods are modular enough to run one section and produce the same result. There are often cases where a variable in the first half is used in the second half, so completely commenting out the first half isn’t an option. Binary search still allows large chunks of code to be ignored to find the root cause.

debugger Statement

Setting breakpoints to get the current call stack and local/global variable is a cornerstone to any debugging utility. JavaScript debuggers do allow breakpoints to be set when inspecting code. Most people, however, don’t know about the debugger statement.

The debugger statement allows you to define breakpoints as part of the code itself. If the same line needed to be inspected in multiple different browsers, it’s easier to put a debugger statement in the code than try to set the breakpoint in each individual developer tools.

To put a debugger statement in JavaScript code, simply do:

debugger;

I use debugger statements for a wide variety of uses. If I’m working on coding and need to setup stub methods to fill in later, I’ll add a debugger statement to remind myself to fill it in. I also don’t put white space to the left of those kind of debugging lines to make it easy to spot and correct before I check my code in to source control.

I’ve noted several times that the debugger statement is a statement, not an expression. This is because I’ve often seen people write:

if (this.someMethod() && this.someOtherMethod() && debugger && this.someOtherOtherMethod())

They want to see the call stack after someOtherMethod is executed, but don’t want to step through each previous method. The line above is invalid JavaScript syntax, and will throw a run-time exception. The valid version of the code uses an automatically executed closure:

if (this.someMethod() && this.someOtherMethod() && (function(){debugger;})() && this.someOtherOtherMethod())

It looks funky to non-JavaScript programmers, but it works.

I prefer debugger statements to setting breakpoints in the browser’s developer tools. If you set a breakpoint in a file in Chrome and it is loaded asynchronously, it will throw a breakpoint at the end of the file once it is loaded. This gets very annoying if you’ve put breakpoints in multiple files. Debugger statements don’t suffer this behavior. They also make it easier to compare behavior in two browsers at the same time.

Overview

In this blog, I’ve gone over the paradigm I use when debugging. I also discussed binary searching, which can be used in any language. The debugger statement allows for quicker debugging between browsers. In the next blog, I will go over top-down, bottom-up, and event listener breakpoints. These are slightly more advanced than the previous techniques, but are critical to effectively debugging complex JavaScript application.

— Zach Gardner, asktheteam@keyholesoftware.com

Advanced JavaScript Debugging Series:

  • Part 1 – Validate Your Assumptions, Binary Search, and the debugger statement
  • Part 2 – Bottom-Up debugging, Top-Down debugging, and Break on DOM changes
  • Part 3 – Chrome-specific debugging techniques
  • Part 4 – Coming Soon – how teams that use Agile can help their developers and QAs debug JavaScript effectively
  • Share:

7 Responses to “Advanced Debugging Techniques in JavaScript – Part 1”

  1. Silon says:

    I was expecting something on debugging, and was disappointed to find the article was just a load of newbie crap.

    • Keyhole Software says:

      Hi Silon,

      There are many who don’t understand the fundamentals of debugging. This post was a foundation that the rest of the techniques will build off of – Part 2 will have more JavaScript-specific techniques, planned to be published February 10th. Thanks for reading.

  2. […] my previous post on advanced debugging techniques in JavaScript, I spelled out the idea of validating assumptions. This is the most important concept when it comes […]

  3. […] is the third part in my series on Advanced Debugging Techniques in JavaScript. Part 1 introduced Validate Your Assumptions, Binary Search, and the debugger statement. Part 2 covered […]

  4. […] This was originally published in the Keyhole Software blog on 1/6/2014. […]

  5. […] I got to May 1st, 2014. The bug occurred in this version, but not in the April 1st, 2014 version. Using the same principle to my Binary Search JavaScript debugging technique, I tried the April 15th, 2014 version. The bug did not occur, so I know it was somewhere between […]

Leave a Reply

Things Twitter is Talking About
  • .@NebraskaCC is just 2 weeks away & tickets are still available! #KC developers: Lincoln is just a quick 3-hour drive away. Well worth it!
    March 3, 2015 at 10:59 AM
  • Happy Punday from the Keyhole team! :-) We hope you're having a great day. http://t.co/p0iDzAY9qL
    March 2, 2015 at 2:54 PM
  • There's a new post on the Keyhole dev blog from @joshuarob01 - Agile Team Member Anti-Patterns http://t.co/2nfYQNIkP0 #agile
    March 2, 2015 at 10:57 AM
  • Heard of #GrokOla yet? Q&A with our expert dev team + code-sensitive wiki for tribal knowledge http://t.co/oCITNW9xEf http://t.co/61dIP4Q4jE
    February 27, 2015 at 1:38 PM
  • Rapid appdev has a bad rep, but there are ways to bring development time down the right way. Don't Fear the Rapid - http://t.co/8CKhAzmysb
    February 27, 2015 at 1:05 PM
  • RT @DZoneLinks: Swift 1.2 Arrives: 13 New Features - http://t.co/07q5vavZsT - @DZoneLinks Big Link by mswatcher
    February 26, 2015 at 2:17 PM
  • Our GrokStars are at it again - they've released a free #GrokOla primer. Get to know Java Lambdas: http://t.co/D2iLLj8mph
    February 26, 2015 at 9:13 AM
  • RT @dbgrandi: OH: “Do programmers have any specific superstitions?” “Yeah, but we call them best practices.”
    February 25, 2015 at 6:05 PM
  • New Primer: Introduction to the #Backbonejs MVC Framework - http://t.co/VLRJ4b5fwj Free #GrokOla tutorial available to the public.
    February 25, 2015 at 4:26 PM
  • #RabbitMQ: messaging software built on AMQP protocol. Learn relevant concepts & how to avoid common "gotchas" here: http://t.co/ZwMXlhspJ0
    February 25, 2015 at 3:20 PM
  • #Java is OO but contains non-object primitives. Autoboxing feels more like a band-aid. Do primitives need to go? http://t.co/A8ChCBHXJO
    February 25, 2015 at 1:44 PM
  • We're excited for Tech Night tonight! @bricemciver will present to the team on Leaflet.js in preparation for his @nebraskacc talk. Lucky us!
    February 24, 2015 at 4:15 PM
  • Do Primitives need to go in enterprise apps? - http://t.co/A8ChCBqmle New #Java post on the Keyhole blog.
    February 24, 2015 at 3:31 PM
  • When you pair #JAXB & #JPA, you can expect some "gotchas." Here are techniques to help you overcome the hurdles - http://t.co/J1s5DpcsCp
    February 24, 2015 at 8:15 AM
  • Do Primitives Need To Go? - http://t.co/A8ChCBHXJO New #Java post on the Keyhole blog by @jhoestje
    February 23, 2015 at 10:44 AM
  • New to #JavaScript prototypal inheritance? Here are some notes to help you along the way - http://t.co/NTIDZS6Uhy
    February 20, 2015 at 12:10 PM
  • XML Manipulation With XML Copy Editor: http://t.co/iHHmyAUQqU Good, free tool for when you need to manipulate an #XML document directly.
    February 20, 2015 at 10:35 AM
  • We've been releasing some free #Grokola tutorials. See them all in one spot - http://t.co/WDt5fWa728 #JavaScript #Backbonejs #nodejs #java
    February 19, 2015 at 2:42 PM
  • Code For Maintainability So The Next Developer Doesn't Hate You - http://t.co/iG2wW2rSWj Eight helpful tips to do so.
    February 19, 2015 at 11:20 AM
  • Functional Reactive Programing & #JavaScript offer an elegant way to reduce complexity of time-varying events. Intro: http://t.co/YGSsz5e0xN
    February 18, 2015 at 3:15 PM
Keyhole Software
8900 State Line Road, Suite 455
Leawood, KS 66206
ph: 877-521-7769
© 2015 Keyhole Software, LLC. All rights reserved.