The Problem with Node.js

I'm pretty open when it comes to trying out new technologies and I don't really prescribe particularly to technology and language bashing either. I believe in the “right tool for the job” mentality. Over the last 8 months, I've been deep in writing a commercial Node.js application so I'd like to think that I can now at least hold an opinion on it.

I'm really interested to know if you all hold the same or different beliefs or have noticed some of the same issues with Node.js that I'm going to point out in this article. I'm traditionally a Java developer of nearly 10 years so I may be coming from a rose-tinted glasses perspective - so forgive me if you think that's the case.

Please note: Some of these things are related mainly to Javascript as well so not explicitly just Node.js

Error Handling

First off, let's start with Error Handling. Error handling, for me is pretty important for mission critical server-side applications. Java is great in that respect because it provides you with a very solid exception handling model. Even if you don't happen to catch an exception all it'll do is fail your request, it won't completely crash your app. Exceptions are bubbled up the stack and spit out into your console. I like this model. For me it works and it's pretty solid and fairly idiot proof.

Node.js on the other hand, because it's a single threaded model, will bite you hard if you don't pay attention. Woe betide you if you happen to forget to catch an exception. Your absolutely critical Node.js app will crash if you don't handle it, but you can always keep the app running by spinning up a new app in a new node.js thread.

This for me is fairly unforgiveable for a language that you may want to build mission-critical apps with.

I once had a very subtle issue where I was seeing an undefined:undefined error message in the console after running some tests. No stack trace, just the above error message. My first thoughts. What the hell? Since when could you get an undefined:undefined rather than an error message and stack trace.

It actually turned out that the error object was actually a string because someone had written...

return 'this new error message'

So what they'd intended was to add additional text to an error thrown further up the call stack so becoming...

new Error('Initial error: this new error message')

This wasn't initially spotted because there was a disconnect between two modules (a common one and one that consumed the common module).

Obviously this is a clear problem with the fact that there's no static type checking in Javascript and it's not a compiled language. This is probably a gripe more about Javascript per sé but also a gripe at the fact that a lot of people have jumped on the bandwagon of Node.js recently but without realising the consequences of dropping static typing.

NPM

Again, as Java developers we're pretty spoiled here. Maven, for all the stick it gets for “downloading the internet”, is a fantastic dependency management and build tool. There's also Gradle as well which again is really really great. Both are very mature and “Just Work”TM.

NPM on the other-hand is a terrible dependency management tool. It's great when it works but when it doesn't you often get incomprehensible errors and stack traces. Googling npm errors often leads to Github issue tickets where problems are brushed off and an npm cache clean or removal of the node_modules folder is suggested followed by an npm install.

Console.log

I've found that because of a distinct lack of a decent debugging toolset for the Node.js stack I use console.log a lot more than I feel I should. I actually can't remember the last time I had to log out stuff in Java because the debugging tools are just so darn good.

This irritates me no end. It feels very much like a backwards step in my eyes.

Lack of Type Safety when using Foreign APIs

In the Node.js world you'll find that you tend to consume lots of different libraries etc. because Node.js really doesn't provide you with that much out of the box. Looking at API documentation for modules is therefore a must.

Due to the lack of typing and the fact that debugging tools are not great making use of new libraries can be a source of extreme frustration, especially when the documentation for said library is woefully lacking.

Promises

Now I love the concept of Promises, however, writing tests for promisified code is painful. You need to ensure you always resolve your promises before you can make any assertions about the correctness of your code. Not to mention on top of that you can have callback hell with having to close your callbacks correctly for cucumber or jasmine unit test suites.

In Java, you don't have to worry about any of those problems any more. Sure, concurrent code can be complex but often you have frameworks (such as Apache Camel that are excellent at abstracting away that complexity and letting you deal just with the business logic. Also, with the recent advancement of Akka and more recently the Quasar framework this job has been made significantly easier.

Do we really have need of the ubiquitous use of Promises any more when we have multi-threaded languages and such frameworks at our disposal?

Which NPM library do we use? No Idea?!

The Node.js community for me is very fragmented. It's difficult to know which NPM library is best to use with an option of at least a dozen at your disposal. Also, even if you happen to find a library that's used by 98% of the projects out there you take a look under the hood and you might be horrified. One particularly well known and core library I found had an entrance method that was full of if statements and the method was 600 lines long! I would absolutely not like to have to maintain that.

Scoping

This is probably a minor gripe by me but I find the scoping in Javascript mildly annoying. Should we really have to do...

var self = this;

or

.bind(this)

Both of which means your code is in essence much less readable. I would definitely sacrifice performance for readability and maintainability any day of the week.

C-Bindings

So a lot of Javascript libraries where performance improvements are needed are compiled into C. For me, this creates a bit of a headache when upgrading versions of Node for example, because you need to re-compile the Javascript libraries C-bindings so that you have the latest code. Sometimes you can forget to do that and be searching around for the reasons why the upgrade hasn't worked.

From my perspective, I would much rather just deal with the stack in a single language only since it's much more predictable and there's less margin for error.

OO or Functional?

When I first started looking seriously into Javascript I read Douglas Crockford's Javascript: The Good Parts which highlighted the huge benefits of Javascript that made it stand out from the rest.

An ability to use flexible prototypal inheritence and also use a functional style of programming. More often than not though I've found that the Object Oriented paradigm has been dropped completely in Node.js applications in favour of a procedural approach. For me, OO, procedural and functional programming paradigms should be married together and used when appropriate. Node.js doesn't seem to encourage this as much and has a heavy procedural bias.

Io.js / Node.js

Back in November there was a spat over the future of Node.js with core Node.js contributors falling out with Joyent over the lack of releases of Node (only 10!) in 2014. Just 3 days ago (as of the time of writing) Microsoft have announced they will be forking Node.js for their own Javascript engine.

All of this only helps to add fuel to the fire that Node.js is not a platform you want to rely on in the future. With so many different players in the game the future is very uncertain. Microsoft's move to fork Node.js could hint that they are worried whether Google even cares much about Node.js future on their Google V8 engine (which it seems they don't with their own Dart language being used to power Google Ads) and a strong targeting by Google at server-side Javascript as opposed to client-side in V8.

Ten Ways to Solve the Same Problem

As a Node.js developer you'll notice that there are so many ways to skin a cat it becomes almost impossible to choose. Go onto Stack Overflow and you'll receive lots of different answers to the same question. Sometimes choice is good but I actually prefer the structured rules as they enable you to be more productive because you don't have to make these choices (they're made for you!).

Google Searches don't bear Fruit

I've found that many Google searches are often very unfruitful as far as turning up answers is concerned and that it can often take 6-7 posts/links before you find a solution close to what you're after. I'm not sure why this in comparison with Java but it seems a lot harder to find the answers to your problems via keywords in Js than with other languages.

Just a trend?

A cynical part of me thinks that the current trend with Node.js is part of the “full-stack” developer trendy movement, but as I stated earlier in the post I'm a “right tool for the right job” kind of guy and whilst it's not cool any more to code in Java it's a pretty solid choice to get things done.

I think as a community we need to take more responsibility as far as adopting new languages and platforms is concerned and not be so quick and eager to jump onto the “next big thing” just because some big corporation or other has decided to adopt it. It may not be the right choice for us.

I hope you've enjoyed this article and I really welcome good debate. How have you found Node.js? Do my hopes and fears ring true with you?

Look forward to hearing from you guys. As always you can get in touch with me follow me on Twitter or subscribe to my rss feed.

UPDATE: 25th August 2016

So it's been nearly a year on and this blog post is easily the most popular (and controversial) blog post on this site, accounting for nearly a 3rd of the traffic (staggering!). On balance and reflection I still agree with a lot of the sentiments I expressed a year ago in this post. Largely around my frustrations at the javascript community more than anything else.

I can't stress enough that if there's anything to take away from this blog post I would say it would be around the increased importance of monitoring and logging when building applications in Node.js

I would still advocate the use of Node in certain circumstances. It's excellent for example as a backbone for applications that require a lot of short-running threads. So if your application design leverages and makes best use of that, then by all means Node is a great solution.

However, it doesn't suit monolithic architectures.

If you're going to use Node make sure the purpose of it is well-defined and you're designing for scalability with lots of async processing. So don't go doing something stupid like trying to use a single-threaded non-blocking framework like Node for long running calculations or data analytics. Leave that to Java, Scala, Go or some other more heavyweight multi-threaded language.

James Murphy

Java dev by day, entrepreneur by night. James has 10+ years experience working with some of the largest UK businesses ranging from the BBC, to The Hut Group finally finding a home at Rentalcars.

Manchester, UK
comments powered by Disqus