Thursday, February 23, 2012

Rails Went Off The Rails: Why I'm Rebuilding Archaeopteryx In CoffeeScript

Ever been to one of those parties where your work friends and your college friends don't talk?

I posted a great video on my Tumblr which I would never post on my Facebook:

It's a guitarist shredding along to "Bangarang" by Skrillex. I wouldn't post it to Facebook because on Facebook I've got high school friends who I know from Spotify are listening to Skrillex, as well as rave scene friends from when I lived in San Francisco. I don't actually know their opinions on Skrillex for a fact, but if I had to guess I'd assume a certain disdain, because some of my old rave scene friends are hard techno purists, as well as huge music hipsters, who distrust popular music, grow bored very quickly, and knew about dubstep years before Skrillex. In fact, I heard some extremely early proto-dubstep records in London in 2000, and I probably wasn't the only one of this particular group of friends to do so -- which means at least a few of us knew about dubstep a decade before Skrillex.

My old rave scene music hipster friends would probably hate that video for the same reason my musically naive high school friends would love it: Skrillex built huge, phenomenal success on a style which is essentially a join table pulling columns from both rock music and rave music. Posting something like that on Facebook could mire me in a situation where I'm trying to get two utterly disparate groups of friends to get along with each other, despite having utterly opposite opinions, and despite the fact that I haven't seen any of them in years. Total waste of time.

It reminds me of an old Why the Lucky Stiff quote:

when you don’t create things, you become defined by your tastes rather than ability. your tastes only narrow & exclude people. so create.

I bring this up because I saw an otherwise great presentation at LA RubyConf which featured a staggering number of catty remarks about almost every other language but Ruby. The only exception I remember is Smalltalk, which got the kind of reverence you sometimes see when the Ruby community talks about Smalltalk. I used to be pretty excited about Smalltalk too, but I distrust exclusionary reverence. I also remember buying an old Mac Mini from an LA Rubyist who collects so much weird old computer stuff he's like a tech historian. One item in his collection: a staid, dull, lifeless manual for IBM Smalltalk, one of the most bland corporate documents I've ever seen in my life, and a strong counterpoint to the Ruby community's small but vocal "Smalltalk was the best thing ever" cult.

A few years ago, Rails was as crazy hot shit as Skrillex is today. But in 2012, a Hacker News post asked this question:

Which one should I learn deeper, Node.JS/Express.JS or Ruby on Rails?

Many offered positions asks for Rails knowledge but looks like Node is getting a nice spot in Web development for the very near future

In other words, should I learn the dominant paradigm, which will make it easier to get a job, or the new hotness?

We all know what the opposite of new hotness is.

And indeed the Hacker News thread features this response:

Rails is over. It's a bloated meta framework that requires enormous amounts of peripheral knowledge to understand.

You should take anything you read on Hacker News with a grain of salt, if you take it at all, but what does it mean for Rails to be over? It doesn't make sense at all if you look at Rails as an application development framework, but if you look at it as a fashion trend or a party, it makes perfect sense. Rails was the height of fashion a few years ago, which made for a quite a party, but it isn't any more.

People decry the degree to which tech is a fashion-driven industry, but there's a reason for it. As Smalltalk creator Alan Kay said, "Once you have something that grows faster than education grows, you’re always going to get a pop culture."

Rails is old and busted; Node.js is the new hotness. But people hate Node.js because of "the hype." This amuses me, because the only things I know about the hype around Node.js come from people who hate Node for that hype.

I'm not surprised to hear that Node is bratty. When Rails was Node's age, it was bratty as hell. RailsConf 2007 featured incredible tech, but to me it also felt like the epicenter of the world's most powerful douchequake. I ignored Rails douchery then, as much as I could, and recommend doing the same with Node now. Here's why.

The sulky, bratty teenage Rails had three big things it made fun of the Java old folks for: design patterns, the JVM's long startup time, and overly ceremonial code which had nothing to do with the day-to-day experience of writing web apps. Today Rails has a startup time which is so long, the Rails community actually created Spork, a gem which keeps your Rails environment alive between test runs, because otherwise it's hard to use TDD with Rails. Rails tests can take so long to run that by the time a test run completes, you're liable to forget what you were doing, and, in fact, your name. The Rails community mocked design patterns relentlessly when it was Node's age, but look at how ActiveRecord::Base hijacks inherited and you'll realize that this:

class User < ActiveRecord::Base; end

really means this:

User =

kind of like this:

User =

We use a bizarre, convoluted mechanism for attaching ClassMethods and InstanceMethods modules to ActiveRecord::Base because if we attempt to subclass it in a gem, we don't get a subclass in the purest sense. What we actually get is a new class which ActiveRecord::Base creates. ActiveRecord::Base is an ActiveRecordClassFactory in denial.

And as for overly ceremonial code, let me tell you about my balls. I actually have a rake task to scratch my balls. Somebody told me a good entrepreneurial programmer writes code to scratch their own itch, and I took them literally. The code uses a serial port to power an Arduino board. The Arduino's got a servo with a backscratcher attached. I keep it on a shelf at scrotum height underneath my desk.

I literally need to type bundle exec every single time I want to scratch my balls. I don't like having to type bundle exec every single time I scratch my balls. I named the task balls, so I can type rake balls, because it rakes my balls, and Bundler pisses all over my tidy syntax, but am I going to complain? Am I going to point out that asking me to type bundle exec every time I want to scratch my own balls shows incredible contempt for me as a user, particularly considering that the whole reason I'm a user of this particular thing is because I work in a language which was designed to optimize for programmer happiness? Of course not. It's not productive or helpful to say that, so I simply type bundle exec rake balls and scratch my balls in sullen silence.

Typing bundle exec every single time I want to scratch my balls is the epitome of the overly ceremonial code which Rails defined itself against from 2005 to 2007. The Rails community has become everything it used to make fun of. Despite that, it's also managed to utterly transform web development for the better, and not just in Ruby, but in nearly every language. When Rails was new, it sprouted clones in other languages on an almost daily basis, and now that it's matured, the outsider response has matured as well. You don't see a new Rails clone in a new non-Ruby language every Tuesday like you used to in 2006, but you do see the Rails community implementing code generators, convention over configuration, and tidy routers every time they venture into unknown territory, and CoffeeScript took obvious inspiration from both Ruby and Rails in making developer happiness a priority.

Consequently, I think listening to Node.js hype at all is foolish. It's just not worth having an opinion about. It leads to a foolish brattiness in those who believe it and an equally foolish hostility in those who harp on its flaws. Hype is hype. It's bullshit. Let it go. Node will change course to accomodate all its critics sooner or later, just like Rails did, and in the meantime there's a lot of exciting work going on. People are building very interesting things, and the browser landscape is changing so fast that by the time Node grows up a little, web development will be an entirely different world.

This was true of Rails, too, and it's what made Rails fun when Rails was a party, and what makes Rails powerful and useful today, now that it's only a tool.

However, going back to the Why the Lucky Stiff quote, it's pointless hating on Rails for not being as fashionable as it was. It's possible to see Rails as a fashion trend which has run its course, but it's actually a lot more intuitive to see it as a useful tool for building things. But there you also run into some problems. Let's take "Rails is over" out of the equation, but revisit that Hacker News comment:

Rails is... a bloated meta framework that requires enormous amounts of peripheral knowledge to understand.

The first thing this reminds me of is an inane rant which called Rails "pants on head retarded." I can't recommend this rant, because a large number of its criticisms apply only to how the official documentation instructs you to use Rails, not how serious, well-known, best-of-breed Rails developers actually use it (except of course for DHH). I think the "enormous amounts of peripheral knowledge" criticism is dead on. Chief among this vast range of peripheral knowledge: knowing the difference between what the Rails documentation says Rails developers do, and what Rails developers actually do.

For instance, I don't think anybody but DHH and maybe one or two other members of Rails core really use Rails tests the way Rails says you're supposed to. I don't think anybody but DHH and maybe one or two other members of Rails core even takes the official Rails approach to testing seriously at all. Rails unit tests aren't really unit tests, Rails integration tests aren't really integration tests, and Rails functional tests aren't really functional tests. Most people create a spec directory, install RSpec, and throw all that other bullshit away. So it's kind of a waste of time for an anti-Rails rant to go on and on and on about the clothes we politely agree to pretend our emperor is wearing.

The "old" part of "old and busted" is not really worth thinking about. "Old hotness" means "classic." But "busted" is something to address, and there's busted shit in Rails. Consider what happens if you set up your Gemfile without source :rubygems on the first line:

Your Gemfile doesn't have any sources. You can add one with a line like 'source :rubygems'

Are you fucking kidding me?

This is what Google's "Did you mean" functionality would look like if the Bundler team had implemented it:

Bundler makes dependency management much, much less painful than before, but because source :rubygems isn't the default, even though Bundler knows it should be, Bundler also fails completely at convention over configuration. I don't mean like, "that isn't perfect." I mean "grade F, you cannot graduate, you have to repeat this year." Like the way you would fail at wearing clothes if you showed up to work at the office in your underwear, and nothing but your underwear, and your underwear wasn't even clean.

Bundler isn't the only problem. With Rails 3, Rails went off the rails.

The link's ironic; it takes you to a gigantic page full of things you have to do before you can start writing your app.

Consider this discussion:

You can read the whole thing here if you want. I'm just going to give you some excerpts.

To paraphrase Jose here, Rails 1 and 2 were releases for application developers. Rails 3 was a release for plugin creators and maintenance programmers. This is cool, but building application frameworks without application developers as the primary audience was one of the things Rails made fun of Java for in 2006. Jose's a member of Rails core, and he wrote a terrific book which showcases the incredible power of Rails 3's newer, more modular APIs, but there are times when tweets speak louder than books.

Ward Cunningham is kind of a big deal.

My answer to the Hacker News guy who wanted to know if he should learn Node or Rails is the same answer he'd get from Jeremy Ashkenas: learn Node. (Actually, I can't speak for Jeremy, but I'd say learn both, but prioritize Node over Rails.) There are times when it's fun to be a partyhopper, and the music next door is better right now. It's more important to learn Node.js, CoffeeScript, and Backbone these days, because the work going on in those communities changes paradigms. The work going on in Rails is mostly just tidying up after the paradigm-changing work which used to go on in Rails -- except that Rails 3 introduced as many rough edges as it removed.

Speaking of rough edges, the browser is turning into the operating system. If you're on a new version of Chrome, you can already play with in-browser drum machines, as well as filters, compressors, and synthesizers. You'll risk crashing your browser now, but it's going to be pretty awesome pretty soon. It's also likely mobile apps are going to make web apps look pretty dated, and Node is better poised to take advantage of this than Rails is.

Also, when you're learning something, you want to have fun. Rails is still useful, but it's no longer exciting. Although there's a ton of awesome all over the place, there's also some "what the fuck were they thinking?" here and there. Fixing that shit isn't fun. If you're looking to do work you can get excited about, it's Clojure, Scala, or Node.js. Clojure and Scala both run on top of Java, which holds horrible memories for me, while Node.js involves a language I've mostly had a lot of fun with, despite its frequent idiocy. CoffeeScript is far from perfect, but it's a joy to use, because it reduces JavaScript's WAT factor down to a tolerable level of mild background noise.

Rails just isn't the future any more; it's the past.

Although I think you can get much better jobs with Node.js than you can with Rails these days, I'm much more interested in creating my own projects, and I'm having more fun with Node.js there as well. So I'm creating a series of videos which use making music to teach Node, CoffeeScript, Backbone,, and most importantly of all, jasmine-node, a Node.js port of the Jasmine BDD library for JavaScript. With jasmine-node, you can run your specs server-side most or all of the time (depending on factors I'll explain in these videos), and the payoff is fucking awesome.

Running specs in a browser has always felt like bullshit to me. It's an incredible pleasure to run them lighting-fast on the command line instead, in a context where you can hook them up to continuous integration, or indeed anything, via Unix status codes. There's really no excuse not to write your JavaScript TDD/BDD in 2012.

Going back to the topic of JavaScript drum machines, I wrote a library in Ruby called Archaeopteryx. It's a combination MIDI interface, drum machine, and probabilistic breakbeat improviser. I've started to rewrite it in CoffeeScript. The new version is called Clyde, and the code's much cleaner.

I've also already cooked up some really fun hacks.

I chose the name Clyde partly because I got way too many questions about how to pronounce Archaeopteryx, but mostly after legendary drummer Clyde Stubblefield -- not just a funky drummer, but THE funky drummer James Brown was singing about -- who coincidentally will be SPEAKING at Madison RubyConf this year, the same conference where I last year freaked out at a panel for saying you don't have to test JavaScript. I can't even describe how excited I am for that.

To be fair, Ari Russo wrote a fantastic MIDI library in Ruby called Unimidi, which looks better than anything I ever did, but I'm sticking with JavaScript for this project. This is partly because investing my time in this language looks wiser today than investing it in Ruby (especially since I'd be repeating stuff I already did in Ruby), and partly because of bona fide technological superiority.

Clyde isn't just easier to pronounce. A lot of people complained that Archaeopteryx was hard to read. Clyde, although still very much a work in progress, is already much simpler to read. First, I had to snag a lot of low-level MIDI interface stuff for Archaeopteryx from a great book by Topher Cyll called Practical Ruby Projects. (Ben Bleything later rewrote it, creating a cleaner interface library called MIDIator.) To set up MIDI for Clyde, however, I just installed a great Node.js library and wrote some really simple code. Archaeopteryx also devotes a bunch of code to implementing an equivalent to JavaScript's setTimeout(), and aliases Ruby's lambda to L so that it can freely assign methods to objects, the same way you can pass functions around in JavaScript.

JavaScript's basically a better language for this type of project, because Archaeopteryx uses a lot of hacks to make Ruby work like JavaScript, and while JavaScript itself is hideous to read, CoffeeScript is so beautiful it sometimes even makes Ruby look clunky.

My tech reviewers have also found Clyde's techniques easy to copy in Garageband, which means anyone with a Mac will be able to get Clyde working very quickly, whereas I had a lot of people puzzled out of their minds trying to get Archaeopteryx to work on their machines. An open source project which only works for the guy who wrote it is no use at all.

Because my videos are going to be a fun way to learn about cutting-edge technologies, I'm pretty excited about them. They may in fact become the best, most exciting and engaging way to learn modern JavaScript development. I think it's important for software development training to be fun, because I want to inspire people to come up with their own hacks, because you learn most when you're paying the most attention, and because this idea is built into the language hackers use: when we explore a technology, we say we've been playing with it. I'm releasing my first video for free tomorrow afternoon, so check back here Friday to see it.

Since this blog post is to some extent an ad for these videos, and truth in advertising is important, I want to confess that I don't really have a rake task to scratch my balls. However, it still feels as if I have to type bundle exec whenever I want to scratch them, and that feels like the kind of horseshit a cursory knowledge of Unix environment variables and paths could resolve. (To rant even further about Bundler, if you type bundle && foo, you never get to foo; it appears Bundler doesn't even support status codes.)

Going back to the larger issue, Rails definitely went off the rails. Cleaner, more modular APIs are an important goal, but they're way less important than speedy development, a modern feature set -- why is Rails not staying up to date with HTML5 the way it did with Ajax? -- and, above all else, programmer happiness. The Merb integration rewrite was a giant, time-wasting threadjack with only a few small payoffs, and DHH, who wrote two whole books about why you should turn down feature requests, should have nixed the whole thing. I'm still going to keep using Rails, because it's still a terrific framework, and I still enjoy it a great deal, but I think it's absolutely fair to say that Rails 3 is a step backwards from Rails 2, and that Bundler, although very useful, is clearly not even close to finished. They say they're at version 1.0, but I don't think they're fooling anybody.

Update: Yehuda Katz from the Bundler team and Rails core sent me this helpful gist:

Update: Yehuda's apologized for the phrasing, and the point he raises is in fact completely valid. Meanwhile, I've created eight episodes of a video series on making music with CoffeeScript and Node.js. The first two are free.