← Back to context

Comment by gruseom

14 years ago

comment on the technical merit

Hi, Hrishi. There is a grain of technical merit in two of his three objections, but he trollishly overstates them. I've had to think about some of the same questions lately, so here are some thoughts. If anyone has a substantially different perspective, I'd like to hear it.

By the way, the most interesting thing about his critique is that he doesn't even touch on the most common objection to Node, that async callbacks don't compose well and so break down under complexity. That one's been argued to death on HN, though, so I'll follow his example and leave it out of this.

Let's consider the criticisms in reverse order. #3, about Javascript, we can dismiss as a vacuous language flame. #2 is about separation of concerns. He argues that web servers should be separate from web apps, and Node confuses the two by doing web server stuff (handling HTTP requests) and app stuff (whatever your app does) in the same context. Now you either have to put a "real" web server in front of Node (in which case there's the question of what value Node's adding) or use a relatively immature web server (Node itself) as your front end. There is a good point about modularity here. But is the line between web servers and web apps always so clear-cut? If his argument were completely true, CGI would be perfect for everything. Most people wouldn't agree with that. Moreover, you wouldn't see complex configuration languages and extension APIs for web servers, the kinds of things that arise when the lines start to blur (and are not very pleasant to work with). So the question is just how separate the concerns really are. This surely depends on the application. Separation of concerns is a good thing until interactions between modules become unduly complex, at which point one sometimes gets a big simplification by unifying them.

For example, in the project I'm working on, there are resources that need to be requested by the browser and sometimes also by the (app) server in order to complete some computation. You could divide this work many different ways, but it sure is convenient to just write Node handlers to do whatever I/O you need in the course of completing a request. To have the app server go back to the web server would be awkward, and so would having two different ways of fetching the same stuff.

#1 is about blocking. He refutes a blurb that says "nothing blocks in Node" by showing a trivial example that indeed does block Node by doing a long computation in an event handler. (One wonders why he didn't go full retard and just put an infinite loop in there.) This is a deliberate misreading of the blurb, which obviously meant not "nothing blocks" but "no I/O blocks". So, a straw man. But dig deeper and there is a valid point nearby. If you have long computations to do while fulfilling a request (where "long" is defined as "taking longer than you're comfortable having all other requests to this server wait"), then for Node to work well, you have to farm those computations out to other processes. This is doable, but adds complexity. You start to move out of Node's sweet spot.

What's the sweet spot? If writing your server code in Javascript is a win for you and your app is I/O bound (more precisely, if there aren't any long-running computations as defined above), Node looks pretty good. If in addition the app server and web server have more complex interactions than just "here's your request" and "here's your reply", it starts to look really good. An example might be a web chat app.

As things get more complex, the judgments get trickier. In our case, we do have long-running computations. Bad for Node. But we also have webserver-like needs in our appserver, a lot of I/O that we don't want to block on, and Javascript is a big win for us. So on the whole Node wins. Take away the point about Javascript, though, and it probably wouldn't.