Coffeescript: Joyful and Unreadable

Posted in Javascript, Rant

I had an interesting chat with a visiting engineer today about Javascript app frameworks, specifically Backbone.js. Backbone is probably the most popular one out there right now, on account of having excellent documentation and being minimalistic and non-intrusive. They even have a section telling you how awesome they are.

Anyway, he was telling me how the combination of Backbone and Coffeescript made for happy JS app development. Coming from a Ruby enthusiast, the structure that BB provides along with the nice syntax of CS and the cleanliness of writing pure client-side code with an abstracted API backend was a “joyful experience”.

Strange, I thought it made for some terse, unreadable code.

Of course, I’m hardly the expert in this area; the exposure I’ve had comes from playing around – and failing – with the BB + CS (+ jQuery + underscore.js, which comes with BB) stack, namely to try to layer a JS app on top of WordPress via the WordPress JSON API. I wanted to be hands-on with the technologies, and they did exactly as advertised, providing the base for an app and some really nice simplifications along the way. For me, though, the trouble came from using all of them together.

Let’s review. First, there’s:

  • Underscore.js, a perfectly nice, minimalistic library that adds a bunch of nice utility functions and a simple templating library.
  • jQuery, the DOM manipulating wonder that’s the simultaneous cause of joy and suffering for web devs. It’s great when you can move 5 pieces of DOM around on one line, it’s terrible when I have to debug it.
  • Backbone, which adds additional model, view (really more like a controller), routing and API “sync” support, along with some conventions to tie itself back into the DOM.
  • Coffeescript, which tries to make everything look and feel like Ruby, but has to leak the underlying Javascript at times as the languages don’t directly translate.

When I put all of them together, the result is some really terse but dense code. I found myself writing lines like this:

fetchRecent: (num) ->
  AC.api.getRecentPosts num, (posts) =>
    @reset (new AC.content.Post(post) for post in posts)

But I wasn’t sure whether my code would be a good sample of good BB + CS code, so I Googled and found some other samples:

render: =>
  # Set the name of the page
  @el.find('h1').text("Editing #{@model.getName()}")</p>

<p># Render the content
  @el.find('.ui-content').html(@template({venue : @model}))

There is so much happening on each line across multiple libraries that I’m finding myself spending extra effort to understand what’s being done. For example, for that last line of code:

  • @ is a CS shorthand for JS’s this.
  • Because we’re inside an event handler, we have to use render: => to preserve this to mean the backbone object.
  • el is a backbone convention that a view uses to reference a DOM element. Since we have jQuery convention makes it a jQuery object as well.
  • @template refers to a template we set up previously, using underscore’s built in templating system. It takes in an object of key-value pairs, which the backbone model object @model provides.

Maybe I’m a bit old-school JS, but having to context-switch across multiple systems on just one line of code is a lot of work.

I think of JS as a powerful but not exactly feature-rich language – constructs like classically inherited classes, public/private methods and namespaces are basically hand-built by people who truly understood its strengths and limitations. These imperfect abstractions we’re layering on top makes for easy writing at-the-moment, but much more difficult reading, not to mention the debugging nightmare.

That said, if making Javascript look and act kinda like Rails makes Rails devs happier, maybe it just means I’m not Ruby enough.

  • Odds are you aren’t Ruby enough 🙂 Really though, yes there’s a lot happening, but that’s some what the beauty of it. Translating that in to it’s JavaScript equivalent would make for a very unreadable and unenjoying experience.

    We as Rubyists are spoiled with beautiful syntax and I know I personally have trouble looking at syntax such as JavaScripts.

  • I felt the same way until I started using Coffeescript. Once I actually sunk my teeth into it, it became very readable, very quickly. Beyond that, not having to mess around with all kinds of closures and verbose looping mechanisms meant that character-for-character, more of my code is business logic. Your examples up there feel very clean to me.

    Try comparing the equivalent handwritten JS to the Coffeescript examples up there. I think you’ll find that they aren’t very readable (though they’ll be more comfortable, since you know Javascript already).

  • For me, it’s all about how clearly the code communicates the intent of what’s going on.  That first example I would read as “call getRecentPosts and with the result call reset on myself with a new Post for each post”.  I can easily understand the essential intent because it’s not hidden behind a bunch of syntax noise and hoops I have to jump through to make the language happy (eg var self = this).  It may be that after trying coffeescript for awhile it will read more naturally for you as the other commenter suggests.  

  • Anonymous

    I would try writing something a little different to start with CoffeeScript. You’re example you listed as evidence to your code being dense looks an awful lot like the wordpress api is partially at fault here. Backbone is another culprit for making your code seem dense. Try CoffeeScript/jQuery by itself and I’d be willing to bet you’d find it more enjoyable. I mean, the title to this post is CoffeeScript: Joyful and Unreadable. It really should be CoffeeScript, Backbone, and the WordPress JSON Api: Joyful and Unreadable. Not really a fair assessment.

  • Pingback: Blog Redesign and Resources - Code | allenc()