If you’re interested in CoffeeScript, then I’m sure by now you have read Ryan Florence’s blog post titled “A Case Against Using CoffeeScript”. In this post, Ryan explains that he uses CoffeeScript at work, and he likes the language, but in his opinion it is too difficult to comprehend and too difficult to debug. My response to this, in the immortal words of Dwight Schrute, “false!”
Before we get started, let me just say that this article is more about disagreeing with some of the statements made in Ryan’s post, its purpose is not to “sell” you on CoffeeScript, but merely point out that CoffeeScript is not something to be scared of. If you want somewhere to show you how awesome CoffeeScript is, I would recommend checking out the official CoffeeScript site and CoffeeScript is for Closers by Brandon Satrom.
Let me start out by saying that I think Ryan is making two completely unrelated assertions in his post:
- CoffeeScript is too difficult to debug.
- CoffeeScript is too difficult to comprehend.
I feel that the first issue definitely has some validity, but the second really holds no water for me at all.
Too Difficult To Comprehend?
To say that CoffeeScript is too difficult to comprehend seems silly to me. Every language has features in it that, when used poorly, can create horrible unreadable code. If a developer wants to leverage a language in a way that causes unreadable code, there isn’t a language in existence that will stop them. Just saying that code is “bad” or “unreadable” should be a red flag in most language arguments, since these adjectives are usually a matter of personal preference, but too often delivered as fact.
A big part of his argument revolves around “one liners”. As if CoffeeScript is a horrible language because it allows you to do a lot on one line. And by giving developers this ability (gasp!) they will write horrible code and make terrible choices! I hate to break it to you, many languages give you the ability to do a ton of work in a single unreadable line. Python? Check. Ruby? Double check. C#? With LINQ, absolutely! Java? Can you say “fluent” interfaces? Scala? Absolutely. And unfortunately, I can write some pretty horrible one-liners in JavaScript, especially with everyone’s favorite library jQuery.
Reasonable developers will write reasonable code. Bad developers will screw up any language. I guess CoffeeScript gives developers more chances to write crappy unreadable code than some languages, but I don’t think that JavaScript is one of them.
CoffeeScript’s “Bad” Parts
Yes, CoffeeScript has a few warts. But is its ability to call methods without parentheses a “bad” part? I don’t know, ask a Ruby developer then ask a Java fan (do those exist still? I kid. I kid.). I’m sure you’d get two different answers. Given the example that Ryan had:
dfd = $.ajax url: url format: 'json' method: 'get'
I’m sure that many developers would find that hard to read, while other developers might not be too offended by it. In this case though, CoffeeScript still allows you to put curly braces around the object literal or parentheses around the method call, but does encourage you to be terse. CoffeeScript isn’t perfect, but the alternative is JavaScript, and so I think if we wanted to get into that war, I believe that CoffeeScript would come out on top.
And don’t take that as me saying JavaScript is bad, because it isn’t, it is a great language. What I am saying is that if we want to start comparing which language has more peculiarities, I think that JavaScript would come out on top.
CoffeeScript Is Hard To Debug?
This second part of his argument is one that I think needs a bit more attention, but unfortunately it is the part that he touches on the least. I’ll be completely upfront, I’ve found that CoffeeScript can definitely be more difficult to debug than JavaScript in some cases.
I have run into a few situations where I’ve written a chunk of code in CoffeeScript and I’ve received some very odd messages from the CoffeeScript compiler. This has actually been the biggest source of frustration writing CoffeeScript, is that there are places where ambiguities in the language can be accidentally introduced and you’ll get an error saying something along the lines of “unexpected statement start”. Then you have to hunt down the cause of this error.
As far as CoffeeScript being compiled to JavaScript causing problems with debugging, well, I haven’t been overly encumbered by it. Sure, the more expressive statements in CoffeeScript can generate a fair chunk of JavaScript, but that is precisely the tradeoff for making CoffeeScript more expressive, it is hiding a lot of the work that it is doing behind the scenes. However most of the statements you write in everyday CoffeeScript, with the exception of a few curly braces and semi-colons, compile almost 1 to 1 with their JavaScript counterparts.
But I think that it is the generated JavaScript that really scares people. They think of a ton of generated JavaScript and they cringe at having to debug it. But I think that it is rarely an issue, for a few different reasons:
- CoffeeScript doesn’t rename variables – If I put a watch in my JavaScript debugging tool for a particular variable, then that variable will get inspected, just as if I was using it in JavaScript (because in the end I am!).
- CoffeeScript generates mostly readable JavaScript – Despite the big chunk of code that Ryan’s comprehension example produced, I think it is still fairly readable. The example combined a comprehension, string interpolation, a boolean check, and assigned the results to an array. The resulting JavaScript is just a loop with an if statement.
- Console.log – I can use console.log in my CoffeeScript in the exact same way I use it in my JavaScript, and it works just fine.
- Debugger – I can still write “debugger” into my source and force the browser to break on a line. No, I don’t have to hunt and peck through JavaScript source to find where a line of CoffeeScript compiled to, this jumps me right to it. (If you have never written the “debugger;” statement into your JavaScript, you should try it one day)
What I think the problem really comes down to is tooling. If CoffeeScript was natively supported by the browser, you wouldn’t be asking for tools to view the generated ASTs, you would want a debugger. The fact that I can’t view CoffeeScript in the browser and set a breakpoint and debug at that level is annoying, but it isn’t annoying enough that I want to give up the expressiveness that CoffeeScript provides me.
Why Would I Use It?
Now that I spent all this time telling you that it doesn’t suck, I should probably tell you why you might actually want to use it! On a personal level I think that it has a cleaner syntax. I like its roots in Ruby and Python and reading CoffeeScript feels better to me. But I think the real power lies in its expressiveness.
It gives me features like classes, string interpolation, comprehensions, an existential operator, reasonable “for” loops, chained boolean expressions, everything is a value, predicative boolean expressions, etc… without taking away any of the flexibility and power that JavaScript gives me. For example, it has classes, but they are truly just syntactic sugar on top of JavaScripts prototypical inheritance mechanisms. I can even build up objects using prototypes in CoffeeScript just like I would do in JavaScript.
The list goes on and on. I could write a whole blog post about it, but the CoffeeScript website lays it out for you far better than I ever could.
If It Makes Your Life Better, Use It.
I know there are concerns about whether CoffeeScript will be around in 5 years. And honestly, I don’t know the answer to that question, but its inclusion in Rails 3.1 by default can’t hurt! I know that future versions of JavaScript will be better for CoffeeScript having existed. CoffeeScript is open source, and people today are writing a reasonable amount of code in it. I can’t imagine that in the future the CoffeeScript compiler will just up and die, if anything it will leverage future constructs in JavaScript and you will start to see the languages converge more.
When I want to use a tool, I always look at it and weigh the risks of using the tool versus the benefits. At the end of the day I think that the benefits that CoffeeScript gives me outweigh the risks, if you don’t agree, then don’t use it. But if it makes your life easier, and you’re not risking the farm by using it, then by all means have at it!
Loved the article? Hated it? Didn’t even read it?
We’d love to hear from you.
Compelling article. While I hadn’t read Ryan’s article, after seeing a few articles by Rob Conery on CoffeeScript I just didn’t see a good enough reason to use it and I figured it would be a bit challenging to debug.
Maybe it is because I haven’t jumped into Ruby or Python, though I have played around with each, that I don’t see enough benefit in a cleaner, more Ruby like, syntax. I still write C, C#, and PHP on a daily basis so I kind of like JavaScript being similar.
On another note, do you use CoffeeScript when writing Backbone.js apps? I’m working on my third Backbone app and I am finding it challenging enough debugging as it is without throwing CoffeeScript into the mix. Perhaps it’s not as big a deal as I think it it?
If you have some time I’d love to chat about how you structured your Backbone code when coding the Epic Win site. You can reach me on Twitter, @JustinBezanson.
One way I like to compare languages is by reference to a hypothetical language, L.
Imagine that L represents the best possible world for a developer, one in which every statement is clean, expressive, and clear. In L, making software do what you want is simply a matter of knowing what you want to do. By definition, you are maximally productive when using L, so long as you never make a typo and you know in advance what you want to do.
Now, compare L to a language at hand (say, P), and note the productivity differences:
* How much does P “raise the floor”? That is, how much productivity does P provide in the form of preventing errors (e.g. type checking, checking compile-time expressions for overflow, etc.)?
* How much does it “lower the ceiling”? That is, how much productivity does it subtract in the form of making you do extra work, provide XML manifest files, be more declarative than usual, etc.?
Then the best languages are ones that raise the floor as much as possible without lowering the ceiling. Languages that do that can catch a lot of silly mistakes, and they can help mediocre developers do just as well as productive developers.
Unfortunately, the reality is that languages that raise the floor a great deal often do so at the expense of lowering the ceiling. Java can be an enormous win over C++ for typical business applications, for example, but it cripples the productivity of your best developers. If you’ve ever worked in C# or Ruby, it feels like cutting through butter; working in Java feels like cutting through molasses.
In the more mature members of these languages, you typically find replacements for the lost productivity in the form of file templates/macros that you can use to start a new idea. Those are helpful, but they’re a band-aid and don’t address the real solution, which is to improve the language itself.
On this metric, JavaScript doesn’t raise the floor very much; it’s quite easy to write terrible code, and even worse, terrible code that is wrong but you don’t know it yet. But it also doesn’t lower the ceiling much either. You can be relatively expressive in JS, though there are many antipatterns.
You didn’t address in the article, but a big part of the reason you see a lot of vitriol about CoffeeScript is that some people think it’s better to focus on improving JS rather than on inventing a whole new programming language. With JS, there are some very obvious behaviors that could be eliminated (sometimes at the expense of backwards compatibility). These would raise the ceiling without lowering the floor, and make JS a much bigger win than it is now.
There are also some very smart people working on this already (see: JS.next, ES.next, etc.). So, why not use that as a starting point, instead of saying “well, it’s a lost cause; onto a new language, everybody!”? Imagine if everybody gave up C# 1.0 because it didn’t have generics, or Ruby 1.0 because it didn’t have mixins; you wouldn’t have anything near what we have today.
Great article.
My article was mostly a rant for my co-workers that struck a chord I guess, I’m really not the “anti-coffeescript” guy.
> I’ve found that CoffeeScript can definitely be more difficult to debug than JavaScript in some cases.
I think that’s what my article is about.
> CoffeeScript generates mostly readable JavaScript
I don’t want “mostly”. My point was that it takes an extra brain cycle (though small) to get over this “mostly”.
> I think it is still fairly readable.
Again, I don’t want fairly. I want to debug EXACTLY what I or the original author wrote, and save the extra brain cycle shuffling between languages. I admit its minor, but so is are mosquito bites, and they are irritating.
> I can use console.log in my CoffeeScript in the exact same way I use it in my JavaScript, and it works just fine.
I mentioned “I’m back to putting in console.log statements”. So, yes, my debugging has regressed to what is normal for you (I guess).
> I can still write “debugger” into my source and force the browser to break on a line.
Only in some browsers.
> The fact that I can’t view CoffeeScript in the browser and set a breakpoint and debug at that level is annoying
My point exactly. When I get a ticket with a bug, or I find one in my own code, I like to stay in the browser until I know what the deal is. It’s MUCH faster than switching between my editor and browser and refreshing and recompiling, etc. etc.
> there are places where ambiguities in the language can be accidentally introduced
So essentially you just rewrote my article 😛
The intro of my article said I just had some beefs to get off my chest, but that I _like_ writing CoffeeScript.
If I were debugging the CoffeeScript directly the language features wouldn’t bother me so much either, you just need a good style guide and adhere to it.
It’s unfortunate I went off on a tangent with the syntax, my real beef is debugging, but I’ve since learned from the comments section of my post that real engineers don’t have to debug, they just write specs that pass the first time in every browser.
@John
CoffeeScript *is* an attempt at improving JavaScript. It’s a way to write better JavaScript *now*, and not 5 years from now when all the browsers finally get support for JS.next or whatever the next revision of JavaScript is that rolls in all these great improvements everyone is working on. Ideally, sometime down the line you’ll be able to take all your CoffeeScript, feed it through a small conversion script, and get out nearly identical JavaScript that you can run in your browser and then never look back, but that time is a ways off. Until then, CoffeeScript represents one of the least disruptive ways to write nicer JavaScript.
Alternatives certainly exist, there are things like GWT, JSF, Dart, and others, that allow you to write in different languages and get some kind of JavaScript blob out of the other end that can run in browsers. The problem with just about every other “X to JavaScript” language floating around out there is that they aren’t just an alternative syntax for JavaScript like CoffeeScript it, but entire different languages that have Runtimes and non-trivial mappings from source to generated code. Look at the much maligned example of the Dart “hello world” example that compiles to something like 67k lines of JavaScript because it includes an entire runtime library.
@Kyle: For the record, I use CoffeeScript and think it’s a fine language. I’m just pointing out that the criticisms that were addressed in the article are somewhat deeper and more substantial than just “oh, the syntax is annoying” or “bad developers can write really dangerous code with CS”.
And yes, Dart is a silly answer to this problem.
As a professional javascript dev and a hobbyist coffeescript coder, I share some of Ryan’s concerns. If you use coffeescript on a daily basis, you can be immensively productive with it, but if you touch your code every two weeks, you suffer from a more severe productivity penalty than with ordinary Javascript. This penalty consists of all those tiny caveats that payed off the tight and nice syntax.
If you are an infrequent cs coder, you find yourself making the same mistakes over and over again (especially whitespace issues) and you have to fight with less helpful debugger messages than in pure javascript.
Nevertheless I’m confident that some of those issues can be adressed (e.g. .coffeescript -> javascript line number matching in the debugger) and that Coffeescript 2 will also be “friendlier” to occasional developers.
Debugging your own code is one thing. Using CoffeeScript in a team environment is a pain in the ass for my tiny brain. The fewer context switches the more productive I am. Until JavaScript becomes Assembly and CoffeeScript can be debugged in Firebug, etc I’ll be sticking to JavaScript.
Thanks for the article, I found it very informative.
I’ve used CoffeeScript for some small/personal applications.
I’ve found that looking at the generated JavaScript while debugging is actually teaching me a lot about how to write good quality JavaScript .
Before using CoffeeScript, things like “this” binding, extend, etc were difficult for me to understand, coming from a Python/C# background.
I’ve found that seeing how simple/familiar concepts like class inheritance in CoffeeScript map to JavaScript has definitely improved the quality of JavaScript that I write at my day job, where we don’t use CoffeeScript (yet).
@Matthys That is a good point. I think that people can definitely learn a thing or two about writing good JavaScript by looking at the JavaScript generated by the CoffeeScript compiler.
Does anyone know file size comparisons for compactly written JavaScript vs CoffeeScript? I’ve heard CoffeeScript has a less than negligible file size bump in deployment.
It didn’t take me very long to love CoffeeScript. About the only thing I don’t like about CoffeeScript is that, like virtually all languages, it’s formed some pretty opinionated cults on both sides. You don’t have to like it. At the same time, liking or not liking it doesn’t make you a good or bad programmer. It’s a matter of taste and preference.
As a regular Ruby coder, I love CoffeeScript. It actually requires LESS context switching for me because the syntax and idioms are similar to my main language.
I have yet to have a serious debugging issue. When native debuggers are available (and it looks like they’re coming) I’ll be a lot happier, but thus far the amount of time saved using “for own” more than makes up for the minor inconvenience caused by the current state of debugging.
With all of that said, if you’re going to be a good CoffeeScript programmer—right now anyway—you need to understand JavaScript. Ironically, one of the biggest problems with JavaScript itself is that a huge number of people using it don’t really understand it beyond a hack’n slash toy. On that note, JavaScript design patterns map directly to CoffeeScript.
I really, really like CoffeeScript. I would have preferred “end” to close blocks rather than relevant whitespace but again, this is purely a matter of taste.
Since I really learned JavaScript, it’s a language that I love using but hate the syntax. CoffeeScript has turned it from a tool I tolerate to one I enjoy.
Hi Justin, I think we are on the same page when it comes to the debugging aspects of coffeescript. You list a couple features of coffeescript that make it not-so-bad to understand the javascript, but obviously some degree of tooling would make it an even more pleasant experience.
So, let me apologize in advance for a shameless plug, but I believe it’s on topic.
The hardest thing about dealing with CS and JS simultaneously is that CS doesn’t generate source maps to begin with, so even if the browsers themselves had better support for compile-to-JS languages, CS would still be behind. This is mostly being addressed via the epic Issue 558 in github. Various patches have been proposed, but there’s a bit of a chicken/egg dance going on, since the browsers don’t yet support source maps (although they’re close, too!).
I decided to just build my own tooling until the compiler catches up. Given a .coffee file and a .js file, it’s pretty easy to reverse engineer the transcompilations, at least enough of them to get down to small chunks of code (think 20 lines or less). Here is the tool that I wrote:
https://github.com/showell/CoffeeScriptLineMatcher
It’s an interim solution for viewing all the .coffee files in your project, and you can see the .js files side by side. Even though it’s a bit of a stopgap, I think the overall tool will be useful even as CS/browsers start upgrading their tooling.
Thanks for the excellent article.
Awesome! I will definitely have to check that out.
It amazes me how often these type of arguments, er, discussions completely omit context. If you are writing a lot of cookie cutter reports that use basic javascript I could see coffee being a great aid to some. But if you’re writing cutting edge js to do things nobody has ever done, it seems ridiculous.
I’m not an expert on js, not even close, but it seems like CoffeeScript is writing JS in a classical sense and not the prototypical ?