It's 2020 and I'm Still Using Coffeescript

March 10, 2020 by Steven Ng

Get Off My Lawn

I find that technical choices can be an especially polarizing topic among techies, especially with the newer generation.

While tech has never been immune from the "smartest guy in the room" syndrome, programming language debates can often be fatiguing to watch, and soul sucking to engage in.

So here's my old geezer "you don't know how good you have it" lecture. When I was coming up in the tech industry three decades ago, there were only a handful of programming languages you could get gainful employment in. It was usually a some variant of C, a mainframe language, Java, or for a time Visual Basic. Everything else was dismissed by the smartest guys in the room as a "toy language".

Today, you can get gainful employment in a wide variety of languages. In addition to the old standbys, Python, Ruby, Javascript, Typescript, Erlang, Go, Swift and a pile of other languages are pervasive and popular. I think it's great that there are so many acceptable language options today.

If you've been watching the Javascript world, you'll probably notice that everyone in the know has jumped onto the Typescript bandwagon over the past few years.

I don't have any quibbles with Typescript, but I haven't jumped on that bandwagon... yet. I'm still using Coffeescript. If you're not familiar with Coffeescript, it's a language written in Javascript that compiles into Javascript. Wait, what?

Coffeescript

This description will date me, but Coffeescript is essentially Javascript shorthand. It lets you to write Javascript with a Ruby-ish/Python-ish syntax. Coffeescript is sweetened by a pack of syntactic sugar resulting from the elimination of semicolons and braces as well as the improved readability of nested logic using indented whitespace.

For example, this Coffeescript snippet:

palette =
  "gray" : ["#dee2e6","#ced4da","#adb5bd","#868e96","#495057","#343a40","#212529"]
  "purple" : ["#e5dbff","#d0bfff","#b197fc","#9775fa","#845ef7","#7048e8","#5f3dc4"]
  "blue" : ["#dbe4ff","#bac8ff","#91a7ff","#5c7cfa","#4c6ef5","#3b5bdb","#364fc7"]
  "green" : ["#c3fae8","#63e6be","#20c997","#12b886","#0ca678","#099268","#087f5b"]
  "yellow" : ["#fff3bf","#ffec99","#ffe066","#ffd43b","#fcc419","#fab005","#f59f00"]
  "orange" : ["#ffe8cc","#ffc078","#ffa94d","#fd7e14","#f76707","#e8590c","#d9480f"]
  "red" : ["#ffe3e3","#ffa8a8","#ff8787","#fa5252","#f03e3e","#e03131","#c92a2a"]

colors = Object.keys(palette)

shades = ["lightest","lighter","light", "", "dark", "darker", "darkest"]

foreground = (shade,background)->
  color = "#ffffff"
  switch shade
    when "lightest","lighter","light"
      color = "#495057"
    when ""
      if background == "yellow" then color = "#495057"
    when "dark"
      if background == "yellow" then color = "#495057"
  color

Compiles to this:

var colors, foreground, palette, shades;

palette = {
  "gray": ["#dee2e6", "#ced4da", "#adb5bd", "#868e96", "#495057", "#343a40", "#212529"],
  "purple": ["#e5dbff", "#d0bfff", "#b197fc", "#9775fa", "#845ef7", "#7048e8", "#5f3dc4"],
  "blue": ["#dbe4ff", "#bac8ff", "#91a7ff", "#5c7cfa", "#4c6ef5", "#3b5bdb", "#364fc7"],
  "green": ["#c3fae8", "#63e6be", "#20c997", "#12b886", "#0ca678", "#099268", "#087f5b"],
  "yellow": ["#fff3bf", "#ffec99", "#ffe066", "#ffd43b", "#fcc419", "#fab005", "#f59f00"],
  "orange": ["#ffe8cc", "#ffc078", "#ffa94d", "#fd7e14", "#f76707", "#e8590c", "#d9480f"],
  "red": ["#ffe3e3", "#ffa8a8", "#ff8787", "#fa5252", "#f03e3e", "#e03131", "#c92a2a"]
};

colors = Object.keys(palette);

shades = ["lightest", "lighter", "light", "", "dark", "darker", "darkest"];

foreground = function(shade, background) {
  var color;
  color = "#ffffff";
  switch (shade) {
    case "lightest":
    case "lighter":
    case "light":
      color = "#495057";
      break;
    case "":
      if (background === "yellow") {
        color = "#495057";
      }
      break;
    case "dark":
      if (background === "yellow") {
        color = "#495057";
      }
  }
  return color;
};

You'll notice that the Coffeescript code is terser, which in my opinion, makes it more readable.

Coffeescript, however, does not absolve you of needing to know any Javascript, as debugging still requires full Javascript fluency. As I mentioned, Coffeescript is shorthand for Javascript, but not a replacement.

Why?

So why do I still use Coffeescript, even though it's 2020 and there are arguably better (and inarguably more popular) options?

Well, I started using Coffeescript when I started to do Ruby on Rails development roughly 10 years ago. If you've spent any time doing RoR, you'll know that indented syntax languages like SASS and Haml are incredibly popular in that world. SASS and Haml let you write CSS and HTML without becoming muddled with braces, semicolons or open and close tags. With Rails 3.1, Coffeescript adoption became even more widespread among RoR devs.

Using Coffeescript with Rails has real benefits, as Coffeescript code has a lot of similarities to Ruby, which means less mental "mode switching" when jumping back and forth between front-end and back-end code, which makes it feel like you're writing in the same language across the breadth of your entire application.

So back to the question of "why", I still use Coffeescript today because it allows me to translates my thoughts into code faster without worrying about details like braces and semicolons. The use of whitespace also makes the code incredibly easy to read for me, which makes debugging much faster. The primary cost of this language is that it needs to be compiled (which for me happens in near real time, since I use a Gulp script to compile my code when files change. Now that I'm working with Svelte, which is a compiled web development platform, the notion of Coffeescript's compilation step as an inconvenience is moot, as Svelte requires compilation anyways. I simply include Coffeescript as a seamless preprocessing step in my Svelte workflow.

Looking Forward

I have been tempted to switch to Javascript (or even Typescript) now that I've been using Svelte, mainly because of some Coffeescript-unfriendly idiosyncracies in Svelte (i.e., export let, let and $: { someCode}). Those idiosyncracies, however, are easily solved with the use of backticks, which in Coffescript, lets you pass through raw Javascript in your Coffeescript code.

So while my use of Coffeescript might be considered passé to some, I still find it to be a valuable part of my toolchain, because I am more efficient and productive with it. Having said that, I'm not at all ignorant or resistant to change. Myself, I'm partial to tools that work the way I think, and sometimes timing matters. Industry-wide preferences often become replaced with even newer ones.

For example, I've been looking to move away from AngularJS for newer web projects for some time. I considered Angular (AngularJS's successor whose name is not at all confusing, smirk), React and Vue. I was about to jump on the Vue bandwagon until I heard about the Svelte 3 announcement, and was simply blown away by how it ticked all the boxes that I was looking for in an AngularJS replacement. Had I made my choice earlier, I'd be a Vue developer right now. Timing affects outcomes.

So yes, I could adopt Typescript now, but I need some convincing that at some point Typescript won't fall out of favor of something newer, faster and better. In the end, whether you're using Coffeescript or Typescript, you're still compiling that language to plain old Javascript, since that's what runs on browsers and NodeJS. So why not stick to the tool that works best for you, whatever that may be?