4/16/2012 - 9:42 PM

style guide

style guide

High level style in javascript.

Opinions are like assholes, every one has got one.

This one is mine.

Punctuation: who cares?

Punctuation is a bikeshed. Put your semicolons, whitespace, and commas where you like them.

This post is concerned with higher-order style.

Be obvious

Don't do something complex just to make your api simpler. That will lead to confusing bugs, and necessitate reading your code, while also making reading your code harder. This will be frustrating for me, when I'm trying to use your module.

Example, avoid chaining DSLs.

This is bad:


It's not really obvious how when relates to dothing. It's better to pass in related things together.

  thing.when('something', doThing)
  //or maybe
  thing({when: 'something', then: doThing})

Chaining where you simply return this is acceptable.

Be idiomatic, or not.

if possible, make your code follow the APIs in node core. That way, I already know how to use your module. I don't even have to read the documentation. This is ideal.

If you don't do this, you need documentation. But even worse, is if have merely a similar API, but does not behave exactly the same, I will misuse your code, get an error and be forced to read your code. This will frustrate me.

if your can't follow an idiomatic API precisely, do something completely different.

ALWAYS PASS ERR IN CALLBACK, (an event listener is not a callback, so this doesn't apply in that case)

If you have a function called createServer, it should return a server, and it should have a listen function. createServer should never start the server listening. That should never happen until I call listen.

a listen function that takes something other than a port, a hostname, and a callback (like in should be called something else.

my favorite API from node is Stream (more on that later)

"all you need is lambdas" -- John Lennon

Functions are your most powerful weapon. In javascript you do not need fancy plugins. Allow users to extend of control your modules behaviour by passing in a simple function, with given arguments.

connect is a good example of this.

something only needs to be faster when it's slowing you down.

don't optimise things that aren't gonna be bottlenecks, example; it's completely acceptable to read configuration files synchronously. because you only do it once, and you need to do it before anything else happens in the application.

it's something you have to read every time you respond to an http request, then it must by async.

use flow control over control flow

streams in node are one of the rare occasions when doing something the fast way is actually easier. SO USE THEM. not since bash has streaming been introduced into a high level language as nicely as it is in node.

compare downloading a file one step at a time, and streaming it:

  //load the response entirely into memory
  request ('', function (err, doc) {
    //write the whole thing to disk
    fs.writeFile(dest, doc, function (err) {

now, stream it:

request('') //read from the internet
  .pipe(fs.createWriteStream(pathToFile)) //write to disk as data arrives.
  .on('end', function () {

the latter is preferred, the syntax is nicer, but more importantly, streams handle data in a smarter way.

they pass data along as it arrives, and can also tell the upstream to pause if they can't handle any more.

in the above example with the callbacks, the time it would take to complete is the time to request + the time to write to disk.

in the example with the streams, it will only take slightly longer than the time to request.

if the file is VERY LARGE this will be significant, also if it is VERY VERY LARGE it may not all fit in memory at once, but streaming will still work. the node.js team work very hard to make streams as fast as possible, and it's also easier, so use them.

if in doubt, modularize

node.js has the best package manager so far. This is not hyperbole. It's simple yet powerful. so split up every thing, this also makes it easier to test, and easier to extend.

I also like to separate layers,for example, if you are writing a service of some kind, write it to that you can test it entirely in memory, and then wrap it with layers that provide the network io.


The style of a line is easy to change. But the style of a module is much more important. This is something that I think is truly worthy of debate, because it actually makes a significant difference.

what are your opinions on high-level style?