Oh No(de)! JavaScript on the Server…?

It’s been a few months since the storm erupted around this post on Node.js by Ted Dziuba. Ted writes in a deliberately controversial style with comments like “Software development methodology is organizational Valtrex.” raising the ire of readers and his post on Node.js was no exception. When he pointed out the Achilles heel of event loop frameworks – that any computationally expensive operation in the main loop will cause the whole system to grind to a halt, fans of Node rallied round and did one of two things – they either missed Ted’s point and pointed out that his method of calculating the Fibonacci series was sub-optimum (and missing the point that it was supposed to be an example of an expensive operation) or pointed out that Node is still young, addresses many common use cases in web development and fits a useful niche with real business benefits.

JavaScript has been used for server tasks before. The venerable Broadvision ran JavaScript in one of the most popular application servers in the late 90’s. The was no syntactical difference between the code that ran on the server and the client side code. Of course we know that JavaScript fell out of favour for server tasks and languages like C++, Java and C# until the new pretenders to the crown of PHP, Ruby and Python came along.

Node.js has really changed the game to allow JavaScript to be a viable alternative again. A simple framework that made a strength out of JavaScript’s lack of threading or blocking reads that could create incredibly powerful event-loop based applications that allowed front end developers to operate on the server. Developers are able to write fast and scalable code that doesn’t have to worry about locking or other concurrency issues to deliver an entire application stack… apparently.

There was an interesting talk given by Doug Crockford around server-side JavaScript covering much of the history and current thinking including Node.js. Now Doug Crockford is an acknowledged legend of JavaScript programming but there were a number of points he mentioned that seemed to beg the question:

  • Just because JavaScript is successful on the browser, what justification do we have to suggest that it would be good for the server?
  • Is promoting the idea of one language for all domains a good idea?
  • If we need to create sub-processes or workers for potentially blocking tasks, aren’t we just recreating threading but with crappy scheduling?
  • We know that threading is bad but does that automatically make event loops good?

Just because JavaScript is successful on the browser, what justification do we have to suggest that it would be good for the server?

JavaScript is rightly called the x86 assembler of the web. It is ubiquitous across all major browsers to such an extend that until Google proposed Dart, there hasn’t been a useful alernative since VBscript (and how useful VBScript was can be debated). It is fast (or rather fast enough) and getting faster and has a programming model that is relatively easy to understand. However, this is a function of the bundled engine rather than some transcendent requirement that all browsers have to support JavaScript.

For all its good features, and there are many, JavaScript has more than it’s far share of bad ones: global variables, reserved words that are only sometimes illegal, terrible arrays, a single Number primitive and truly weird true/false evaluation. We have to ask whether we need another language on the server side that has such flaws and performance that relies on a sufficiently smart compiler for decent performance. Now given V8  instruments the code when it’s being interpreted so can optimize to machine code and also infer the types, it is close to being sufficiently smart but when going against the likes of Java, C#, C or even the more dynamic Python and Ruby why would you choose JavaScript?

Is promoting the idea of one language for client and server domains even a good idea?

If the recent explosion of languages has shown us anything, it is that not all of us think alike. Some of us love functional programming, some prefer object orientated programming. Some love prototype inheritance and some prefer class based inheritance. Some love static typing and some prefer dynamic typing. Now some of this is going to be decided by how we think, what shape our “mindcode” is. But some of this is going to be based around how the shape of the language fits the domain model. As an example, PHP is a horrendous language by any technical standard but it is phenomenal at allowing developers to get a web application up and running faster than almost anything else. Likewise, Java is boring and staid compared to the likes of Python and Ruby but offers an enormous pool of developers with superb tooling on a high performance platform with unrivaled support from major vendors which is just what a large company is going to want. These are different domains that have different requirements and different languages offer differing levels of suitability for each set of problems. Having a single language for your entire stack means you are compromising somewhere.

If we need to create sub-processes or workers for potentially blocking tasks, aren’t we just recreating threading but with crappy scheduling?

Probably the biggest bit of truth in Ted’s post is that any computationally expensive activity is going to block the main event loop and render your application useless. The common response to this is to fire off the long running operation in its own process/thread. That sounds a perfectly reasonable way to avoid blocking your main event loop except that you are effectively recreating a threading model that you have to manage. An example of this is knowing which requests can be handled in the main loop and which need to be spun off. If you the developer has to know in advance how to handle requests, you have got it wrong.

We know that threading is bad but does that automatically make event loops good?

No it doesn’t. Event loops are brilliant constructs for many jobs but really really bad at others. They are not a great general purpose multi-threading construct since they deal with concurrency and not parallelism. There are also other issues around exception handling, paired closures or Option/Maybe monads being examples of solutions, and transactions (hand coded?). When compared to an Actor or Agent framework, event loops are limited in what they can do and not as easy to understand, especially when you are dealing with nested closures. Nested closures are almost a separate topic in themselves but if the true value of a technology is to lower the barrier to adoption, having a fundamental property of the language be as awkward as this is another bad smell.  There are options like the async or step libraries (in fact there are about 10 different ways which in itself is indicative that something needs addressing) but they are still sticking plasters on the underlying issue; that you are required to understand CPS if you want to avoid complexity hell since you have to write code that is directly reliant on the concurrency semantics of your framework. Given that JavaScript has no other concurrency model available to it what else can one do?

So why is the so much noise around JavaScript on the server again?

JavaScript has a massive following and having the same language both front and back makes prototyping simple and fast so companies can focus on creating applications that make them money. This is the true value of Node.js, the ability for developers who would normally be restricted to the front end to be able to delivery a full stack from front to back. This has immense business value, especially when a single developer can use the same programming language and framework to create the server, client and their interactions. This is the quickest way to get up and running and a blessing to any startup. The trouble starts when you want to productionize your prototype. You want things like operational monitoring, security and knowledge around its performance foibles like memory ceilings before you start committing your company’s fortunes to a one-size-fits-all tech stack.

The adoption of node indicates that there is a real need for web developers to have frameworks that enable them to write fast full-stack applications in one language. Node’s focus on productivity and ease-of-use to a population of developers who had no other option has made it very successful and the community that has risen up behind it can be rightfully proud of what they have created. But anyone adopting it needs to be aware of the inherent limitations and maybe ask the question; do we improve the frameworks to help the developer or improve the developer to help select a better framework.

 

Leave a Reply

Your email address will not be published. Required fields are marked *