Style Checking (linting) Node.js Apps

Style checking (aka linting) is a vital part of any application development process. Sloppy coding practices increase the chances of coding errors and other problems later on, and style checking can help flag many coding problems to keep your code clean. Why is it so important to keep your code clean and uniform? Simple: While you are building a system, you create a mental model of that system-uniform style helps reduce the cognitive effort required to translate the code into your mental model. It’s less taxing on your brain! Consequently, you have thought power to apply to what you’re trying to build, and you’re more likely to build something that works properly.

For node.js, I use the jshint tool. For grunt integration I use grunt-contrib-jshint. The gruntfile entry looks like this:


jshint: {
all: {
src: ['app/**/*.js', '!app/tests/**'],
options: {
//reporter: 'checkstyle',
jshintrc: true
}
}
}

Look at the src: element. The first entry tells jshint to look for all js files in all subdirectories of app, while the second entry tells jshint to skip my tests directory (and subdirectories).

Now look at jshintrc: true — that tells jshint that there is a file .jshintrc in the app’s root directory that contains configuration parameters. Here’s a jshintrc file:

{
"quotmark": "single", // Define quotes to string values.
"bitwise": true, // Prohibit bitwise operators (&, |, ^, etc.).
"noempty": true, // Prohibit use of empty blocks.
"curly": true, // Require {} for every new block or scope.
"eqeqeq": true, // Require triple equals i.e. `===`.
"smarttabs": true, // Suppresses warnings about mixed tabs and spaces
"trailing": true, // Prohibit trailing whitespaces.
"unused": true, // Warn unused variables.
"immed": true, // Require immediate invocations to be wrapped in parens e.g. `( function(){}() );`
"latedef": "nofunc", // Prohibit variable use before definition.
"newcap": true, // Require capitalization of all constructor functions e.g. `new F()`.
"noarg": true, // Prohibit use of `arguments.caller` and `arguments.callee`.
"regexp": true, // Prohibit `.` and `[^...]` in regular expressions.
"undef": true, // Require all non-global variables be declared before they are used.
"camelcase": false, // Permit only camelcase for `var` and `object indexes`.
"globals": { // Globals variables.
"jasmine": true,
"angular": true,
"ApplicationConfiguration": true
},
"predef": [ // Extra globals.
"define",
"require",
"exports",
"module",
"describe",
"before",
"beforeEach",
"after",
"afterEach",
"it",
"inject",
"expect"
],
"node": true, // Enable globals available when code is running inside of the NodeJS runtime environment.
"strict": true, // Require `use strict` pragma in every file.
"browser": true, // Standard browser globals e.g. `window`, `document`.
"esnext": true, // Allow ES.next specific features such as `const` and `let`.
"devel": true, // Allow development statements e.g. `console.log();`.
"indent": 4 // Specify indentation spacing
}

If you didn’t use jshint from the very beginning, you’re in for a big surprise when you first run jshint. Don’t panic!
1) In the .jshintrc file, set to false all of the entries after quotmark up to globals.
2) Run lint and fix the problems that show up.
3) Set one of the entries to true.
4) Repeat steps 2 & 3, working your way through until you’ve corrected all of your code.

camelcase comes last, because there are side-effects–you have to change multiple lines at once and make sure that you’re not causing other issues–like renaming a variable to a variable that’s already defined. Another trouble spot is if you’re preparing a json structure and sending that to the client–you have to change the client code (eg: angular templates, etc.) that’s processing that json at the same time. If you have unit tests defined, this is a good time to use them liberally.

The reason why I suggest following the above and fixing one type of problem throughout your codebase and then moving on to the next problem is that it lets you focus on making one type of change, then a different type of change, etc. Your mind can focus on just the one thing. If you want to correct all issues in one module before moving on to the next, change the src: entry so that only one module is linted at a time. Otherwise, the output is difficult to read, and you could end up making a change in the wrong module.

Global settings will only get you so far. There will come a point where you want to permanently ignore a specific warning for a specific line of code. Let’s take “strict”: true, for example. I have a few modules where I assign things to ‘this’:


function myFunction(task) {
this.key = task.key;
this.userId = task.userId;
this.name = task.name;
...
}

Assigning to ‘this’ will generate a strict violation, but I am OK with that here! You can suppress a warning by doing the following:
1) In gruntfile.js, uncomment the reporter: ‘checkstyle’ entry.
2) Run your lint task.
3) The output is difficult to read, but each entry will include a warning code at the end, eg: W040.
4) In the source code in which you want to suppress this specific warning, add: /* jshint -W040 */
5) To re-enable this warning elsewhere in that same module, add: /* jshint +W040 */. Try to limit the scope of these suppressions.
6) No other module is affected by these hints.

Advertisements

About jeffmershon

Director of Program Management at SiriusXM.
This entry was posted in Software and tagged , . Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s