April 30, 2015

April 10, 2015

Please reload

Recent Posts

I'm busy working on my blog posts. Watch this space!

Please reload

Featured Posts

Why use JSLint?

October 1, 2012

 

Why use JSLint?

http://www.jslint.com/

JSlint is a Javascript parser and code quality checker. It was created by Douglas Crockford, who also created the official JSON data standard.

It will warn us if we use features of Javascript which are problematic, and if the variables we use in a function don't match the variables we declared, and if we accidentally leave a dangling comma at the end of an array or object literal. It also checks for style and formatting issues.

Its behavior is configurable, and there are a lot of options to configure, so if we aren't careful we will end up with quite a few warnings to deal with, and many of them will not lead directly to fixing bugs. For an existing codebase that has never used it before, it would be a good idea to turn off almost all the checks at first, and then turn them on one at a time when the development schedule allows it.

And of course we are probably going to want it to run automatically on all Javascript files after we make changes, as pasting our code manually into a form on a Web page isn't very convenient. So once we have decided to use it, we need to create a plan for how to use it. But that is a topic for another time. For now, let's look at an example of a realistic bug that JSLint can help us find before the code makes it to production.

The example is a bit contrived for the sake of simplicity, but it is our experience that JSLint has found real bugs that would have otherwise been missed.

Javascript doesn't have a built-in average function, so if we need one we have to write one. It should ignore empty strings, and it should work whether the elements of the array are proper numbers or numerical strings such as "5.5", and it should do something reasonable if we pass in an empty array. We assume the array has been validated, and it contains either numbers, or numerical strings, or empty strings, and nothing else.
function average(arr) {
var i, n, sum;
sum = 0;
n = 0;
for (i = 0; i < arr.length; i++) {
if (arr[i] != "") {
sum += +arr[i];
n++;
}
}
return n == 0 ? 0 : sum / n;
}

Of course we wouldn't want to deploy this code without testing it, so we write some tests, which all pass.

average([]) == 0 OK
average([1, 2, 3]) == 2 OK
average(["1", "2", "3"]) == 2 OK
average(["1", "2", "3", ""]) == 2 OK

But our function contains a very serious bug, and our test suite doesn't catch it. Later we find this reduced test case:

average([0, 2]) == 2 FAIL, EXPECT 1

The problem, of course, is that in Javascript the expression 0 != ""
evaluates as false, so 0 gets ignored in the computation the same way ""
does. So we can fix the bug by replacing != with !==, and for good measure we also replace == with ===, and that fixes the bug. We also expand the test suite to test arrays which contain 0.

OK, so we have some confidence that our average function is now correct.

But what if there are similar mistakes elsewhere in our code? What if we make the same mistake again somewhere else in the future? Ideally, we want this kind of thing to get checked automatically when we prepare to deploy our code, or maybe every time we check new code in to the version control system.

Now of course we could create our own checker which uses regular expressions to look for use of != and ==. But we probably also want to check for other things, like misspelled variable names and stray commas at the end of arrays, etc. Those are very difficult to look for using regular expressions, so we really need a proper Javascript parser such as the one in JSLint.

Obviously JSLint cannot find all bugs, and like other static analysis tools it doesn't replace a runtime test suite. But unlike a test suite, it doesn't need to be rewritten when our code changes or when we add new features. Once we have it integrated into our code management and deployment process, it requires very little direct maintenance.

We will of course have to get existing code to pass, and depending on how many options we have enabled, that could be a nontrivial amount of work, some of which may be just reformatting. It can also happen that JSLint's checks become more strict in the future, so that existing code which used to pass no longer does. Thus we may incur some maintenance costs when upgrading to a newer version of JSLint. Of course new versions may also help find bugs that old versions could not.

Overall, given the advantages and disadvantages, we have found at Third Defense that JSLint is a valuable tool, and no Javascript is deployed to production until it passes. We have around 25,000 lines of Javascript spread over 145 different files, and it is nice to know that, at the very least, each line conforms to a minimal standard of clarity.

JKL

Share on Facebook
Share on Twitter
Please reload

Follow Us

I'm busy working on my blog posts. Watch this space!

Please reload

Search By Tags