I love the idea of using other open source projects and their test suites to test the tool. It feels like this approach could be useful for other projects as well. For example, what if you could test changes in your library by running the test suite of a couple of projects that depend on it?
> Rust has a standard testing facility that most Rust crates use, and Rust has a standard repository of Rust crates in crates.io. GitHub further contains repositories of Rust crates that are not published to crates.io.
> These factors allow us to treat the entire world of open source Rust code as our test suite.
> As new nightlies and betas are published, we use the cargobomb tool to test this corpus of Rust code (as of 2017/07/10 over 13,000 crates) against both the stable release and a nightly or beta release, comparing the results for regressions.
CoffeeScript added some useful features, like destructuring assignments, and some syntax sugar for objects, loops, etc... but it also made some choices that in my opinion are bad:
- Making delimiters optional like parentheses, brackets, semicolons... in addition to implicit return statements: makes programs hard to read if abused. Makes code formatters get confused and corrupt your code.
- Not being able to distinguish an assignment from a variable definition: causes identifier typos to become new variables.
This implicitness makes programs error prone in ways that are hard to verify and work with. Plus, needs to be transpiled and you will need sourcemaps.
In the end, the benefits are not worth it, even back during the time it was created.
Another pain is (was?) debugging. This might have changed since but back when I tried and rejected using it. But back then, if you had an error at line X it would report the (compiled) JavaScript line rather than the CoffeeScript line - meaning you'd need to figure out which CS code generated what line of JS code in order to hunt down and fix issues.
The first problem is easily avoided with a few style guidelines. If a feature exists it doesn't mean it must be used. You can configure CoffeeLint to avoid confusing constructs.
The second problem didn't turn out to be as big as I thought. I was bitten by it about a couple times a year, and every time it was symptom of too long functions or too many closure nesting.
Transpiling and source maps are not a problem. Small changes in my code takes 200 ms to recompile with source maps, with webpack in watch mode (projects are ~20k lines). And when I start a new project I just copy the webpack config from the previous one (with cli switches for several features).
> There are many transpiled languages working on-top of js.
That's only because JS is literally the only language allowed inside the browser (back in the day you had at least two other possibilities: ActionScript and Java. However, both Java applets and Flash-based sites fell out of favor (for good reasons)). No matter how well designed a language there's always going to be a particular combination of problem domain + programmer type for which the language does a poor job. And that's assuming the language is well designed in the first place, which is at least debatable with JS.
It's also worth noting that the JS itself tends to be transpiled to itself with Babel or other tools. There's nothing inherently bad about transpilation, and source maps solve the most serious problems with them.
> As many things in JS world, they tend to end up as an abandonware.
That's not really the case. After initial development, once a transpiled language implements all the features an author wanted, there is little more to do with it. New features of JS, which would have to be implemented in a transpiled language, are few and far between. The last such features were generators, and most of the "abandoned" transpiled languages had them quickly implemented.
In other words, there's a difference between "abandoned" and "feature complete and in maintenance mode". While some transpiled languages are indeed abandoned, others are not - there's simply not that much to do with them, aside from fixing bugs.
> This all make long-term mainainability of large JS + "featurelang" projects hard.
Why? Most of the "featurelangs" are stable and were stable for a couple of years at least. You can reasonably expect CoffeeScript code from 2011 to get properly transpiled today. What exactly makes it hard to maintain the code written in such languages, compared to pure JavaScript?
> [TypeScript] had initial burst of interest, but seem to be waning now.
I believe TS is here to stay, even if its popularity diminishes a bit. There are programmers who want their languages statically typed and that's one thing you cannot, in any way, emulate in pure JS. TS is only going to get replaced once the Web gets first-class support for other languages, but that's not happening anytime soon.
> no featurelangs in my projects has paid off massively whenever I took post-delivery maintenance and support contracts.
Again, what problems did you have with long-term maintenance of transpiled code bases? I never had any and, if anything, updating JS code over time to take advantage of its new features was a bigger pain than having all those features available since 2009.
It seems that a project like TS that restricts itself to adding future JS features and types should be different. To strip the types, and be left with plain javascript, just run it through typescript.
Other types of businesses choose to maintain large chunks of code in a "legacy language" and paying people to maintain it overtime, at a cost (e.g., banks and COBOL).
Let's say there's a COBOL -> C/C++/Rust/someotherfancylang transpiler. Maybe there is one, maybe not. Would it make sense for a bank to invest in something like that, or is there really no incentive to do so? Why would there be an incentive for a startup to do so, but not for a bank?
I have no specific knowledge, so take this with a grain of salt.
The article comments "Yuck. It works, but it certainly wouldn’t pass code review. Here’s what we really want:"
This shows that what's needed isn't simply a transpiler, which only needs to be technically correct according to the language semantics, but rather a transpiler which generates maintainable source code.
The "--loose" option gives another example of how maintainability might be important enough as to prefer a possibly incorrect transformation.
CoffeeScript and JS are semantically quite similar languages. COBOL is nowhere near as close to C/C++/Rust/etc. This makes it much harder to generate maintainable transpiled code.
Finally, the author's company developed "tools to help biologists coordinate experiments, analyze and work with DNA". A bug in this sort of environment has less severe consequences than (say) in the banking industry, where there are laws and regulations to follow, and where people's money might be on the line.
That is, banking has a lower risk tolerance for the sorts of errors that might sprout up in large-scale automated source code conversion.
I believe microfocus iirc has a cobol to java transpiler. But when we looked at it, it was decided it was too high of risk. At the millions loc level automated tools add another level of risk.
This is an interesting article. However, it makes one important error.
It compares the cost of hand translation with the cost of auto translation, but fails to account for any time developing the translation tool, as it was done "in my own time". Clearly not a valid comparison.
The author has also done lots of free ot-of-hours work for his company which he doesn't seem to realise.
In quite a few companies this would also cause problems with IP ownership, particularly due to alignment between in-work and outside-work work.
> fails to account for any time developing the translation tool
There are (at least) two ways of looking at it:
1.) If you're an open source project or a company with a large amount of CoffeeScript that you want to move to JavaScript, should you convert it by hand, use decaffeinate, or take some other approach, and how long should you expect it to take?
This is the viewpoint I was focusing on because that's the real situation people are in today now that decaffeinate exists and is stable. Hopefully the article convinced you that decaffeinate is the best tool for this job, but that you should still expect tens or even hundreds of hours of investment, depending on the size of your codebase, the level of code quality you're targeting, and the amount of risk you can accept.
2.) If you're a project or company with a codebase in language A and you want to convert it to language B, should you develop an in-house translation tool for that purpose?
I think that in most cases, the answer is "no", unless you're a very large company, and this case is no exception. (Really, it depends on many factors, and tools like jscodeshift are a great way to lower the barrier to entry for large-scale codebase changes.) Not only did decaffeinate take a long time to develop, it was unclear how well it would work and how safe it would be. And, frankly, CoffeeScript to JavaScript is one of the easiest programming language conversions you can do.
I mostly worked on decaffeinate because it was fun, rewarding, and educational, not because it was meant to be an efficient use of time for my company in particular. But given the number of people who have said "thank you" and the number of open source projects and companies that have already used it, hopefully it's a net benefit for the world.
Not just IP problems, but also encourages bad work habits. His company should of sponsored this work if they felt it was in their best interest. This type of hero behavior burns people out and keeps open source projects with very limited resources.
Edit: To the author because he replied once to this thread: I hope in the future you feel comfortable in the future asking for time to work on open source projects during company time and realizing that you doing work that benefits your company for free is not in your or your companies best interest long term. If you feel that they would be unwilling to do this during work hours then push for something like this: https://futurice.com/culture/sponsoring-free-time-open-sourc....
Thanks for the link, that Futurice policy is really cool.
I certainly felt comfortable working on decaffeinate a little bit during work hours, and my company was fine with it, but I think the amount of time it needed was more than a small startup should be willing to invest. I would have pushed back if someone wanted me to work on it full time until it was done, and I wouldn't have worked on it if it was only an internal tool. Agreed that having a more formalized company position on open source work would be nice. For now it's just "use good judgement".
I think in an ideal world, there would be lots of companies that each explicitly invest a little bit into these types of projects. It's already happening to some extent, but I think the incentives are hard to get right (especially for projects with a high chance of failure), and plenty of popular projects probably don't get enough attention, especially from companies that rely on them.
When I had to convert a CoffeeScript project to plain JS, I basically took the output from the coffeescript compiler, formatted it using prettify/standard and fixed up any obviously stupid things that the coffeescript compiler does by hand. Took only a few days, but it wasn't a large project either.
Makes sense, I've certainly heard of people taking that approach. When I started working on decaffeinate, Prettier didn't exist and ESLint autofixing could only handle very simple cases.
Out of curiosity, were you using CoffeeScript 2? As I was doing research for this post, I noticed that the CoffeeScript 2 output was pretty good compared to what I had seen with CoffeeScript 1, although I think decaffeinate still gives better results in many cases. CoffeeScript 2 also had some small breaking changes, whereas with decaffeinate I needed to stay true to the exact language semantics, so arguably decaffeinate is safer than CS2 when run on a CS1 codebase.
I think it is quite funny how a tool to turn proper code into the mess that is ESxx can become so popular. I'm still using Coffeescript 2, it's awesome :)
I am using an even more minimal subset of CoffeeScript 2, basically classless, and love it. I can't find a sane reason to hand-write ESxx.
I complement it with Rust as needed, which is the only language that justifies having a verbose syntax.
Those two couldn't be farther apart, but their combination covers an extremely wide spectrum of programming tasks. From prototyping, to incrementally improving the robustness and performance as needed.
jashkenas did a great job, and CS2 is a very elegant and ongoing effort.
The JS tools/libs ecosystem really reminds me of crypto currencies. There's a million of them to choose from and if you jump on one during the height of its popularity you just end up losing a bunch in the crash that inevitably follows the pump. Should have just stuck with plan JS / those 50 bitcoins you had back in 2012...
CoffeeScript is a match in the heaven with JSX IMO. You for example no longer have to face the bracket and semicolon hell. (Unless you have StandardJS or ESLint, which is pretty much default for all devs)
There’s also implicit return, so the code pattern is prettier, no more return (<JSX />)-ish thingy, and it feels closer to a template, but it is a boon and a bane at a same time since some devs got used to return like that.
Before CS2, we have to stick with coffee-react-transform, which is hacky and unmaintained and old. It transpile JSX to createElement directly, not good.
With CS2, you can write JSX expressions directly. A large subset of JSX is parsed, and only bracket/property expression will be transformed by the compiler, then processed with Babel. This is safer, more spec-conforming, and I could do some tricks like babel-preset-react-optimised.
CSX gets even better if you have MobX! It feels like PHP+Rails all the way while you’re also enjoying the MVVM ride. I'm already loving it and using it in my production heavily.
CoffeeScript is great, man. It is influential to ES6. Don't give up on CS yet. The ecosystem, however, is already shifted to JS. It took years to revive CS I guess.
I guess the main reason to migrate off CoffeeScript is that popular JS tools like for example Serverless Framework do not maintain their CoffeeScript plugins.
I have about 30 old AWS lambdas written in CoffeeScript, which I tried to convert to serverless framework.
I tried two serverless-webpack-coffeescript plugins and none of them works.
Fixing them requires to know both serverless framework and webpack internals and their plugin APIs are constantly evolving without regard to backward compatibility.
It was much easier to either add a script that runs transpiling before running "serverless deploy" or just to port the source code to JS.
Decaffeinate make this even easier by porting to JS6.
reply