

CoffeeScript Under Pressure - wgx
http://mattdw.github.com/2012/rapid-coffee-postmortem.html

======
jashkenas

        > It wasn’t just fancy HTML we had to build; it was a port of a 
        > graphic- and animation-intensive Flash app, with the polish 
        > intact,1 and it had to work on iOS. It had to work on IE7. 
        > It had to work on Android 2.1 on one of the clients’ phones. 
        > And we had six weeks. We did the maths and figured that at 
        > twelve hours a day, six days a week for six weeks, we might 
        > just sneak in.
        > [...]
        > There were also three levels of stakeholders above us, with 
        > different priorities, and constantly shifting (and always 
        > growing) specs cascading down from above as the site took shape.
        > 
        > After some discussion with my ‘if I get hit by a truck’ backup 
        > developer, I decided to add CoffeeScript to this, despite no 
        > real experience with it.
    

Then you're a brave, brave man. After this intro, I fully expected to hear a
disaster story of missed deadlines and feature cuts ... not a successful
project and a Super Bowl launch.

I think it goes without saying that "on deadline" is probably _not_ the best
time to learn a brand new JavaScript dialect. I'm relieved to hear that it all
turned out for the best.

You mention that you're thinking of adding an explicit validation step --
great idea. For CS & JS (which can be compiled and validated quickly), even
better than having it run when you build is having it run every time you save
the file in your text editor...

~~~
driverdan
"Brave" is far too kind. This is the kind of project nightmares are made of.
Unless the pay was completely off the charts or I needed the work badly I
wouldn't go anywhere near this type of project.

~~~
mattdw
To reply to you and jashkenas, we weren't completely delusional. Sure, the
project was big and tight, but we were pretty confident that we could nail it;
none of the particulars were new, just the scale and the timeframe.

There was never any question of "can we actually do this?", just "can we do
this in time?" Hence picking a tool that looked like it might offer some
shortcuts. Yeah, it was a hell of a lot of work, but that was always going to
be the case, and I accepted the project on those terms.

(My post perhaps came across as more extreme than the reality. We delivered.
The site works. The code never got to 'unmanageable'. Given the opportunity to
refactor this particular site, I'd leave it in Coffee, although I'd rework the
build and deployment process.)

------
pilif
This article gives a perfect example of why you would want to take advantage
of the git index: the author was talking about different versions of coffee
sometimes producing different output which lead to commits going back and
forth between the two versions.

The author is right: this is annoying.

Now, the correct way to solve this would probably be to either not check in
generated files, to leave the JS out of the repo, or, if that's not possible
due to politics, then use the same version of coffee which I would highly
recommend anyways because it gets rid of really bad WTFy issues if one version
of the compiler has a bug which manifests itself in an application bug which
will then only be seen if the last commit was done by the person with the
broken compiler.

Anyways. Let's say you can't use the same compiler and you have to check in JS
in addition to coffee (you are not trying to sneak in coffee by ONLY
committing the JS, are you?)

Now we have the perfect oportunity to show off the git index:

Instead of committing the whole file, you would use add -p to only select the
changes which are actual code changes and not changes in compiler output.

Then you would only commit those changes and then undo the unneeded stuff and
test again, to ensure that you added the right lines to the index (commit
--amend or rebase -i if not).

This will give you a much cleaner history, which will be a huge help when
blaming or reviewing the code. No more annoying flip-flopping between compiler
output styles. No more meaningless changes in a commit. All the changed lines
in the diff are the lines that count. The lines you should look at when
reviewing. No risk of missing the trees in the forest.

But, you might say, history rewriting is bad. I don't want to commit something
I haven't tested.

Remember though: you haven't pushed yet. You haven't altered public history
yet. Nobody knows about those commits yet. You have all the time for testing,
patching and massaging commits. Only once you pushed, your changes (should)
become set in stone. Only then, history gets written. Only then it can't be
changed any more.

This is why I love rebase and I'm really glad I finally found a good real-
world example to show why.

~~~
pkulak
When I heard about that I just wondered who could possibly see a diff that
changed every line in a file (unnecessarily) and actually commit it.

~~~
mattdw
Let me readily acknowledge that our process wasn't optimal. The CoffeeScript
version-change happened while I was completely offline for a week, having
dumped the next dev right in the middle of things with insufficient handover,
so we caught that a bit late.

In hindsight (1) I should have used something other than Make for my build
process and (2) I should have figured out a way to move some of the build
upstream.

Things to get right next time.

------
joshu
Aside from being a good read, the author comes off as the kind of person I
would like to work with.

~~~
dpritchett
What an interesting thing for a highly-regarded founder/angel to say in
public. I hope to hear about this on his blog too!

~~~
joshu
It's just an aside. There's nothing pending.

Thinking about it further, I think the tone is due to the level of humility
you get from someone who is really experienced.

------
bedatadriven
For what it's worth, facing a client-side project of similar magnitude, we
chose Google Web Toolkit and learned Java.

Two years and 60k LOC later, (www.activityinfo.org) I'm not entirely satisfied
with the tool -- sometimes more abstraction introduces new problems to be
solved, and it's hard to find good, affordable java devs to work on the
project here in NL, but it does IMHO bring tremendous advantages in terms of
modularity, dependency management, and generally keeping the code base
maintainable. And the optimizing compiler is nothing short of amazing.

I realize the idea of Java-to-Javascript is sacrilege for many, but if you've
looking at building a large, single-page javascript application, I think it's
worth taking a look at.

~~~
mattdw
I've been seriously considering ClojureScript (which is on top of Google
Closure) for exactly those reasons. The extra toolchain complexity is still an
issue though.

~~~
hkolek
Google Closure (JS optimizing compiler and library) has nothing to do with the
Google Web Toolkit which compiles Java to JS (GWT). ClojureScript is awesome
in any case though :)

------
chadhietala
We recently have switched over to using CoffeeScript in production and haven't
looked back. One thing we found out real fast was to not compile the CS until
you go to staging or QA. The way we get around this is using RequireJS
(<http://requirejs.org/>) and the CoffeeScript
Plugin(<https://github.com/jrburke/require-cs>). This buys you the ability to
compile at runtime in the browser, so you don't have this mess of CoffeeScript
files and compiled JS files in your source. When you are ready to build for
production or QA you use RequireJS' optimization tools to concatenate, minify,
obfuscate and compile the code. Hope that helps.

~~~
functionform
Found out the same thing. Developed mostly via TDD/QUnit in FF with Firebug
only and occasionally running the entire suite with multiple browers. Even IE6
(via IETester) would compile several thousand lines in a few seconds or so.

Used tdd for almost everything even clicking ui widgets to populate from a
rest resource and then validating the result. CS rocks!

------
jtchang
A very well written article.

I've considered learning CoffeeScript but have decided for now to let things
play out and focus on learning JavaScript better. There are a ton of
frameworks for javascript (backbone/spine) that make it more bearable. Also JS
for all its quirks is ridiculously powerful.

To me maintainability is huge in a project. There needs to be a really strong
reason to choose CoffeeScript over plain javascript. Catching all syntax
errors seems okay but not entirely justified. I usually catch those in a
staging environment on a console.

~~~
div
I am now on my third project using coffeescript together with BackboneJS.

On the second and third project, I am also teaching coffeescript to 3 people
who had never written any coffeescript OR BackboneJS before.

Granted, there is a fair amount of coaching involved, but the quality of the
code produced is top notch, and the maintainability is _vastly_ improved
compared to anything we've done in plain javascript before.

This may be due to Coffeescript, and it may be due to Backbone adding some
much needed structure, but I'd like to believe it's a combination of both and
even using one in isolation should yield an improvement.

If you are familiar with Javascript, picking up Coffeescript should be a
breeze, and in my opinion, the benefits are there.

On a closing note, you say that JS is ridiculously powerful which leads me to
believe that you feel using CS means sacrificing some of that power. Since CS
translates directly into JS, I think you'll find this fear is unwarranted.

~~~
recursive
> On a closing note, you say that JS is ridiculously powerful which leads me
> to believe that you feel using CS means sacrificing some of that power.
> Since CS translates directly into JS, I think you'll find this fear is
> unwarranted.

That alone is really not any evidence that CoffeeScript is as powerful as
Javascript. Just because the target language exposes a particular feature does
not mean that source language does.

~~~
div
That's so obviously correct that I'm going to stop making HN comments so early
in the morning and see if that stops me from saying stupid shit.

------
chrislloyd
> Due to our deployment requiring the generated Javascript to be checked into
> the repository, this made for incredibly noisy diffs.

Add `// Generated by' to surpress JS diffs on Github.

> I really like for x in xs. I don’t really use the list comprehensions (which
> Andrew Brehaut had some things to say about), because I tend to use map and
> filter anyway.

CoffeeScript's list comprehensions can be used for `map' and `filter' too.

> I was a bit surprised to discover that CoffeeScript has no more opinions on
> code structure than does Javascript (short a class syntax which I barely
> used.)

One cannot be saved sola gratia.

------
driverdan
Maybe I'm just feeling cynical this morning but I don't understand why the OP
came to his conclusion. I read it as him making a bunch of mistakes which led
him to conclude he shouldn't use CoffeeScript.

He took on a large project on short notice with a tight deadline, browser
compatibility issues, and growing requirements (client is a big company after
all) using a language he's "not terribly confident with". This alone is a
really Bad Idea. But I'll give him the benefit of the doubt and assume he
recognizes this in hindsight and felt he could handle it at the time.

Then he decides to do it in CoffeeScript, something he has never used before.
It seems he had expectations that CS was much more heavy handed, providing
library-like code structure and compensating for his lack of JS knowledge.
Mistake #2.

He finds a bug and some other small annoyances. This is understandable. There
are some things about CS that annoy me too. Every language has its problems. I
suppose this alone could be enough to drive someone away from a language.
Personally I find the trade offs worth it for increased productivity, but
that's just my opinion.

His conclusion about CoffeeScript is that "it just doesn’t feel quite robust
enough (as a language or as a tool) that I’m confident in it at this sort of
scale, and at smaller scales it doesn’t confer enough benefit to be worth the
added complexity." Again, problems with confidence.

My suggestion? Be confident with JavaScript first, then use CoffeeScript. Not
understanding the underlying language is just going to lead to problems like
this.

------
EtienneK
"You may have seen it advertised during the 2012 Super Bowl."

For those of us not in the US - anyone have any idea what site he is talking
about?

Edit: Just saw the link in a previous comment. Seems the site is:
<http://toyota.com/camryeffect/>

------
Perceptes
I've posted this before, but it's relevant again here, as the author mentions
the dangling comma issue. Discussion on preferred syntax for a parameter
spanning multiple lines followed by another parameter:
<https://gist.github.com/1215863>

------
functionform
You have got to be kidding.

Paraphrasing: We were under massive time constraints and by our own
estimation, already barely able to meet the deadline, so we decided to add a
language which compiles Javascript even though I am not that well versed in
Javascript.

There are so mnay things wrong with this approach I really don't know where to
begin.

------
jugglinmike
> CoffeeScript was a godsend here, simply as an explicit compile and
> validation step. > Automatic local scoping (no var necessary) is a sane
> choice, and safe loop scoping with for x in y do (x) -> erases a whole
> category of errors. > indentation

Thought it might be useful to others seeking these advantages that passing
your JS through JSHint in the build process could provide these benefits. It's
not a cure-all, of course--the author cites other benefits that linting can't
achieve. But if you're a like-minded developer looking for assurances along
these lines in JavaScript, check out <http://jshint.com> and
<https://github.com/jshint/jshint/>

------
mafro
A very interesting read, although from this line I couldn't quite stop
thinking "there's no silver bullet":

> I decided to add CoffeeScript to this, despite no real experience with it.

------
75c84fb8
> The lack of a strong set of standard control and data structures [in
> JavaScript] means that you end up typing many of the same patterns
> repeatedly

Care to elaborate? I'm not saying I don't have my own notions of what's
missing in JS, but I'd like to hear your take, given your experience.

~~~
mattdw
Particularly I'm thinking of the inescapable async-all-the-way down, which
necessitates endless lambdas. In other languages it's possible to pick a point
at which to invert control back to blocking-style; JS's single-thread model
makes that impossible. So for instance all calls to the server API have to be
callback style; if you have to make serial calls, you can't avoid nested
callbacks.

I miss a set type, I miss solid iteration (although coffescript mitigates
that), and immutable datatypes would be nice (I've got used to them in
Clojure.) I miss a solid FP stdlib, although jQuery has map and filter, which
goes a long way.

That's the ones I can immediately think of :).

~~~
75c84fb8
> inescapable async-all-the-way down, which necessitates endless lambdas. In
> other languages it's possible to pick a point at which to invert control
> back to blocking-style

I hear you. Have you heard of iced coffee script
?(<http://maxtaco.github.com/coffee-script/>) I didn't sleep well the night
after I read that.

~~~
mattdw
Looks much like <http://tamejs.org/> in the semantics. I guess if you're pre-
processing anyway, you may as well pre-process all the way.

~~~
mattdw
Oh, same guy. That'd be why.

------
ricardobeat
> I don’t think CoffeeScript adds quite enough benefit to outweigh the costs

Those "costs" were the cost of learning, not development/efficiency costs.

If you are already comfortable with Javascript _and_ know coffeescript
beforehand, the cost is zero and the benefits far outweigh that.

------
jnbiche
If JS/CS typing is an issue for you, you may want to take a look at
CoffeeScript Contracts, a fork of CoffeeScript that implements contracts:
<http://disnetdev.com/contracts.coffee/>

I've not used them in production yet but it looks like a very cool way to
ensure code quality. The syntax of the Contracts resembles Haskell type
definitions. Contracts are very flexible -- for example, you could create and
enforce a "Prime Number" type (or whatever type you wish).

Also, you don't have to include the contracts in your production code -- you
can compile to JS for production and omit the contracts once you've validated
the code against them.

Actually, the more I look at this, the more I think I'll use it for my next
CoffeeScript project.

------
howardr
would like to see the app. it seems like it would have been a hard task.

now, trying to think of which apps were featured during the super bowl. the GM
one? anyone have any guesses?

~~~
mattdw
My link was apparently not obvious enough :).

<http://toyota.com/camryeffect/>

------
no-espam
It shouldn't matter what the generated code is. Use gitattributes to ignore
diffs on generated folders.

~~~
mattdw
Could you explain this further?

------
ZenPsycho
Uhm, I don't think CoffeeScript is meant to be used on production mission
critical projects. It's a research language, not a "fix javascript" language.
That so many people are going ahead and using it in production anyway really
raises some serious questions about how technology choices get made.

~~~
knowtheory
I'm a bit bemused by your comment. Given the conversations that jashkenas and
Brendan Eich have had... I think it's pretty clear that CoffeeScript is an
"improve on javascript" language quite explicitly.

Interestingly, I think that quality is entirely orthogonal to production
worthiness and any implied or explicitly stated guarantees about utility and
unbreakiness.

I've personally thrown my weight behind up and coming technologies in the past
(Merb to be specific, back in the Merb vs Rails insurgency), and ended up
supporting a technology stack that was left abandoned. In spite of that, my
company continued running happily on Merb for 3 years after that (until a move
to Scala).

That jashkenas warns people with a "caveat emptor" doesn't mean a tool
shouldn't be used in production. It means that you should carefully evaluate
how you use your tools in production, make sure you write modular testable
code, be willing to dive down into the weeds, and most importantly always have
a backup plan.

The interesting part about CoffeeScript is that the backup plan (again if you
have properly factored code) can just be "use more Javascript". :P

(my own caveat is that I do not CoffeeScript in production. At least, not
yet.)

