Programming With The Lowest Common Denominator

What’s the hippest programming language in 2015 that all of the fashionably dressed hungry young developers can’t get enough of? Something new? Something compiled? Something fast? Something well-structured? Something maintainable? Something someone spent more than two weeks designing? No! JavaScript!

I recall many years ago when node.js was new on the scene, a contractor who wrote one of the shoddiest hackjobs of C#.NET code I’ve ever seen, gave me some unsolicited advice: “hey you should rewrite your application in JavaScript.” I thought he was high on bath salts. “What, the backend??” I asked incredulously. He replied now it was now possible to do so. I called him a raving lunatic, thinking no one would ever voluntarily do such a thing.

Several years later JavaScript is everywhere. Frontends, backends, HTML5 mobile “apps”, cars, TVs, watches. As usual my prediction that the very suggestion of writing JavaScript by choice would be subject to ridicule was totally wrong. This has led me to reconsider my assumptions and opinions; if so many people are this into JS and promoting its usage, I must be missing something. So let’s go though some common objections.

JavaScript”. While being named “JavaScript” the language actually has very little to do with Java at all, although the syntax of both is closely derived from C. Netscape wanted a competitor to Java so some marketing genius decided to stick “Java” in the name. This caused a lot of confusion for a long time. The structure and primary features of the language are based more on Scheme or Lisp, most notably the presence of an “eval” directive and first-class functions which neither Java nor C have. There is a lot that has been said on the beauty of distilling the machinery of describing programs down to their essence of eval/apply that I won’t bother repeating here. All you have to do is watch this minute-long video:

JavaScript was a rather bare-bones language in terms of features and goodies to help structure large programs or catch common mistakes at compile-time, and there’s nothing wrong with that. In its original uses, simplicity was a great benefit since no programs were longer than ten lines and the fanciest thing you could do was change the status bar text.
image

If you wanted to mess about with “classes” and reusable components you were completely free to, but you had to build a system yourself. This gave programmers great flexibility to innovate and try out different models over time that evolved with the web as they weren’t locked into a rigid system of object-orientation or modularity. Many competing and incompatible frameworks like x.js, Moo, YUI, Prototype, jQuery and a zillion others popped into existence to fill in the gaps, with most large companies just making up their own. Eventually jQuery “won” the cross-browser compatibility layer competition and most everything in the browser uses that today.

There is much to be said for building the bare minimum and letting people design new layers to be put on top and having them all battle it out. I think JavaScript takes this a little too far though. Its complete disregard for typing sanity or really typing of any sort is hostile to writing performant code or code that you can sanity-check before running it. There’s a good little talk on this breakage.
Fucked up JavaScript examples

When writing a serious piece of software, such as one that a company or important system relies on, you want it to be maintainable, catch obvious bugs ahead of time, and make it easy for others to join your project and be able contribute easily. JavaScript encourages none of these things. JavaScript does not have any concept of modules, imports or dependency injection. Yes there are such capabilities in Node but I am speaking of the JavaScript one writes that is compatible everywhere. There is one and only one valid reason to write JavaScript as a server-side programming language and that is because you can share the same language and code on the frontend and backend. There are innumerable better-suited languages for pure server-side or application programming besides JavaScript so if you want to consider JavaScript that doesn’t run in a web browser then fine, but who cares? The only useful feature of JS is that it is executable by the lowest common denominator, namely web browsers.

Without a standard object model of inheritance or interfaces people generally roll their own, borrowing features from other languages that they miss from the prototyping system, such as the ability to call the superclass version of an overridden method, a nice feature available in obscure toy languages such as python, ruby, C#, java, perl, actionscript3, PHP and every other language except C++ (due to multiple inheritance). If you want this feature in JavaScript, just roll your own as the “Secrets of the JavaScript Ninjainstructs.

Typing. Ahh static typing. The way you save me from conversion errors, invalid function parameters and invalid method and property accesses. Too bad JavaScript provides none of those things. Good solution to the problem of BigInt and floating point conversion errors though: all numbers are a double. End of story. While you may think that JavaScript is not suitable for checking instance types due to its dynamic nature, you would be wrong! In fact another JavaScript-compatible language called ActionScript3 has the most pleasing type declaration system imaginable. In addition to actual semantic classes and interfaces (which sit alongside the prototype chain) it allows you to optionally specify static types for all objects and primitives. Rarely do you actually need to modify the methods on an object at run-time, but you can optionally declare that type as dynamic if you don’t want the compiler to yell at you. Or you can just eschew static types altogether if you aren’t writing anything serious. That language was a great example of how one could actually write very beautiful and well-structured code where many of your mistakes would be caught by the compiler, and it was a derivative of JavaScript! It is the one thing that I will truly miss from the demise of Flash.

Modularity. It’s great when you can encapsulate little bits of reusable functionality into packages that export only the public bits of your interface and declare their dependencies. Really makes it easy to develop serious software. Yep.

But really, what’s the point of complaining? No language is perfect. Lots of innovative things are happening in JavaScript, some day it may be possible to write ES6 and expect most peoples’ web browsers to understand it. There is undeniable progress here, and even a new push to replace it with something even more fundamental. I believe the strongest argument in favor of JavaScript is: it runs on servers and web browsers. No other language can make that claim. But just because you can does not necessarily mean that you should.

I’m not entirely sold on the benefits of the frontend and backend being so tightly coupled. I think of the JavaScript running in a browser as my application’s user interface, rather than thinking of the whole package as a “website.” Websites are a collection of HTML, CSS and JavaScript that are entirely handled client-side. A web application is an application that happens to have a user interface that is implemented in something a web browser or view can understand that talks HTTP. If there’s one rule every application developer should live by it is this: separate presentation from business logic. Meaning don’t couple your interface to your code that deals with the database. The flexibility and constraints this gives you are extremely valuable into not getting sloppy and putting functionality where it doesn’t belong. I’ve seen a number of frameworks now that make it way way too easy to query a database directly from JavaScript, hiding away all of the logic of building a query and validating it. This scares me and it should scare you too.

In all seriousness, all programming languages are roughly the same. A mistake many people make is falling into the trap of thinking that there are vast differences between languages and that they take years to master. Most common programming languages do pretty much the same things and are derived from C and have similar syntax and features, and they can be picked up in a week or two by someone who is an experienced developer. For some reason many people still ask “what language do you code in” or say “we need to hire some python people” or love to argue for hours about which programming language is best, which is an unsolvable question and just leads to religious wars.

That said, there ARE major differences between programming in different languages, but not because the languages themselves are hugely different. It’s much more about the problem you are trying to solve, the community you interact with and the quality of the libraries you are going to rely on to build something useful. These things can and do vary wildly. Python is a great general-purpose language with a friendly community, Ruby is probably a bit more web-focused but mostly the same. PHP is great for making web applications if you’re 12. C# is great for windows desktop applications. J is used by about 20 people in the whole world but is great for numeric applications. Java is not really good for writing software.

The JavaScript community though largely of well-meaning and enthusiastic programmers (not usually “software engineers”) who are fresh out of their Coder Bootcamp and ready to disrupt the stodgy old world of UNIX weenies who waste their time doing silly things like memory management and aren’t up on the latest frontend frameworks. With the notable exception of transpiling C to JavaScript, running JavaScript on an operating system instead of a web browser requires a whole lot of library support for things like networking, threading, files and more. So much to rewrite and make asynchronous!

My previous open source experience was with the Perl community. It had a large number of highly competent, serious-minded, occasionally smelly geeks who cared about designing and engineering high-quality software.

Definitely one of the most important aspects of any language is the community because they are the ones building the software you rely on, answer your questions when you need help, and are responsible for maintaining code quality. So when I first gave node.js a try I decided to write an IRC ASCII art flooder bot, always a great way to get acquainted with any new language. One of the requirements for a good IRC bot is that you need to be able to bind to various addresses on a socket to change your source IP up, and the node-irc module was lacking in this capability. No problem thought I, I’ll just submit a pull request with my addition to allow specifying the bind address.

I guess I was used to the community of CPAN maintainers for Perl, where someone would review my patch and merge it in, or tell me they weren’t maintaining that module anymore and give me maintainership, or occasionally tell me to add tests or go fuck myself. Here I got silence. And then more silence. Then, following up two years later, I got a request to rebase it, since every single file in the project had been deleted. I guess someone thought it was cool to come along and delete all files, destroying all history and any hope of merging in the 40 or so outstanding pull requests, and then started a rewrite of the code, which they kinda gave up on halfway through. For some reason this had been accepted.

Instead I had to do some gnarly git incantations to copy a branch of the proper mainline back into master and remove the history of some random asshole shitting all over the module. Then we got things back on track. The guy who helped me with fixing everything was someone I recognized from CPAN, interestingly enough.

While I can’t say for certain that this one incident is typical of most of the people contributing to JavaScript and npm modules, more than a few anecdotes and questionable practices are found here. More than most. Some gems include multiple people asking why their node application crashes on invalid input when eval()-ing JSON from a client to parse it, callback functions a dozen levels deep, and attempting to rewrite build systems in lots of ways that suck. Why bother with make when it’s not even written in JavaScript, right?

I don’t want to hate on JavaScript too much. Everything sucks if you dig deeply enough into it. And JavaScript is the only option for a lot of applications, specifically their user interfaces. When you do have the choice though, for server-side software, I still think there are better options.

For more, please see this talk from the year 2035 on the birth and death of JavaScript.

5 thoughts on “Programming With The Lowest Common Denominator

  1. Anyone who makes this statement: “Java is not really good for writing software.”, -especially- from someone who comes from Perl where you can punch a keyboard three times and likely have least one executable line of Perl is kind of hard to take seriously.

    You are throwing flamebait, sir – fun for you but not really inviting of discussion.

    Like

  2. “In all seriousness, all programming languages are roughly the same. A mistake many people make is falling into the trap of thinking that there are vast differences between languages and that they take years to master.”

    Thank god someone else has finally said this. I’ve been telling people this for years, and years, and years. This entire article is fantastic, a great read.

    Like

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s