

Drinking the Node.js Kool-Aid - shawndumas
http://journal.paul.querna.org/articles/2010/06/12/node-js/

======
andrewvc
Since we're talking about node...

I like async, and I like node. However, for plain jane dynamic web apps, with
no real time needs, I see it as being more of pain than using Ruby (or Python,
or whatever).

Why? JS syntax kinda sucks for dealing with day to day business logic. Ruby is
just more clear and easier to work with.

I think using node.js by default is bad design. It should be isolated to the
cases where you need it.

~~~
FlemishBeeCycle
If you find the syntax to be a problem - you may find CoffeeScript
(<http://coffeescript.org/>) interesting. It emphasizes the good parts of
JavaScript while minimizing the warts, all wrapped up in very nice syntax.

~~~
jashkenas
Here's a fun example. Matz (creator of Ruby) contributed a chapter to
Beautiful Code (the O'Reilly book). In it, he uses this example of a Rake task
as his example of a beautiful piece of Ruby:

    
    
        task :default => [:test]
        task :test do
          ruby "test/unittest.rb"
        end
    
    

Let's see what that could look like in CoffeeScript, assuming a similar
library:

    
    
        task default: ['test']
        task 'test', ->
          ruby 'test/unittest.rb'
    
    

Pretty nice. Running that through the CoffeeScript compiler produces this
JavaScript:

    
    
        task({
          "default": ['test']
        });
        task('test', function() {
          return ruby('test/unittest.rb');
        });

------
enneff
"Everything is Async: Because the base environment has been built essentially
from scratch, everything is asynchronous. This means there is no ‘defer to
thread’ like in Twisted Python; You just can’t make blocking code."

This is not necessarily a good thing. Sometimes you need to write a piece of
code that executes sequentially. Having the ability to do that if you need to
is a good thing. Sometimes it can be unnatural and unwieldy to split a block
of functionality up into a set of callback functions.

~~~
mjw
Yep. Your code ends up looking like the output of a continuation-passing
transform, with every kind of sequential composition involving nested
callbacks. It feels quite low-level and clunky and is one of the things I like
least about writing Javascript on the browser.

Another thing is, when you go async, you're essentially giving up on using the
language runtime's stack for most purposes. With that, you lose some useful
functionality (useful stack traces, exceptions bubbling up).

~~~
Andi
Use Step, man

------
mkramlich
Node.js is one of the most promising sounding projects I've seen in the last
year in terms of something I may actually use in production code. JavaScript's
agile syntax combined with ubiquity thanks to web browsers make it one of the
few languages that would make switching to it bearable for, say, a Pythonista
like me. And Node.js may be the final straw that unleashes it on the server-
side.

~~~
weixiyen
Curious though, if you are a Pythonista, why not use something like gevent or
tornado?

~~~
dlsspy
tornado solves one very specific problem that friendfeed had. It's being used
for other problems, but it solves them less well than, say, twisted.

twisted solves networking problems of all types really well, but (as Paul
mentions in his post), most libraries for python are written assuming they
have the entire interpreter to themselves for as long as they want (which in
the naïve case, turns it into tornado, but it at least has facilities for
running async tasks in other threads or processes).

node.js does as well, but it's developing a very rich library very fast.
Certain things are harder to deal with (personally, I think twisted got async
error handling right and most everyone else hasn't got there yet), but people
think they understand javascript better than they think they can understand
twisted.

~~~
frognibble
Tornado solves the problem of building web frontends, particularly those with
comet features. This problem is not specific to FriendFeed. A number of other
services use Tornado including Brizzly, Quora and Hipmunk.

Twisted has support for many network protocols while Tornado only has support
for HTTP (client and server). If you are doing something other than HTTP, than
Twisted might be the better choice.

~~~
dlsspy
I argue that twisted is better for most practical uses of comet.

Tornado mastered only the "have lots of suspended connections" thing. Many of
the examples involve blocking for processing one of those connections. What's
the point of having 20k connections terminated on an http comet connection if
you completely block the entire event loop to service a single one while you
make another network connection (e.g. memcached, mysql, etc...).

In this regard, _most_ real life comet apps are doing more than http. To be
fair, tornado did ship with a yet another python http client, so you can at
least use it with a database that speaks http without blocking, though without
chainable deferreds, it's hard to do the exact right continuations required to
chain these events together without locking the event loop.

~~~
frognibble
The Tornado philosophy is to use blocking for fast operations and async for
the occasional long operation. Tornado applications compensate for blocking by
running several instances of the application.

Twisted is theoretically better than Tornado because everything is async in
Twisted, but Tornado is more practical because it's easier to write straight-
line code than chains of callbacks. The cost of Tornado is that you need more
memory on the frontend because you run more instances of the application.

In my previous comment, I listed some real life comet applications that use
Tornado. What real life comet applications use Twisted?

~~~
dlsspy
@inlineCallbacks make linear code very easy to write in twisted. Have you
tried it lately? Here's a snippet of code out of my gearman implementation:

    
    
        @defer.inlineCallbacks
        def gclient(gearman):
            w = client.GearmanClient(gearman)
            x = yield w.submit('test', 'some data')
            print "result:", repr(x)
    

Pretty straighforward, I think -- you just stick a 'yield' between your
invocation and the capture of the results.

As far as who's using in actual comet applications -- it's hard to say. The
last time I tried looking for a comet implementation, what appeared to be the
canonical "cometd" was written in twisted. I ended up not using it and rolled
my own twisted based server that was closer to my requirements. It's been in
production for a few years now, but is still a somewhat secret project.

I'm pretty sure you could research their userbase as well as I could.

I'm not saying twisted is perfect and all other technology sucks (though
deferreds, once you understand them, are really the only way to do this sort
of thing).

When tornado was launched, I started playing with it and couldn't understand
why it prevented me from integrating so many asynchronous tasks. I spent an
hour or two separating the good parts of tornado from the reimplementation of
twisted and built tornado on top of twisted. It was, as far as I could tell,
at the starting point, minus 1,297 lines of python.

------
equark
While node.js has some appealing characteristics it doesn't seem to solve the
main problem with realtime web apps -- coordination between the multiple
client side view states and the server side state. It's easy enough to hack
together communication between these two layers but it always feels a bit half
baked. Something like etherpad should be the new hello world app.

~~~
aaronblohowiak
Groupware is an extraordinarily difficult problemin this respect, especially
if you want to handle the rare edge cases. The problem with maintaining
multiple client side view states to be the same has a great deal of intrinsic
complexity due to the very weak guarantees provided by network communication
(if you want any kind of responsiveness whatsoever.)

~~~
equark
True, but I suspect there is a lot that could be done by baking something like
the feedsync protocol together with knockout.js style view binding, node.js
and a websocket connection.

~~~
aaronblohowiak
The problem with feedsync and trying to serialize knockout.js to disconnected
clients is conflict handling. Secondly, you have to worry about potentially
divergent states if messages are lost in-transit (depending how robust your
needs are.)

That being said, you could hack something together with a very optimistic
approach using knockout.js and socket.io (to gracefully degrade if websockets
arent available.)

------
bostonvaulter2
So it is possible to write an entire webapp in Node.js? I think I'll try it
out on my next project since I don't have experience in any web frameworks. I
wonder if Node.js has any Postgres bindings.

~~~
rpmcb
By Dahl himself, actually.

<http://github.com/ry/node_postgres>

