
The emperor's new clothes were built with Node.js - erjiang
http://notes.ericjiang.com/posts/751
======
dap
Just because lots of people say "non-blocking, good concurrency, event-based
model" without understanding it doesn't mean it's not correct. With a single-
threaded, event-based model, you can get an awful lot of concurrency at
reasonably consistent latency without ever thinking about threading issues or
managing thread pool size to balance memory and concurrency -- and often with
less memory, too.

Yes, there are downsides: it's not a natural model for many people; you do
still have to consider _many_ complex concurrency-related issues; and control
flow libraries are usually needed to make complex code much more readable. But
these are either easy to deal with or intrinsic to the complex problem at
hand, and the above still stands: once you understand how to program with this
model, the "default" implementation usually scales very well.

Yes, Node was not the first to do this, but that's not relevant to anything.

Besides all that: I'd put Node's postmortem debugging and dynamic tracing
capabilities up against any other dynamic environment.

As a side note: it's enormously condescending to tell people that a very broad
technical choice is not only wrong for _their_ technical problem -- without
even knowing what it is! -- but that they're also part of some mass delusion
for even thinking that there's anything to it. I hate arguing about this
stuff. You keep trashing Node, and we'll keep using it to build large
distributed systems.

~~~
erjiang
Hi, I attempted to address your argument in the section roughly titled
"Node.js has super concurrency!". You may have to scroll down "below the
fold", so to speak.

I presented two different ways of writing a single-threaded, event-based
function that can handle "an awful lot of concurrency without ever thinking
about threading issues or managing thread pool size to balance memory and
concurrency". Essentially, it is possible to get good concurrency in a single
thread without the use of many nested callbacks or abandoning the language's
natural control flow primitives. It's not necessarily the case that you can't
have both event-based concurrency and sane code.

~~~
dap
Thanks. Far from not having scrolled far enough, I was actually responding
directly to several points in that section, starting with the suggestion that
people who say "non-blocking", "super concurrency", and "evented" may not
understand what they're saying. I was also responding to your point that Node
wasn't the first runtime to do so.

Yes, other environments have compelling concurrency models. As for control
flow: it doesn't matter much to me whether the control flow abstraction is
built into the language or merely a ubiquitous construct in the code I use.
(In fact, that's a tradeoff, too: I _like_ that I can go inspect, modify, and
extend these non-primitives easily, and I've done so to add better
observability.) The Go example is interesting, but less explicit -- that, too,
is a tradeoff. It's all tradeoffs; to pretend like one thing is strictly worse
(or better) than all others is not founded.

------
kybernetikos
If you read the interviews with Ryan Dahl, one big reason he chose javascript
for his scripting language after considering a number of other options was
that javascript did not already have a huge body of blocking libraries.

If you're trying to script a nonblocking system where everything is
nonblocking all the way up and down the stack, you're going to end up creating
a parallel ecosystem to the normal one, and confuse people by not allowing
them to do the normal things they would do in language X.

Javascript didn't already have a huge blocking ecosystem.

And speaking of ecosystem, that's another really good reason to like node. The
stream programming that is coming out of the community is brilliant, and the
focus on constructing large projects by writing thin modules that use other
thin modules ('onion oriented programming') is fantastic.

I've been doing a lot of Scala recently, and it's extremely noticeable that
despite the languages power to do things in many different ways, the Scala
community frequently seem to choose a strangely convoluted path filled with
hidden magic going on behind the scenes where every new library you depend on
feels like learning a new language from scratch.

It might well be that the Go community is also as good as the node community
for some of this stuff, but the community and library ecosystem is a definite
plus point.

Personally I've never had a problem with Javascript coding. It's perhaps
easier to write stupid code in it than a lot of other languages, but I know it
well enough to know where to be disciplined, and it almost never surprises me
now.

------
pessimizer
This is the article I'm going to refer people to to explain the problems that
I have with nodejs. All of these (absolutely true) observations aside, I
really like how the the nodejs trend has brought concurrent async-style
thinking into the mainstream of web programming.

By "all of these observations aside," I mean that I _hate_ working with it
personally, and I'll be using Erlang/Webmachine thank you, but I learn new
ways to think about modern problems every day from many of the great people
that are part of the nodejs juggernaut.

------
hardwaresofton
Sarcasm is pretty heavy in this article, but I think it's a little overly
negative...

He makes a lot of comparisons with Go, but Go was created after Node. Many of
the languages he notes as possible replacements for the non-blocking rant are
obtuse (I love Haskell, but there's no way it's not obtuse)

[EDIT] - turns out they were made pretty much at the same time 2009... Learned
something today, I guess. Felt like Go came after node to me but I guess it
didn't

Also, I must be the only one that doesn't really mind callbacks. Maybe it's
stockholm syndrome.

I also think node should get kudos for at least seeming different enough to
prompt the move from enterprise customers. Any move away from burdened
"enterprisey" software is worth praising I think. Not because java is bad/lame
by default, but instead because it might prompt other companies to lust after
something new that might be better (whether it's python, node, go, or haskell
is irrelevant)

~~~
erjiang
I picked Go not because it's my dream tool (not having 'map' is kind of sad)
but because it's proof that you can have your cake and eat it too. Otherwise,
people think that you have to choose between programming sanely and high-
performance, but not both.

~~~
hardwaresofton
Yes, I agree -- but Go's got it's own warts. I think they picked up that
(err,result) common function signature from node (or they just thought of it
themselves, either way).

However, I think once you start trying to manage go routines and all their
channels, and all the messages that are flying around, go will start looking
less utopian. Of course, a lot of that is subject to code architecture (well
architected code will be easy to follow), but I feel like no one's found
enough of the dark corners of go yet.

Oh one thing I wanted to mention - Why didn't you include any samples of go
routines in your code?

Unless I am misunderstanding go immensely, a statement like
"(task3(task2(task1()))" wouldn't actually be asynchronous, you would need to
spawn dependent go routines right, and wait on completion on the channels?

~~~
danudey
> a statement like "(task3(task2(task1()))" wouldn't actually be asynchronous

Correct, because you're passing the result of task1() into task2(), and the
result of that to task3(), afaik.

------
aespinoza
I agree with a lot of the arguments in the article, but I do feel a very
negative opinion about Node.js. I don't believe Node.js is that bad.

The 2 points I always hear from Node.js are:

1) Node.js is fast. It is really not that fast. It all depends on what you are
comparing it to.

2) It is easy to learn. It is not easy to learn. The difference between
browser javascript and V8 javascript are considerable. Not everybody will pick
it up as easy as you imagine, specially if you are choosing Node.js to allow
frontend devs work on backend code. It is a very different mindset.

I like the idea that is Node.js, but I don't think it is mature enough to take
over the backend. I think there are other more mature languages right now that
do the job without making programs look like spaghetti code.

I think people should take this article with a grain of salt, and keep getting
their hands dirty in Node.js. I think it has a future in the cloud.

------
mambodog
Why is it that most of the articles which pop up complaining about node's
concurrency options don't even mention streams? For most data-manipulation
tasks, FRP-style composition of higher order operations on streams turns out
to be the best choice; not callbacks, promises, etc. Not even bringing them up
in a discussion of concurrency in node makes it hard to take the article
seriously.

~~~
xhrpost
Not sure I've ran across what you're describing. Are you talking about using
streams as an option to get around callback hell? Have a link describing this?

~~~
mambodog
[http://caolanmcmahon.com/posts/how_i_want_to_write_node_stre...](http://caolanmcmahon.com/posts/how_i_want_to_write_node_stream_all_the_things_new/)

[http://highlandjs.org/](http://highlandjs.org/)

[https://github.com/dominictarr/event-
stream](https://github.com/dominictarr/event-stream)

[http://reactive-extensions.github.io/RxJS/](http://reactive-
extensions.github.io/RxJS/)

------
akilism
Computer Programming: A million wrong ways to do something and a million right
ways to do something.

~~~
Cthulhu_
And where the only correct answer is "It Depends"

------
mslider
Isn't it just the case that nodejs is the least worst way of writing a
concurrent web server? we know it's not perfect, but what is?

~~~
bphogan
I'd like to think that if we weren't all watching Node we'd have more people
to pitch into other things. I hear a lot of bluster about "learn new things"
but I often just see people sticking with what they know. When the bright
minds of web development are figuring out new ways to make JavaScript less
awful, those minds aren't focusing on other solutions.

FWIW I think Elixir holds a lot of promise for the future. Projects like
[https://github.com/dynamo/dynamo](https://github.com/dynamo/dynamo) look
really cool. Of course, it's new, and alpha. But maybe we could all give it a
try?

~~~
wcummings
Erlang pretty much blows Node.js out of the water, in terms of sophistication
of concurrency primitives (to mention one thing). Erlang is really just syntax
on top of BEAM, which is pretty tailored to the language (you'll notice Elixir
and Erlang share identical types etc).

Elixir adds some nice metaprogramming features, and I love that it exists.
Erlang is used for a lot of Important Things in production, and its value to
many developers is stability and fault tolerance. Erlang moves slow. It's nice
to see a sister language that can more rapidly develop new language features
(maybe some of the goods ones will get added to Erlang (:

Joe Arms post about Elixir is pretty interesting [1]

[1] [http://joearms.github.io/2013/05/31/a-week-with-
elixir.html](http://joearms.github.io/2013/05/31/a-week-with-elixir.html)

------
aashishkoirala
I love your ending :) "Does your local Node.js Meetup group need a presenter?
I am available for paid speaking engagements. Email me for more info."

------
logn
I prefer [http://silkjs.net](http://silkjs.net)

It handles each request in a forked subprocess so it's a lot more straight
forward.

~~~
hardwaresofton
without sounding like a web 3.0 idiot -- how do you manage to scale that?
subprocesses are not cheap

~~~
logn
I'm sure someone else reading can answer your question based on more
experience and expertise than me... anyhow the subprocesses are re-used so
there's no overhead in their creation. And if your server is doing I/O bound
work (or is just waiting a lot) then it should perform ok. If everything is
CPU bound, then you'd want to not create more subprocesses than cores. SilkJS
lets you define the number of subprocesses you want.

More info:

[http://silkjs.net/sync-vs-async/](http://silkjs.net/sync-vs-async/)

~~~
hardwaresofton
Thanks for the additional info -- though I would argue that it starts to sound
like apache+fcgi (not that it's bad), or unicorn+wsgi... I think node pushes
async to an extreme that makes it truly different from what's out there.
Unfortunately, it results in leaky abstractions, and lots of misguided
enthusiasm as the post goes into...

You could think of pure functional programming (haskell/ml) as a similar
extreme -- Haskell gets a lot of concurrency/parallelism guarantees for free
just because of how the language was built (pure functions,etc)... Is it wrong
to think that node took a similarly crazy step, but in their case, they
weren't able to rebuild the language, and that's what you get?

If I wanted to event-loop, or lightweight thread stuff in python, I'd need
some libraries, and many of the ones that you might find are not very easy to
learn.

------
ilaksh
I use ToffeeScript. Its a nice alternative to nested callbacks that looks like
normal synchronous code.

------
general_failure
Node is popular because it is fairly simple to learn and use. That really is
the mains reason why I have seen most people pick it up.

~~~
erjiang
I assume you read what I wrote and I wasn't clear enough. Node is actually
quite DIFFICULT to learn and use. It's very very easy to write code that's
broken in some way if you don't have a deep understanding of Node.js.

Fun unrelated anecdote: someone was showing off their concurrent Node.js web
scraper and as requests piled up, it was apparent that it could handle no more
than 5 concurrent requests. Why? The HTTP library's internal concurrency limit
defaulted to 5.

~~~
dap
How many concurrent requests can the six-line HTTP server on Node's front page
serve? (I don't know the answer. I've taken a quick stab a few times on a few
platforms, but I keep running into local TCP port exhaustion, leading to
multi-second latency bubbles, long before I run into any Node.js or physical
limit.)

~~~
randallsquared
Not sure if you changed the context from HTTP clients to HTTP servers
intentionally, but it's true that the default of five connections is an
outgoing connections restriction, not related to the HTTP server.

This client restriction is deeply irritating. A project I was involved with is
about creating a general purpose hypermedia API, and building up documents
involved following the links in parent documents back through the API, which
meant that a single request can end up requiring hundreds of further calls to
satisfy, which seemed like no problem at first with node.js' easy concurrency
(and an auto-scaling fleet of EC2 servers), but the client connection limit
turned out to be the cause of a lot of timeouts and prompted a lot of working
around.

~~~
dap
The client "limit" is just a tunable with a bad default value. You can tune
this up and completely eliminate that limit. (The failure mode is pretty bad,
but this comes from a lack of observability in abstraction design that
pervades most code.) The server example, on the other hand, demonstrates the
point that the default way to write a "hello world" web server actually scales
very well.

------
compsci_mofo
We learnt that Node wasn't cancer, but it also wasn't a good technology
either. Still, it was useful in keeping the clueless muppets away, lest they
fuck up other tech ecosystems.

------
woah
These articles always seem to boil down to only one thing- "I'm bad at
callbacks".

I mean, really, is there any other criticism here? There is a valid point
about the true nature of Walmart and Paypal's rewrites, but that's pretty
tangential.

There's kind of a thing about some completely rookie mistakes in error
handling, but that's really not relevant to anything, and again, tie into the
"I'm bad at callbacks" thing.

I'd really be interested in some criticisms of node that aren't variations on
stories of the author's past difficulties with callbacks, as most people who
use node have no problems with them.

EDIT: Downvotes? Please, point out to me the part of the article that is not
about callback troubles.

