Unless you’re Chuck Norris you need a code style guide. Read on to learn JSCS — JavaScript Code Style.

Intro

This is the second article in the series about tools that will help you keep code in order. In the last article, Emberocop to safeguard your code—intro I listed tools and explained why consistency matters. Today I’m going to take a closer look at JSCS—JavaScript Code Style.

I encourage you to read the first part before if you haven’t yet. Are you ready?

What is code style guide?

Code style guide is a set of rules that a project contributor should abide by. For sure no guide, I hope, is a whim of a code syntax nazi. It’s meant to keep consistent, maintainable and pleasant to work with code in projects.

Now better take:

A style guide or style manual is a set of standards for the writing and design of code. The implementation of a style guide provides uniformity in code style and formatting, often covering guidelines regarding indentation (tabs vs. spaces), variable and function naming conventions, where best to apply whitespace and so on.
JavaScript Style Guides And Beautifiers by Addy Osmani

‘Consistent, maintainable and pleasant to work with’? Are you kidding me?! Give me concretes!

Sure:

  • Discussions about style during code review is a waste of time
  • You can onboard new contributors faster

Every developer has habits and preferred way of writing code. Without any rules no one would care about style, and what’s worse, code review would be flooded with comments like:

  • ‘Cut redundant empty line’ / :scissors:
  • ‘Replace single quotes with double quotes’
  • ‘This line is too long’
  • ‘Missing trailing comma
  • etc.

Things that you could delegate to a tool and let a developer code. ‘Manual linting’ is time-consuming for both parties: the coder and the reviewer.

All code in any code-base should look like a single person typed it, no matter how many people contributed.
Principles of Writing Consistent, Idiomatic JavaScript

Code style guide also helps onboarding new developers on the project. One just runs npm install that will install necessary dependencies, linting tools included, and before pushing code, npm test will show him offences1.

So, I don’t have to do manual linting? Nope2.

Manual linting is soo 1993!

Years ago (not precisely 1993), I was using jQuery JavaScript Style Guide. Perhaps there were no tools like JSCS at that time as I was trying to follow it ‘manually’.

Now with tools like JSCS you don’t have to worry about forgetting rules—even if you do, the linter will tell you how many times you offended it.

You will get into a habit to code ‘the right way’ with time, which entails some positive side effects.

JSCS—JavaScript Code Style Linter

JSCS is a code style linter/formatter for programmatically enforcing your style guide. You can configure JSCS for your project/company using over 150 validation rules, including presets from popular style guides like jQuery, Airbnb, Google, and more.
JSCS—JavaScript Code Style site

3 guys, 3 approaches, 3 editors, 1 project. I’ve always been kind of ‘-nazi’ or perfectionism inclined follower so it was only a matter of time when I started to look for tools that would keep code in the project I work for, in order.

Some time ago Dawid, the other team member, showed me how useful RuboCop is. Naturally I started to look from a similar solution for JavaScript.

RuboCop—looking for similar solution

RuboCop makes easy:

  • Checking for stylistics problems in your code
  • Checking for possible errors and very bad practices in your code
  • Checking code complexity and helping you with refactoring it
  • Fixing unambiguous RuboCop offences automatically

For JavaScript I had to use more tools to have the same effect, but I’m sure that a comprehensive solution may exist that cover all of them. If you know such a tool, let me know in the comments section below!

Today let’s focus on the first point—Checking for stylistics problems in your code as it can be achieved with JSCS.

Ember.js JSCS preset

First I looked up what Ember.js team uses for code style guide and figured out, that it is JSCS, by looking into their .jscsrc config file.

To have a good start, I decided to use that config. Comparing it with Ember Suave config (more below), Ember.js config, with lots of customization, seemed too complex. Thus I asked a question on Ember.js Discussion Forum what JSCS preset is suitable for regular Ember.js projects. The answer came shortly after:

I would suggest using ember-suave as your preset (but I’m biased 😃).

And so I did! Thanks Robert Jackson (@rwjblue)!

Ember Suave with customizations

Ensures super stylish code by enforcing the DockYard JavaScript and Ember style guide rules.
Ember Suave repo in GitHub

Setup was much simpler and with small adjustments the final config looks as follows:

{
  "preset": "ember-suave",
  "requireTemplateStringsForConcatenation": null,
  "requireTrailingComma": {
    "ignoreSingleLine": true
  },
  "disallowTrailingComma": false
}

When you’re introducing style guide to existing code base, the natural question arises—what kind of trade-offs can be made when existing, unwritten rules go against those defined in the JSCS preset? Let’s see!

Follow or break the rules?

The answer is run-of-the-mill: it depends.

Overriding preset rules

Without style guide some unwritten rules have already been set implicitly. Some could caught up, some not. The issue is that they can stand up against default preset that you have chosen.

Does it mean that you should follow blindly the default rules, and adjust the existing code base? Not exactly. Sometimes it’s cheaper to embrace what’s already in use.

In our project, Maciek, thanks to the JSCS linter for Atom was adding, prompted by the plug-in, trailing commas, which, by default, Ember-Suave does not allow for.

To have a taste of that past experience and show you the trade-offs I made, I used a way-back machine. Machine—commonly called Git–allowed me to checked out to the merge commit before support for JSCS had been merged into master branch, and deployed.

Running:

$ jscs --esnext app/ --max-errors=500
➜ 114 code style errors found

Brought 114 errors.

I decided to follow Maciek advice: this is how we do it now and embrace the current rule rather than follow the preset strictly.

In a team work, what does matter, is making trade-offs. Collaboration is far more important than acting like the ultimate source of knowledge.

Build projects around motivated individuals. Give them the environment and support they need, and trust them to get the job done.
Principles behind the Agile Manifesto

Let me, for reference purposes, list rules we embraced:

Ignoring is strength

The same idea of making trade-offs applies to ignoring rules if it’s faster and cheaper than rewriting or refactoring the code.

This is how jscs runs in our project:

// package.json
"scripts": {
  "jscs": "jscs -e app/ && jscs -e tests/",
  "test": "npm run jscs && npm run jshint && npm run…"
}

As you can see jscs runs only for JavaScript files under app/ and tests/ directories, places where only application code should reside (no 3rd party libraries). Yet, some of them require that you use style that JSCS treats as an ‘offence’.

Here’s the example of setup Bootstrap Notify.

// jscs: disable
Ember.$.notifyDefaults({
  element: rootElement,
  mouse_over: 'pause',
  placement: {
    from: 'bottom',
  },
// jscs: enable
 some more code

According to JSCS, mouse_over should become mouseOver, which on the one hand, would be possible with a wrapper object, but, on the other hand would be a waste of time and money.

Disabling can also be turned on the line level:

let token = transition.queryParams.token; // jscs: disable

The example above is also a gentle introduction for another important topic what to pay attention to when fixing offences with --fix option. I’ll cover that topic below.

Takeaway

  • Override preset rules if it takes less time (and money)
  • Don’t hesitate to disable rules if it takes…

Automatic fixes with --fix option

Let’s get back to automatic fixes I mentioned in Manual linting is soo 1993!. Remember that we still have 114 errors to fix?

It’s time to get our hands dirty!

$ jscs --esnext app/ --max-errors=500 --fix
➜ 79 code style errors found.

35 gone. 79 to go. 30% of the job done with no effort of our own. Now let’s see what kind of complaints the pending errors are:

$ jscs --esnext --max-errors=500 --reporter=summary app/
┌─────────────────────────────────────────────────┬────────────┬──────────────────┐
│                      Rule                       │Total Errors│Files With Errors │
├─────────────────────────────────────────────────┼────────────┼──────────────────┤
│                   disallowVar                   │     48     │        17        │
├─────────────────────────────────────────────────┼────────────┼──────────────────┤
│          requireEnhancedObjectLiterals          │     26     │        15        │
├─────────────────────────────────────────────────┼────────────┼──────────────────┤
│           requireObjectDestructuring            │     2      │        2         │
├─────────────────────────────────────────────────┼────────────┼──────────────────┤
│       requireParenthesesAroundArrowParam        │     2      │        2         │
├─────────────────────────────────────────────────┼────────────┼──────────────────┤
│     requireCamelCaseOrUpperCaseIdentifiers      │     1      │        1         │
├─────────────────────────────────────────────────┼────────────┼──────────────────┤
│                       All                       │     79     │        37        │
└─────────────────────────────────────────────────┴────────────┴──────────────────┘

Two type of errors prevails:

  • disallowVar: 48
  • requireEnhancedObjectLiterals: 26

Let is new var

Generally in ES6, each var should be replaced with let. Our job is only a matter of find and replace it on the project level. This is how I did that in Vim.

First, I assured myself that all tests pass with npm test. They did so replacing var with let was a butter and cheese, taking me less than 30 seconds.

Sugar, sugar…

The second warning: requireEnhancedObjectLiterals wanted me to replace: user: user with just user, which is a nice Syntactic Sugar courtesy of ES6. The change also didn’t take long to fix.

A hidden trap—requireObjectDestructuring

In spite of the fact that there were only 2 errors of that type, one of them was a nifty trap. According to requireObjectDestructuring error definition I had to replace:

let beforeSend = hash.beforeSend;
let { beforeSend } = hash.beforeSend;

This is the error message with a context:

requireObjectDestructuring: Property assignments should use destructuring at app/adapters/application.js:
    20 |    }
    21 |
    22 |    let beforeSend = hash.beforeSend;
------------^
    23 |    hash.beforeSend = function(xhr) {
    24 |      xhr.setRequestHeader('Accept', contentType);

Unfortunately I couldn’t as hash.beforeSend was a function that overwrote default DataAdapterMixin from Ember Simple Auth. This was at least what I knew at that time.

Now, as of this writing and using the way-back machine in retrospect, I realized that instead of original solution—by ignoring line:

let beforeSend = hash.beforeSend; // jscs:ignore
hash.beforeSend = function(xhr) {}

I could have fixed it the right way:

let { beforeSend } = hash;
hash.beforeSend = (xhr) => {

that is, what original solution did. One lesson learnt.

Takeaway

--fix definitely speeds up the process of embracing JSCS. Still you have to be careful and apart from running tests, review the changes in the surrounding context. If you keep your methods (context) short, you spend less time to figure out if, for example, var can be replaced with let in this place.

Let me quote Addy Osmani to support this:

Use short, meaningful names for variables, functions and modules. This can help reduce the need for detailed inline comments if it means a developer can instantly grasp the purpose of a piece of code.
JavaScript Style Guides And Beautifiers by Addy Osmani

ES6 syntax is still new for many, and getting used to it can take time, especially when you were working with CoffeeScipt for months.

JSCS support in your editor

JSCS can also be run as a plug-in in an editor or an IDE. Here’s the list of plug-ins for most popular editors.

I strongly recommend you getting a plug-in for your editor, as it has some benefits:

  • You don’t have to wait for jscs linting result
  • You can fix complaints on the go
  • With each prompt you get into the habit how to write code the right way

Resources

Summary

Part of being a good steward to a successful project is realizing that writing code for yourself is a Bad Idea™. If thousands of people are using your code, then write your code for maximum clarity, not your personal preference of how to get clever within the spec.
—Idan Gazit
Principles of Writing Consistent, Idiomatic JavaScript

This part turned out to be longer than I planned. If at least one reader3 will find it useful, it was worth it.

And the final takeaway is:

  • Code style guide is your ally, not enemy
  • It saves time, money and pointless arguments over style
  • Start with a preset of rules and don’t hesitate to adjust them

Above all:

Arguments over style are pointless. There should be a style guide, and you should follow it
—Rebecca Murphey
Source: Principles of Writing Consistent, Idiomatic JavaScript


Thanks Szymon for your feedback to this article!

  1. The term comes from RuboCop linter warnings, and I’ll use it in this series

  2. Head First book series by O’Reilly has been one of the best experiences I had with technical books; maybe next time I’ll introduce some fireside chats? :)

  3. I knew that rule of self-deprecation existed!