Node.js Thinks Like A Man

Any man with a wife or girlfriend knows a fundamental fact: women can multi-task and men can’t.  V8 in this respect is exactly like a man: it can only do one thing at once.  Node.js uses V8 and makes a virtue of it.  Only doing one thing at once means there’s no race conditions in your memory model.  None.  I’ve lost count of the number of times I’ve been writing node.js code and worrying about “what happens if the array length changes while I’m reading” before realizing it 100% can’t happen.

One thing that men know is that you don’t actually need to do two things at once.  Consider how you make a cup of tea

kettle.boil()
cup.fill()
cup.waitUntilBrewed()
cup.serve()

Well, actually, if you want to do the dishes at the same time, this isn’t how you do it at all.  What you do is switch the kettle on, then you go and start washing.  When the kettle clicks, you then stop what you were doing and fill the cup.

kettle.switchOn()
kettle.on ‘boiled’, –> cup.fill()
cup.on ‘brewed’. –> cup.server()

Notice that we’ve lost the names “boil” and “waitUntilBrewed”.  These are words that denote processes.  Everything in node.js is asynchronous, and process verbs imply a sychronous approach.  The words we are left with indicate actions and events.  It’s also worth noticing that with a multi-threaded environment, you’d be very careful to ensure that event bindings were set up before you kicked off the process that could fire the event.  With node.js, you’re guaranteed that your current code will finish before anything else happens.  While you’re talking, you have node’s undivided attention until you stop talking.

Doing The Dishes

So, how do you do the dishes?  Well, the simplest way to handle this would be

_.forEach dishes, (d) –> d.wash()

If you do this, you’ll never hear the kettle boil.  Remember, a man can only do one thing at once, even pay attention.  So, you need a way to specify that you want to pay attention

interruptibleForEach = (list, f) –>
    index = 0
    action = –>
        return if index >= list.length
        f list[index]
        index++
        process.nextTick action
    action()

You might want to compare this code to the Caliburn Micro Co-Routine Trick.  It’s fundamentally the same code.  There’s a catch, though.  You won’t stop washing dishes for very long.  In fact, you’re guaranteed to wash a dish between filling the cup and it being brewed to your satisfaction.  Now, you could generalize all of this to interruptible processes, but you’d be missing the point: doing a synchronous process like washing dishes is a fundamentally bad idea in node.js.  If you can’t figure out a decent way to express it as a series of events, you need to hive it off to a sub-process.  You then communicate with that through asynchronous RPC or pub/sub.  I’m going to avoid any obvious gender stereotype humour here.  If you want that sort of stuff, you can read the ZeroMQ Guide.

Personal Note: I was hit by Hurricane Penelope six weeks ago.  She is insanely gorgeous and an awful lot of work.  As a consequence, it’s quite hard to get out blog articles, so please forgive me any stupid errors and formatting problems.  Next time, I hope to talk about Jetlang Remoting again, but it might take a while…

Technorati Tags: ,