Fabio vs. The Internet

Music coder / Code producer

The Async Web, or "Javascript Sucks, but Someone Did Something Cool on It"

(Disclaimer: this is ranty. Don’t say I didn’t warn you.)

I’m old in internet years. I was there for the first browser war, fighting my way through layouts made with <table> tags while adjusting margins with shim.gif to get around half-assed CSS implementations. You could even call me a veteran. If you have also been working with the web since the 90s, you know that server-side Javascript isn’t a new thing, even though it has become the new hotness lately.

I’m talking about Node.js, of course. Everybody wants to jump into the real-time web bandwagon, and Node.js is the passport to the promised Web 3.0 land (or is it 4.0 already?). Single-page apps! Asynchronous connections! Websockets! Webscale! Woo!

Well, I’m all for it. No, seriously, it’s cool stuff. The problem is, of all the languages anyone could have picked to make this happen, someone had to pick Javascript. Wat?

While Javascript is ubiquitous and pretty easy to get started with, it’s also so flawed someone took the time to create a whole new language that gets “compiled” into it to make development less painful. And it’s a huge success! There’s nothing quite like Coffeescript happening on other languages, and certainly not for the same reasons.*

But yes, Node does work pretty well. The V8 Javascript engine out-performs most popular runtimes in other languages, including Ruby’s MRI* and cPython. But since everything is asynchronous, it forces certain patterns that can become messy very quickly and breaks built-in Javascript features like exception handling. Want better performance? Then you have suck it up and code around it. Or, you know, just use Coffeescript and hope for the best.

Of course it’s not all bad. There are amazing frameworks like Meteor and Derby that make it very easy to create real-time collaborative apps. Express is a pretty good platform to create JSON APIs and regular websites that, admittedly, perform way better than Sinatra (the Ruby equivalent). But I can’t help thinking I could achieve the same results with less hassle if, say, Python was picked up by the hipsters as the foundation of the “new” asynchronous web craze (it has Tornado after all).

To be honest, my hopes lie with Go right now. It’s still a bit rough around the edges, but so was Ruby when Rails exploded. Go is statically typed and compiles to native binaries, which makes it extremely fast and light. It’s also built for concurrency and includes pretty good standard packages to build networked and web applications. The only missing pieces are a decent package manager (the current state of affairs is frankly very messy) and a web framework that can bring all that potential to fruition. Revel is promising, but it’s still missing a few key parts to make it brilliant.

It’s interesting to note that Go and Node.js even share similar patterns. Error handling is a good example. Here’s a Go snippet to read a file and print its contents:

1
2
3
data, err := ioutil.ReadFile("/tmp/data.txt")
if err != nil { panic(err) }
fmt.Print(string(data))

And here’s the Javascript equivalent:

1
2
3
4
fs.readFile('/tmp/data.txt', function (err, data) {
  if (err) throw err;
  console.log(data);
});

Take out the mandatory callback on Javascript and it’s pretty much the same code. You have to pass errors around and handle them manually; Go doesn’t have exceptions by design and Javascript’s asynchronous behavior breaks them. The main difference is Go gives you the option of running functions asynchronously instead of forcing callbacks due to bad design.

Another similarity: neither Javascript or Go have a class-based object model. Javascript uses objects that work pretty much like associative arrays in PHP (or hashes in Ruby, or dictionaries in Python). They’re not really objects derived from classes - they just kinda sorta work like them.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// Defining a rectangle object
var rectangle = {
  width: 5,
  height: 10
};

// Adding an area() method
rectangle.area = function() {
  return this.width * this.height;
};


// Adding a perimeter() method
rectangle.perimeter = function() {
  return 2 * this.width + 2 * this.height;
};

// Calling the methods
rectangle.area();
rectangle.perimeter();

Go has type structures that can contain data and functions, therefore working just like classes (but only if you want to). It even provides inheritance through embedding.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// Defining a rectangle type
type rectangle struct {
    width, height int
}

// Adding an area() method to rectangle
func (r *rectangle) area() int {
    return r.width * r.height
}

// Adding a perimeter() to rectangle
func (r *rectangle) perimeter() int {
    return 2 * r.width + 2 * r.height
}

func main() {
    r := rectangle {
      width: 5,
      height: 10
    }

    // Here we call the 2 methods defined for our struct.
    fmt.Println("Area: ", r.area())
    fmt.Println("Perimeter:", r.perimeter())
    // ...
}

All things considered, it’s a good time to be a developer. It’s a pity the best technologies seldom become the most popular, while inexplicable fads take over the landscape from time to time. Such is life. But if people could realize that abandoning SQL completely wasn’t such a good idea, who knows? Maybe the best tools for the job can become more popular sooner rather than later.


* Before anyone mentions it, Elixir is to Erlang as Scala is to Java. Also, it goes whithout saying that Javascript is orders of magnitude slower and less fault-tolerant than Erlang.

* jRuby is a completely different story, though - particularly the latest release. But then you need to run your code in the JVM. Take that as you will.

Comments