Friday, March 23, 2012

Braceless Programming

During the Software Passion Summit in Gothenburg, I had the privilege to talk to Douglas Crockford, the grandfather of Javascript and the creator of JSON and JSLint

While I think that JSLint is an awesome tool, I also think that it is too opinionated and therefore I use JSHint, an alternative that allows me to tweak more of the parameters to fit my style of coding. Douglas think that this is sacrilege, but I disagree. There are two major things I disagree with in JSLint and they are:

  1. I must have braces for every conditional and loop statement. I don't like this, I want my code to look as clean as possible and lots of braces clutters it.
  2. I must declare my vars at the top of the function. I don't like this because it complicates refactoring.

So this is what I think:

All braces that are not necessary should be omitted.

and

Variables should be declared on first usage.

In Javascript, and other C-like programs, there are only two valid cases for using braces. It is when I am declaring objects and functions (and in other C derivates: classes).

So what does this mean in practice?

Lets pretend that I have a function that looks like this:


function feedAnimals(animals) {
  var i, animal, grass, water, meat;

  for (i = 0; i < animals.length; i++) {
    animal = animals[i];
    if (animal.isHerbivore()) {
      grass = prepareGrass(animal);
      water = prepareWater(animal);
      animal.feed([grass, water]);
    } else if (animal.isCarnivore()) {
      meat = prepareMeat(animal);
      water = prepareWater(animal);
      animal.feed([meat, water]);
    }
  }
}

The above fulfills JSLint style, but it does not fulfill my braceless since it has a bunch of unnecessary braces. This is how the code would look like in braceless style:

function feedAnimals(animals) {
  for (var i = 0; i < animals.length; i++)
    feedAnimal(animals[i]);
}

function feedAnimal(animal) {
  if (animal.isHerbivore()) 
    feedHerbivore(animal);
  else if (animal.isCarnivore())
    feedCarnivore(animal);
}

function feedHerbivore(herbivore) {
  var grass = prepareGrass(herbivore);
  var water = prepareWater(herbivore);
  herbivore.feed([grass, water]);
}

function feedCarnivore(carnivore) {
  var meat = prepareMeat(carnivore);
  var water = prepareWater(carnivore);
  carnivore.feed([meat, water]);
}

Braceless style encourages breaking the code up into small functions and this is a good thing. It makes it easier to test and it makes it easier to reason about. It also lowers the cyclomatic complexity

At the moment it is not possible to configure JSHint to disallow braces for loops and conditional, but it would be a good thing.

There are other cases where braces appear in Javascript most notable when creating new objects. I could argue that object creation should also be moved to its own function but, I currently don't follow this guideline myself.