20 ms·
Dropbox dives into CoffeeScript
- kevincennis 14y agoWait, they're looking forward to "Native CoffeeScript support in browsers, so that during development, we can avoid the compilation to JavaScript altogether."? Is there something I don't know about?
- MatthewPhillips 14y agotldr: > Disclaimer: we love Python, and it’s Dropbox’s primary language, so we’re probably biased.
- lowe 14y agoheh, I included this line because it's true, but that whole section is about why "use coffee because you like python" is the wrong tldr.
- MatthewPhillips 14y agoThe rest of the article is about how you prefer CoffeeScript syntax, so how is that tldr wrong?
- scott_s 14y agoBecause an accurate summary would actually summarize what they said, not just list their bias. I would summarize it as, "The Dropbox team prefers the readability of Coffeescript, the conversion took one week, they reduced the lines of code in their codebase by 20%, and there was no impact on functionality."
- autarch 14y agoI mostly do Perl, but I vastly prefer CoffeeScript to JS. The significant whitespace thing is actually a negative for me with CS, but it eliminates so many JS annoyances that it's worth putting up with.
- GeZe 14y agoIf they like Python, maybe they should have tried LiveScript (http://gkz.github.com/LiveScript/ http://gkz.github.com/LiveScript/) - a descendent of CoffeeScript. Unlike CoffeeScript, but like Python, it has proper list comprehensions `["#x#y" for x in [\a \b] for y in [1 2]]` which I think is very important to any Python fan, dict comprehensions, and (more minor) you can use `is not`, like in Python, instead of `isnt`. (Along with many other features.)
- seangransee 14y agothis is great news! for people who prefer python-like syntax, coffeescript is a no-brainer. sites like js2coffee.com make it really easy to make the transition.
- sync 14y agoBig, big fan of CoffeeScript and glad to see Dropbox hopping aboard. That being said, some of their examples are lackluster. @originalStyle = {} for k in ['top', 'left', 'width', 'height'] @originalStyle[k] = @element.style[k] Should really be something like: @originalStyle = ['top', 'left', 'width', 'height'].reduce (hash, position) -> hash[position] = @element.style[position] hash , {} ... though that shows off some CoffeeScript warts. Also, Sharing = init: (sf_info) -> for list in [sf_info.current, sf_info.past] for info in list @_decode_sort_key info Why aren't they using CoffeeScript classes? class Sharing constructor: (sfInfo) -> ...
- gfodor 14y agoOn the former, I think you'll find most people find their implementation more readable/idiomatic, and the second case I'd guess is because they were doing a port and so probably didn't want to make too many semantic leaps.
- alexangelini 14y agoYour first example is the exact reason I dislike CoffeeScript. Sure it's clever, but at a glance it is much harder to determine exactly what's going on.
- rgarcia 14y agoReally they should just use underscore: @originalStyle = _(@element.style).pick ['top', 'left', 'width', 'height']
- deleted 14y ago[deleted]
- csense 14y agoParent's reduce() example is harder to read than the original, and about the same length. If CoffeeScript had dictionary comprehensions like Python 2.7 / 3.x, we could make the code shorter while preserving and easier to comprehend: @originalStyle = {k : @element.style[k] for k in ['top', 'left', 'width', 'height'} Unfortunately this syntax was proposed and rejected [1]. But with a simple to_hash library function, you can achieve something similar [2]: to_hash = (pairs) -> hash = {} hash[key] = value for [key, value] in pairs hash @originalStyle = to_hash ([k, @element.style[k]] for k in ['top', 'left', 'width', 'height']) [1] https://github.com/jashkenas/coffee-script/issues/467 https://github.com/jashkenas/coffee-script/issues/467 [2] https://gist.github.com/2271874 https://gist.github.com/2271874
- Ygg2 14y agoIn our case, we avoided this problem entirely by instrumenting our server code: whenever someone reloads a Dropbox page running on their development server, it compare mtimes between .coffee files and compiled .js equivalents. Anything needing an update gets compiled. I wonder how did they achieve this? Is this a feature of node.js or is this like an automated build system? I suspect the latter.
- reuben_m 14y agoThey said exactly how they did it, it's right there in your quote: when someone reloads a page running on their dev server, the server checks if the CS file has been modified and triggers the compilation… So no, it's not a build system feature, it's a server feature.
- jlongster 14y agoThis sounds so much like some geeks wanting to hack. That's it. There isn't really a good reason to convert a codebase with tens of thousands of lines of code from js to CoffeeScript. Not that there's anything wrong with that. But seriously, every single problem with javascript they mention is never a problem for javascript developers. You simply learn what's broken, and deal with it. Dealing with it is usually one line of code (or even less), making sure you just use ===, etc. It's really not a problem. These kinds of posts smell a little like FUD to me, which is what I have a problem with.
- gfodor 14y agoTo a lot of people CoffeeScript promotes the intangible benefit of happiness. (Similar to ruby.) If working in CoffeeScript makes everyone's work much more enjoyable (for whatever reason), with minimal cost, isn't it worth it? I, for one, want to minimize the amount of things I need to "deal with" at work, be it shoddy programming language workarounds or a half-broken coffee machine.
- MatthewPhillips 14y agoNo, the parent is correct. JavaScript developers do not lose any sleep because '1' + 0 = 10. We learned to do integer math with integers and moved on. We learned to just use === and moved on. The Dropbox devs apparently didn't want to go through that learning curve, which is fine, but rewriting your application in another language just so that you don't have to look at semicolons is a big bikeshedding mistake. Writing new code in CoffeeScript and only rewriting legacy code as needed would have been a more sane way to transition.
- scott_s 14y agoHow can you say it was a mistake when it only took one week? There was a cost, they paid it, now they can reap the benefits. I program in C++ extensively. I "deal with it" a lot. I write things like this all the time: MapType::const_iterator it = map.find(x); if (it != map.end()) { // x is in map, process it } I've done it for years, I know how to do it, and there are great benefits to getting iterators back from my data structures. Yet, I always feel a warm fuzzy when writing data processing scripts in Python, and I get to say: if x in map: # x is in map, process it My point: even though one can have learned to "deal with it," there can still be a benefit to not having to deal with it anymore.
- geon 14y agoThe first comparison is not fair. Audio is 1D, while code is 2D. Obviously CoffeeScript is less cluttered, but JS is nowhere near as bad as the audio makes it sound.
- ivanstojic 14y agoI'd say it goes further than that, as this isn't 1992 any more. I can't possibly find code pronunciation to be of imperative importance because I rarely debug code over the phone. At any given time, I'm likely to have at least two of the following with me: a phone, a tablet or a laptop. Just e-mail me the code. Make a gist with the problematic section. Push it to a branch in our git repo so I can take a look at it myself. IM it to me. Don't read it to me.
- aaronbrethorst 14y ago"I had to be done [with Javascript] in ten days or something worse than JS would have happened." I've heard this quote from Eich several times now, but I've never heard what the "worse than JS" alternative would have been. Anyone know?
- tikhonj 14y agoProbably something like Java. Or maybe a hybrid between what JS is now and Java.
- calibraxis 14y agoHe said it right afterwards: "Something like PHP only worse..." (http://www.jwz.org/blog/2010/10/every-day-i-learn-something-new-and-stupid/#comment-1021 http://www.jwz.org/blog/2010/10/every-day-i-learn-something-...)
- deleted 14y ago[deleted]
- pjmlp 14y agoAs I only use the native application, I can care less.
- bostonaholic 14y ago}); is not a line of code. Please stop counting it as such. Here's a good rule of thumb: "If it can be moved to the line above, without any other changes, it's not its own line of code." The argument that CoffeeScript saves countless }); }); } } is invalid, IMO. I would even argue that function definitions are not lines of code. Example: (ruby) def foo end 0 lines of code. BTW, I'm not a CoffeeScript hater, just trying to level the playing field.
- untog 14y agoThe argument that CoffeeScript saves countless }); }); } } is invalid, IMO. I agree that counting }); as a line isn't necessary, but CoffeeScript saving you doing any of that is a very valid benefit. It cleans up code dramatically- ignore line numbers and just think about all the extra stuff that ends up surrounding multiple function calls.
- thezilch 14y agoI'm thinking it doesn't happen that often, and I would counter with having you think just how much more cognitive effort is used in parsing and debugging the syntax of CS. Remember, debugging and reading "old" code dominates our days, so it doesn't add up for me. As well, if you and the many others that like to claim keystroke reductions, there is no difference in "fu<tab>" for "->" and numerous other comparisons.
- untog 14y agojust how much more cognitive effort is used in parsing and debugging the syntax of CS Have you tried CS? It's far more readable, by virtue of not having "function() {}" splattered all over the page. I don't care/worry about keystroke reductions, I care about readable code. The lack of curly brackets and addition of significant whitespace absolutely does make for more readable code.
- thezilch 14y agoSure, I've tried it. Function calls are never splattered all over my page, so I don't have to care about that. And at best, it only allows me to cram more crap onto a single line, which is also not often helpful. Instead, I get to -- have to -- think about and end every function with something sane, in the event, for example with jQuery's .each(), I can't have my function magically returning false -- the last evalutated variable -- and terminating the each mapping. My code already has significant whitespace; it's required by styleguide and linting. CS has prolific issues with whitespace usage, especially when it comes to parsing function arguments and lines broken over multiple lines. Just look through this or any other thread on CS being pushed. CS often has mind fucks, and I'd rather have to ignore a couple lines with } on them. Note: I mostly write in Python, if that gives any indication into how I very much enjoy significant whitespace.
- funkiee 14y agoIt's nice to see some more prominent companies using CoffeeScript that people could point to if they ever wanted to convince their boss. Did any of the other Dropbox employees have a hard lead-in time getting used to the syntax in CoffeeScript? Would you say you run into a lot fewer syntax errors when running validation now?
- BadassFractal 14y agoI'm a little surprised by the number of negative comments in this thread accusing the three Dropbox engineers of wasting company time.
- adgar 14y agoWhy? It seems like a complete waste of time to this typical software engineer with 100x more objectives than time. Why not convert all your Java code to Scala? Because you have real work to do and reskinning your existing code provides no benefits, that's why. If it works, don't rewrite it, go make more stuff work. Maybe the dropbox folks don't have anything else to do, though. Not my place to judge.
- mamcx 14y agoImprove the codebase (make it small, cleaner, more easy to read, and fix issues of pastime) is NOT a wasted time. Not necessarily the BEST USE of time at a given moment, but dedicate some time to refresh the code with better tools, better syntax, better libraries, etc is a excellent way to move forward. For a related sample, with obj-c I move to ARC ASAP, and plan to introduce the syntax literals as soon as possible. I certainly move the whole app codebase to python if exist a cheap way -and still 100% interface compatible to the coccoa-api - as like move js->coffescript for sure! Is masochist persist in a old way just because is harder. Like when some refuse to upgrade the same language codebase to improve things (for example, I will move to LINQ, Lambdas, parallel code, async in C# as I move along) IF the change provide some advantage - reducing lines, better API, more performance, better clarity, etc - I tough constant -but careful- refactoring of a live project is very healthy. Is better doing it when the project is moving, that wait until a major event happend in the industry -like what happend to my competitors, still on .NET 1 / VB Classic- and suddenly, your move is damm hard, too costly, and you have no skills in the "new thing". I certainly think something that replace or massively fix JS (including, a better JS) will be very usefull. If is ok to move from inline styles to CSS, and from HTML to HTML5, then move from JS with issues related from years of hacking-along-design to anything else, like CS, is a good effort.
- 14y ago
- dustingetz 14y agothe question that should motivate a change like this: what does new-language let your team accomplish that you can't accomplish with old-language? question isn't answered in post, the answer is probably somewhere along a 2x increase in the complexity the same team can handle. i dunno if it is worth disturbing an existing codebase and the QA cost of making sure you didn't introduce any defects. meh. where i work, we have maybe 100k lines of javascript, and its not really a problem other than lack of types when refactoring imperative code, nothing near the scope of the problem of Java's lack of higher order functions.
- supersillyus 14y agoI agree with them on the readability issue mostly, but I don't understand the preference for parens-less function calls, especially where there are arguments. Maybe it's a matter of training, but @_update_status_position(e, files) looks much clearer to me than @_update_status_position e, files
- dougbarrett 14y agoI agree, and I'm pretty sure that you can still use parentheses in coffeescript for this very reason.
- latchkey 14y agoIt's possible in any language to write incomprehensible code. I wish that for single lines like the OP's example, the parentheses were required, but I can see how in CS making them optional for multi-lines is kind of necessary. Like when the last argument is passing in a multiline ->
- stdbrouw 14y agoThe consensus seems to be gravitating towards (@_update_status_position e, files) among CoffeeScript coders whenever there's a need for disambiguation. Also, it really depends. I bet that print statements don't look weird to you even though in most languages they don't use parens.
- crazygringo 14y agoThe thing that will really bite you is when you call a function: some_function arg_a And then later on, decide it doesn't need an argument after all, and simply delete it: some_function And then discover it doesn't work, because you have to remember to add the parentheses back in: some_function() It's the little inconsistencies like that which keep driving you nuts... :)
- tborg 14y agoI just opt for parens every time. I really think they shouldn't ever be optional if in some cases they are mandatory. That this is a matter of personal style is somewhat frustrating.
- crazygringo 14y agoWhere I work, we moved the project I work on to CoffeeScript about a year ago, and I've been using it ever since. Putting syntactic sugar aside, while some things are very welcome (list comprehensions, ===, ?), there are two main reasons why I would be wary of using CoffeeScript again: 1. Complete lack of documentation for syntax. Because there are basically no more braces and parentheses, CoffeeScript just tries to guess what you're doing, as far as I can tell, based on a bunch of internal heuristics. Unfortunately, there's no way for me to learn how to write parseable code without constantly pasting into the coffeescript.org site, and seeing if CoffeeScript understands it or not. This is the first language I've ever used where the syntax rules are essentially unknowable, and a lot of time gets wasted trying to discover them through trial and error. 2. Unexpected side effects. For example, functions return the last evaluated value by default. If you're using $.each(), and your function's last line is something that returns false (like a separate function you call), then your $.each() loop will terminate unexpectedly early, since jQuery does that when it receives a false. So CoffeeScript isn't just a wrapper around JavaScript, but it really changes its behavior. Another example: CoffeeScript gets rid of function hoisting. A significant JavaScript feature, completely gone. I personally am slower to code in CoffeeScript, because I know JavaScript 100% inside and out, but with CoffeeScript that isn't really possible, because so much of its implementation is undocumented. I mean, many times you're forced to end a line with a backslash in order to continue it, and even the existence of that necessary feature isn't mentioned once in the docs. But a lot of people seem to love the syntax, and that seems to outweigh the negatives for them. I personally don't find JavaScript that ugly, but coding in a language I can't ever fully understand gives me a huge headache.
- latchkey 14y ago#1 I agree, making stuff optional was a bad design decision. It encourages people to write code in different ways and makes for unreadable messes if coworkers aren't religious about how they format things or they do things differently than you do. #2 has definitely bitten me, but I see that less of a failure of CS and more of a failure of the design of $.each(). The case is pretty well documented in CS though... the last code line is 'return'ed... if your code unexpectedly returns false, then really you are just bitten by the design of $.each().
- lucian303 14y ago"We’ve heard many arguments for and against debuggability, and in the end, we convinced ourselves that it’s easy only after jumping in and trying it." So, in other words, you have only your own opinion and at best one (1) anecdotal experience. Congratulations! You've failed to prove your point from a logical perspective, let alone anything more!
- gfodor 14y agoI didn't get the sense they were trying to convince anyone, just pointing out why it makes sense for them.
- jackfoxy 14y agoSpeaking as someone who has managed coders writing far more lines of javascript than I will ever write, this is a better articulation of my belief that javascript should be generated from another language (CoffeeScript being the leader) than I could ever propose. Thanks Dropbox! This post should be read by everyone who writes or manages those who write javascript.
- malandrew 14y agoYou guys should use MD5 digests of files instead of mtime for file change comparison. mtime works fine until you want to add other steps that are dependent on the mtime of ephemeral files occuring previously in your process. Steps such as minification, uglification and comparison for uploading to a CDN all become a bit more complex if mtime is used since every compile step has the tendency to modify mtime so recompilations cascade through the process causing at best unnecessary processing and at worst weird edge cases if the order of middleware isn't taken into account (the middleware issues can be avoided with precompilation before production.
- dotborg 14y agoCtrl+Shift+F - does it work with CoffeeScript in Eclipse? oh wait, no semicolons :/
- AndyKelley 14y agoThe middle code example can further be broken down[2] by using coco[1] instead of coffee-script. JavaScript: this.originalStyle = {}; ['top', 'left', 'width', 'height'].each(function (k) { this.originalStyle[k] = this.element.style[k]; }.bind(this)); Coffee-script: @originalStyle = {} for k in ['top', 'left', 'width', 'height'] @originalStyle[k] = @element.style[k] coco: @originalStyle = @element.style{'top', 'left', 'width', 'height'} coco also solves a rather nasty variable scoping issue[3] [1]: https://github.com/satyr/coco/ https://github.com/satyr/coco/ [2]: http://satyr.github.com/cup/#c:@originalStyle%20=%20@element.style%7Btop,%20left,%20width,%20height%7D http://satyr.github.com/cup/#c:@originalStyle%20=%20@element... [3]: https://github.com/jashkenas/coffee-script/issues/712 https://github.com/jashkenas/coffee-script/issues/712
- kbronson 14y agoAnd what about the conectivity with the previously existing deplyoments?
- skilesare 14y agoI tell my prospective clients that if their contractors/employees are still programming in js then they are stealing from them. Coffee Script is clearer, more concise, more maintainable. It has made me 5x more efficient in writing code (just the reduction in scrolling is a massive time savings) and I've seen similar results with my developers. It takes about 2 days to learn and has a significant long term benefit. Switch.