Telerik blogs
quality_header

This series has discussed tools that help developers and companies deploy software with good quality code by automatically perform checks on different areas of front end development. Part 1 introduced the "Musketeer principle" (i.e. a developer is one element of a team and should collaborate to achieve the common goal, but the team should code as if it was made of only one developer) and showed how to automatically check HTML code quality. Part 2 explored options for automatically checking CSS and Sass code.

In this part, we'll look at ways we can automatically check JavaScript code for style and quality, as well as an option for testing accessibility.

JavaScript

Linting CSS and Sass is relatively straightforward because there aren't concepts like cyclomatic complexity, unit testing, time complexity and space complexity, and many others in play. Since JavaScript is a programming language, things get much more complex. You not only want to pay attention to the code style adopted but also to ensure that poor quality code is detected and improved at an early stage.

Fixing JavaScript code style issues

Compared to CSS and Sass, JavaScript has more features (such as methods to work with dates) and a very complex syntax (think about the changes introduced by ECMAScript 2015 and 2016). In addition, JavaScript offers more variations for features than something like Sass supports - for instance, functions.

JavaScript functions can be anonymous or named, inline or assigned to a variable or assigned to an object's property (a method). For this reason, achieving a consistent code style is harder because there are so many ways the code can diverge. To solve this problem you can use a Grunt plugin called grunt-jscs.

grunt-jscs checks a project's JavaScript code style and it uses JSCS behind the scene. This Grunt plugin is actually just a wrapper for JSCS. So, in the remainder of this section I'll refer to the features available as JSCS features when describing them.

To date, JSCS supports more than 150 rules and the team works constantly to add even more to help you in keeping your JavaScript source consistent. This tool supports ECMAScript 2015, JSX, Flow, and much more. It's very stable and reliable, and it's trusted by the jQuery team, Adobe, the Bootstrap team, the Wikimedia foundation, and many others. JSCS ensures the success of a team in adhering to "The musketeers" principle.

Some of the rules available are:

  • disallowAnonymousFunctions: requires function expressions to be named;
  • disallowDanglingUnderscores: disallows identifiers that start or end in _;
  • requireDotNotation: requires member expressions to use dot notation when possible;
  • requireMultipleVarDecl: requires multiple var declaration;
  • requireParenthesesAroundIIFE: requires parentheses around immediately invoked function expressions;
  • validateIndentation: validates indentation for switch statements and block statements.

The complete list of rules available can be found on the JSCS's website.

Among all the features JSCS provides, the following are the ones that I love:

  • It comes with preset configurations;
  • It automatically creates your configuration based on the closet preset configuration;
  • It automatically fixes most of the errors found.

As I mentioned, JSCS supports more than 150 rules. This means that creating a configuration file from scratch can be time-consuming. In addition, unless you want to purposely disappoint some members of the team, you should ask the opinion of all the members for each available rule. You can easily see how this situation can quickly get out of control.

To avoid this problem, you can adopt one of the preset configurations that comes with JSCS. They are created and adopted by some well-known companies and teams such as the jQuery team, AirBnb, Google, and Grunt. You can find a list of all the available preset configurations on the JSCS's website.

There may be times when a team finds that most of the developers are following the same conventions and those conventions are different from the available preset configurations. In such cases, the team can create a custom configuration starting from a preset one.

The tool provides a feature that analyzes a code base and suggests the preset configuration that is the closest to the code's style. Once an option is selected, the tool guides the user in tweaking the settings to match the style used. By doing so, the number of error messages raised by JSCS is heavily reduced when it's integrated into the project. Therefore, fixing the remaining issues is much faster.

As if it wasn't already enough, JSCS provides a feature that can automatically fix most of the issues detected. Let's say that in a project the team decides to use 3-spaces indentation and a space before and after the assignment operator (=). Now, imagine that not everyone in the team is following these conventions. Instead of employing JSCS only to find where the inconsistencies reside, the team can use the fix feature to automatically fix them. The developers would have only to take care of those few issues left. This will save the whole team a lot of time and frustration.

Now that you should have a clear idea of the power of grunt-jscs, let's see a more complex example. To start, let's install install grunt-jscs:

npm install grunt-jscs --save-dev

Once installed, we have to configure it. The following snippet creates a task that analyzes all the JavaScript files in a folder called "scripts". The definition of the rules to follow is saved in an external file called .jscsrc which uses the JSON format.

jscs: {
   options: {
      config: '.jscsrc'
   },
   app: {
      src: 'scripts/*.js'
   }
}

With the configuration in place, suppose that you have a file called main.js, stored in the scripts folder with the following content:

'use strict';

function foo() {
   var sum = 0;

   obj = {
      test: "Hello!",
      some: 'thing'
   }

   for(var i = 0; i < 10; i++)
   {
      sum+=i;
   }

   console.log(sum);

   for(var key in obj) {
      console.log( 'key: ' + key + ' and value:'+obj[key]);
   }
}

foo();

By executing grunt-jscs we obtain the following report:

grunt-jscs output example

Now, imagine you want to automatically fix the issues found wherever possible (this is one of the points of this article after all) and to analyze code that is written using ECMAScript 2015. To do that, you have to update the options passed to grunt-jscs as follows:

jscs: {
   options: {
      config: '.jscsrc',
      esnext: true,
      fix: true
   },
   app: {
      src: 'scripts/*.js'
   }
}

As a final note, keep in mind that if a code style issue is automatically fixed by JSCS, it isn't reported at all.

The future of JSCS

With a blog post published last month on Medium Oleg Gaidarenko described what the future of JSCS looks like. The post contained two main announcements: the release of JSCS version 3 and the fact that version 3 will be the last. For the next few months, the team behind JSCS will continue supporting the project but no new features will be implemented.

The final goal, and this is the good news, is that the JSCS and the ESLint projects will be merged into one. This means that more contributors will work on a single code base, thus you can expect more features and bug fixes in a shorter period of time. Oleg also stated that the JSCS team is working with the ESLint team to create tools and processes to make the transition from one tool to the other as easy as possible.

With the JavaScript style issues fixed, it's time to understand how to detect poor code quality automatically.

Detecting JavaScript code quality issues

Up to this point I've focused mostly on tasks that detect and fix code style issues. When it comes to JavaScript, code quality is even more important, yet often subjective. What's considered good quality code for someone might not be true for others. The evaluation is dependent upon the experience, skills, and preferences of the judge. In this section I'll discuss a Grunt plugin that relies on commonly accepted conventions (that you can tweak to fit your needs) to detect potential issues. The plugin I'm talking about is called grunt-contrib-jshint.

grunt-contrib-jshint helps detect errors and potential problems in JavaScript code. It uses JSHint behind the scenes. Just like grunt-jscs, this plugin is simply a wrapper around JSHint. For this reason, in the remainder of this section I'll present some features referring to them as JSHint features.

JSHint is a static code analysis tool employed by companies and foundations such as jQuery, Mozilla, Yahoo!, and many others. Being a static code analysis tool, it can spot several different kind of mistakes, but it can't detect all software problems like a function that isn't working as expected or isn't fast enough. For such situations, you have to employ unit and functional tests.

An interesting fact about JSHint is that according to its team:

only 15% of all programs linted on jshint.com pass the JSHint checks. In all other cases, JSHint finds some red flags that could've been bugs or potential problems.

The take away lesson here is: don't underestimate the potential issues your code might have.

This tool offers several settings. Some examples are:

  • forin: requires all for...in loops to filter object's items using the hasOwnProperty() method;
  • eqeqeq: prohibits the use of == and != in favor of === and !==;
  • latedef: prohibits the use of a variable before it was defined;
  • maxstatements: sets the maximum number of statements allowed per function;
  • nocomma: prohibits the use of the comma operator;
  • unused: warns when a variable is defined but never used.

The complete list of rules is listed on the JSHint's website.

I find JSHint very useful for improving the quality and maintainability of the projects I work on, but of all the features it provides I particularly love maxcomplexity, maxdepth, and maxparams.

maxcomplexity specifies the maximum cyclomatic complexity value the code can have. This helps in keeping functions short and focused on one task. If a function has a high cyclomatic complexity value, it means that the function is too complex. So, it needs to be refactored. By employing maxcomplexity wisely, developers can make their code adhere to the single responsibility principle (SRP).

maxparams defines the maximum number of formal parameters allowed per function. A function having too many parameters, several of which may be optional, is hard to call and to manage. For cases like this it's often better to have only one argument that is an object.

The last option I want to describe is maxdepth. It allows you to control how many nested blocks of code a developer can write. If the code of a function is too nested, it's usually harder to read and to understand. A better solution is to refactor it.

grunt-contrib-jshint can be installed via npm as shown below:

npm install grunt-contrib-jshint --save-dev

Like the other Grunt plugins I've introduced so far, a basic configuration can be defined with few lines. In the next example, I'll request grunt-contrib-jshint to analyze all of the JavaScript files in a folder called "scripts". In addition, the configuration created is stored in an external file called .jshintrc which uses the JSON format.

jshint: {
   options: {
      jshintrc: '.jshintrc'
   },
   app: {
      src: 'scripts/*.js'
   }
}

To demonstrate how JSHint works and the type of reports it offers, take a look at the following report:

grunt-contrib-jshint output example

By integrating both grunt-jscs and grunt-contrib-jshint into a team's workflow, the team is able to improve the overall quality of the JavaScript code.

Before concluding the article, there's one last topic I want to discuss.

Accessibility

With the tasks discussed so far, a team is able to put sanity in the HTML, CSS, Sass, and JavaScript code of a project. Nowadays there's another crucial aspect that developers must take into account: accessibility. Accessibility is one of those areas that require manual testing for an in-depth evaluation. However, a team can still automate the minimal checks to achieve a decent base without much effort. This, in turn, leads to a further improvement of the overall project quality.

On March 1, 2015, a new tool that promised to automate accessibility tests was official released to the public called Tenon. Tenon can identify 508 and WCAG 2.0 issues on web pages in any environment. On the tool's website there is a demo that lets you enter a URL to verify if it has accessibility issues. An example of a report generated, in this case by analyzing yahoo.com, looks like the image below:

tenon output example

The good news about Tenon is that there's a Grunt plugin for it named grunt-tenon-client. The bad news is that Tenon costs money. It doesn't have a free version, even for open source projects, but it does offer a 30-day free trial. Despite the fact that it costs money, I still wanted to mention it because I think Tenon works really well and it can add a lot of value to any web project.

This task can be installed with the command shown below:

npm install grunt-tenon-client --save-dev

To learn more about it, I suggest reading the task page on GitHub and the Tenon documentation.

Conclusion

In this article, I've introduced you to several Grunt plugins and tools that allow you to improve the code quality of a web project. While many people understand why code quality matters, the same isn't true for code style. So, at the beginning of this article I discussed the benefits of using the same conventions throughout a project.

I also presented a concept called "The musketeers" principle, which is a term coined by me that outlines how crucial it is for every developer to be part of a team and to collaborate to achieve the common goal while, at the same time, how the team should write code as if it was made of a single developer.

After discussing the importance of these concepts, I dissected the main areas of front-end development: HTML, CSS and Sass, and JavaScript. For each of these areas I highlighted the challenges a team deals with to maintain a high-quality and consistent code base considering the variety of skills and experience of its members. Then, I outlined what solutions the team can adopt to solve these problems automatically by employing Grunt (or similar tools) and some plugins made for it. Finally, I discussed bonus topic on dealing with basic accessibility issues.

In case you want a quick reminder of the tasks I've covered in this tutorial, they are:

  • grunt-html: parses one or more HTML files and validate them against the HTML specifications of the W3C, reporting any error found
  • grunt-contrib-csslint: lints CSS files searching for problematic code
  • grunt-scss-lint: lints SCSS files searching for code style issues and more
  • grunt-jscs: parses JavaScript files to search for divergences in the code style
  • grunt-contrib-jshint: detects errors and potential problems of JavaScript code
  • grunt-tenon-client: identifies 508 and WCAG 2.0 issues of web pages

As stated at the beginning, this article is extracted by a talk I gave in Tallinn. If you want, you can take a look at the slides or the video of the presentation.

I hope this article has offered some useful tips on how you, as a member of a team, can improve the workflow of the team itself and how to automate many tasks related to code quality and style of a web project.


Telerik Blogging Ninja
About the Author

Aurelio De Rosa

Aurelio is a (full-stack) web and app developer with more than 5 years experience programming for the web using HTML5, CSS3, JavaScript and PHP. His interests also include web security, web accessibility, SEO and WordPress. He's the author of the books jQuery in Action and Instant jQuery Selectors. You can find him on GitHub here.

Related Posts

Comments

Comments are disabled in preview mode.