How To Kill a Hydra

Fixing the Worst Mistake the Software World has Ever Made

Doron Sadeh
7 min readMay 9, 2019
Killing the Hydra (the wrong way)

JavaScript is an abomination. A language developed in a hurry over two weeks to facilitate web page dynamic programming has taken over the world, spiraling out of control. It has since infested server-side backends with implementations such as Node.Js, wildly outgrowing its original purpose.

The success of JavaScript cannot be understood out of its generational context. It is the language of the millennials. A generation of young programmers who want everything to be easy, who expect instant gratification and the hell with the consequences, has met a language who promises (pun intended) just that.

Why bother with design, good architecture, and strong typing when we can punch a piece of code that sort of works in an hour, and find out all the nasty bugs much later in production. After all, production is a year away and we’ll most probably work for some other company by then.

It’s not that dynamic languages are bad, not at all (e.g. Python is a great language for Data Science), it’s that some of them are badly used, and JavaScript has been the worst of them all.

When you implement a web application with JS on the front-end, it makes perfect sense to use Node.Js as your backend. It is simply the right thing to do. Mostly, because that is what JS and Node.Js were developed for, i.e. the rapid development of beautiful web applications and websites. And boy did they deliver. If only it had stopped there.

A programming language is like a power tool. There must be a perfect fit between the tool and the task at hand, else you may injure yourself. Taking the parable further, you need to always(!) use the most befitting language for the task. Silver bulleting one language, as if it was the holy grail is incorrect at best downright plain stupid.

However, JS has and is becoming a holy grail, such that even fine establishments such as Stanford made it the first language of choice for CS students. If only it was not such a crappy language.

“I chose JavaScript and Node.Js as my server side stack because it has become easier to get programmers who are familiar with the language, and I can use them for both front-end and backend development” (something you’ll hear from many startup VP R&Ds)

To understand where and how JS originated and why it is such a bad general-purpose language metaphor (for non-web applications) one needs to go back to ten days in 1995.

In 1995, Netscape Communications recruited Brendan Eich with the goal of embedding the Scheme programming language into its Netscape Navigator. Before he could get started, Netscape Communications collaborated with Sun Microsystems to include in Netscape Navigator Sun’s more static programming language Java, in order to compete with Microsoft for user adoption of Web technologies and platforms.

Netscape Communications then decided that the scripting language they wanted to create would complement Java and should have a similar syntax, which excluded adopting other languages such as Perl, Python, TCL, or Scheme. To defend the idea of JavaScript against competing proposals, the company needed a prototype. Eich wrote one in 10 days, in May 1995.

They never imagined it would be widely used outside the browser. But, as such things go, it was soon out of their hands.

A language developed for a single use case, i.e. handling the async nature of the web, has become the de-facto general purpose programming standard. But general-purpose programming is not all async, nor all systems require it. Not as JS is concerned.

When you write JS, you are forced to think async and write async. Instead of the language metaphors working for you, you are working in service of its web-centric model.

It’s like premature optimization gone wild, consuming valuable time and programmer resources for no reason, and we have not yet begun discussing the number of bugs such model introduces when you are trying to bend yourself into it in order to write a simple, standalone, micro-service that is completely sequential.

JS programmers would tell you the language has gone a long way. They are correct, it has gone a long way adding features (e.g. Promises, Async/Await, etc.) that try to overcome its basic deficiencies. Features never needed if it kept to its original purpose, nor linter to form the last line of defense against bad coding.

JavaScript newest features such as promises, async/await and its linter are much like a car that was supposed to drive paved roads, going off-road fitted with an external bulky 4X4 transmission attached by a few band-aids and a hint of superglue accompanied by a tow truck to get it out of tricky situations. It drives, but it’s not pretty.

JS is an accident, a language that spiraled out of control, and we need to softly kill it. But we must be smart about it, or else the hoards of millennials flocking to it would wreak such havoc on the global software eco-system for years to come, such that the Y2K bug would look like a minor incident.

Softly Killing the Hydra

A religion never goes away until there is a new, more appealing one. Same for programming trends. If we want to kill JS, we need to provide an enticing model that would appeal to the masses, then gradually change it removing all the bad functionality, migrating into a newer, better model.

Microsoft has attempted that with TypeScript, to some extent.

TypeScript was first made public in October 2012, after two years of internal development at Microsoft. TypeScript originated from the shortcomings of JavaScript for the development of large-scale applications both at Microsoft and among their external customers. Challenges with dealing with complex JavaScript code led the demand for custom tooling to ease developing of components in the language.

TypeScript developers sought a solution that would not break compatibility with the standard and its cross-platform support. Knowing that the current ECMAScript standard proposal promised future support for class-based programming, TypeScript was based on that proposal.

That led to a JavaScript compiler with a set of syntactical language extensions, a superset based on the proposal, that transforms the extensions into regular JavaScript. In layman terms, TypeScript is JavaScript with compile-time typing.

At first, it was coldly accepted, later to be hesitantly embraced but it is gaining traction. JS programmers, for which the act of declaring a type was something methuselah used to do in Java when they were suckled, were slowly accepting the fact that it may actually be more efficient to spend a few seconds declaring type, instead of looking for bugs in their production environment on a Sunday morning when it crashed and burned due to an overlooked string date-variable interpreted as integer.

As nice as TypeScript is, it still maintains the original async/await promise-based metaphor hard-wired into its underlying JS.

We must do better than that.

Beyond JavaScript

When it comes to designing a new programming language, one must ask a single basic question: what is the problem domain? I.e. what are the type of problems we aim to solve using the language.

This basic question, once answered, would provide the appropriate trade-offs we would have to take during its design. As JS has become the standard for many high-profile server backends (sometimes referred to as systems language), we would be wise to focus our JS replacement on the same problem domain.

So, we are looking to design a server-side programming language whose metaphors are lightweight enough as not to burden the millennial programmer with too much syntactical overhead, one that allows (but not forces) OOP patterns, enforces compile-time checks nipping potential bugs in the bud, efficiently (and safely) multi-tasks and distributes execution while enabling a soft migration from JS.

Quite a tall order.

One option would be to use an existing language such as Python or Go, or even Rust. However, those would be automatically rejected by the JS cult the same way every new religion is rejected by existing ones.

Another option, along the path taken by TypeScript, and C++ at the time, is to create an extended language that keeps the look and feel of the earlier one while adding the necessary metaphors on top.

In the case of TypeScript the TS code transpiles into JS, while the older C++ took a similar, even though not same, approach keeping the underlying C linker and most of the C syntax (veteran programmers may remember the Cfront compiler that converted C++ into C the same way TS does for JS). However, this is more of a patch than a full solution, as it keeps language metaphors we would like to do away with, in order to achieve its extension goal.

There’s no escaping it. We need a new language. One that satisfies the above requirements (for efficient, large scale and safe server-side programming) while providing a smooth and attractive migration path from JS. It would most probably be a combination of Python and Go with a touch of Rust and a user-friendly concise syntax notation (we are not going to detail such a language in this article — rather in a follow-up describing this new proposed language).

As migration paths go, we have exactly two options.

Either create a compiler that takes existing JS code, effortlessly converting it into the new language (nothing shorter than that would suffice as no one in their right mind would be willing to throw away the enormous existing JS codebase, and rightfully so). Or, provide a runtime that runs JS code alongside modules in the new language with the appropriate glue APIs to allow interoperability between the languages so that new code runs seamlessly with JS modules, replacing it over time (one may even imagine a Just-in-Time compiler that compiles JS modules dynamically loaded into such a runtime).

Once we have implemented the above there would be no reason to keep using JS, and the herd of programmers now using it would slowly adapt to the new language while keeping their investment in the older JS code bases (much like the process of slowly migrating new modules into TypeScript while keeping older JavaScript codebases). Because it would simply make sense.

And the Hydra can rest in peace.

--

--

Doron Sadeh

I ride motorcycles, gaze, and solve hard problems. I am fascinated with all things data, culture and philosophy. Publishing the "A Colder Lazarus" magazine.