Friday, December 04, 2015

Node's Benefits Don't Matter. Use Node Anyway.

Systems that are be maintained by a single team will coalesce to the paradigm of their least changeable component.  In web development, that's the front end, which is javascript.

One of the problems of being a "full stack web developer" is that you must master very disparate sets of abilities.  In the traditional form, that's HTML/CSS, front-end javascript, back-end languages, and SQL. And maybe devops tools on top of that.

What makes Node unique in terms of platform features is that it is designed to be functional and non-blocking from the ground up.  Each library is already set up to use some kind of callback pattern, and the platform architecture forces the developer to adhere.  There are benefits to this paradigm, but they don't really matter.

Yes, Node's nonblocking IO and other features are great terms of scalability and performance, but these benefits don't really explain the uptake of Node as a first-implementation language.  I would bet that 90% of the applications written in Node never get to a volume where the performance considerations matter.  And those that do still end up needing custom performance features written in a compiled language.

But I hear the word "just" a lot, implying simplicity -- "just build it in Node".  So what's going on?

The real benefit: paradigm consistency. All the different concepts (CSS, functional javascript, imperative Java, SQL, etc) are too much, and take away from your time concentrating on the business problem. So we skimp.  We write Javascript that looks a lot like Java, or vice-versa.  But what about Node?

Node is not only the same language as the front-end, but also the same programming concepts: event-based, callbacks, etc.  This avoids shifting into the paradigm of imperative style, with blocking multithreading, big classes, etc.  This, coupled with avoiding the specialized knowledge of build cycles and compilation and artifact deployment, makes it feel "just easier".  And it is.

What about no-sql?  Everything I said about Node is probably true for Mongo.

Writing to no-sql databases really looks very similar to the list/hash data structures that appear on the front end.  It avoids the specialized knowledge of DDL.  Data migration is done in functional/reactive programming.

That's what makes the node/nosql stack so compelling -- it's all the same paradigm, and it matches the browser-side paradigm, which is the one you can't change.  This isn't bad, necessarily.  In fact, it may be the kind of thinking that unlocks Node for a lot of teams.


Dan Ebert said...

I've only used Node a little bit, but found that the callback pattern could pretty easily lead to deeply nested callback hell. TDD helped prevent it because testing those nested callbacks is difficult. We found that using a promise library (like Q) instead of callbacks made for much more easily TDDed, cleaner, and more legible code.

There are definite benefits to using one language throughout the stack, but as I've become more polyglot in my programming I find that I'm learning new ways of looking at things the more languages I work in. So there are some benefits to actively working in multiple languages as well.

Kevin Klinemeier said...

I think your comment that callbacks are a mess, promises are better is right on -- but it's just as true on the front side too. Maybe another corollary is that you have to have some source of new "genetic material" so to speak.

Tim Myer said...

Interesting recommendation. Would you also advocate that teams writing native iPhone apps use Objective C and its paradigms for their backend code or that teams writing for the Android platform use Java in order to maintain paradigm consistency?

Kevin Klinemeier said...

Good questions, Tim -- I don't know ObjectiveC (or swift) well, but I think the answer may be "paradigms, yes, language, no".

I can't imagine using Objective C literally on the backend, but picking something with dynamic typing, and other features that match (I don't know what those are) would make you the most productive*. That puts you at odds with Java, the granddaddy of static typing**.

This might be where Swift and Java 8 become more important. Both these languages have more features to support functional paradigms. A team working in both might even choose to use fewer dynamic typing features in order to stay consistent and productive, avoiding having a section of code where developers say, "Oh god, this is some clever stuff that can only be done in Obj-C... how does this work again?"

Your comment also sparks the thought that it might go beyond languages and into toolkits and frameworks. Do you parse JSON into objects with names and types, or just a big List/Hash structure? Would consistency help here? I dunno.

* to be clear, my original thoughts are just around productivity. I could see it being reasonable to sacrifices some of that productivity for some other advantage of a language or ecosystem (stability, cost, etc).

**maybe paradigms other than typing systems are a more important consideration, but this was a feature I remembered of Objective-C. Heck, maybe I've even misremembered it.