Ayende @ Rahien

Refunds available at head office

Reviewing Postman

I enjoy reading code, and I decided that of a change, I want to read code that isn’t in .NET. The following is a review of Postman:

Postman is a little JavaScript library (well it's actually Coffeescript but the Cakefile handles a build for me) which is similar to a traditional pub/ sub library, just a whole lot smarter.

This is actually the first time that I looked at Coffescript code (beyond cursory glance at the tutorial a time or two). I got to say, it looks pretty neat. Take a look at the definition of  a linked list:

image

Pretty, readable and to the point. I like that.

Then I got to a head scratching piece:

image

There are various things that refer to postie, but it wasn’t until I got to the bottom of the code that I saw:

image

So I guess that postie line is actually defining a null argument, so it can be captured by the class Postman class methods.

I’ll be the first to admit that I am not a JS / CoffeeScript guy, so sometimes I am a little slow to figure things out, this method gave me a pause:

image

It took a while to figure out what is going on there.

The first few lines basically say, skip the first argument and capture the rest, then call all the subscriptions with the new msg.

Note that this is preserving history. So we can do something with this.

There is also an async version of this, confusing called deliverSync.

Getting the notification is done via:

image

This is quite elegant, because it means that you don’t lose out on messages that have already been published.

I guess that you might need to worry about memory usage, but there seems to be some mechanism to sort that out too. So you can explicitly clean things out. Which works well enough, I guess, but I would probably do some sort of builtin limits for how many msgs it can hold at any one time, just to be on the safe side. I don’t actually know how you would debug a memory leak in such a system, but I am guessing it can’t be fun.

image

This code makes my head hurt a big, because of the ability to pass a date or a function. I would rather have an options argument here, rather than overloading the parameter. It might be that I am a bad JS / CoffeScript coder and try to impose standards of behavior from C#, though.

All in all, this seems to be a fairly nice system, there is a test suite that is quite readable, and it is a fun codebase to read.

Tags:

Posted By: Ayende Rahien

Published at

Originally posted at

Comments

Ben Dornis
01/07/2012 08:29 PM by
Ben Dornis

I should point out that this project belongs to Aaron Powell (https://github.com/aaronpowell/Postman) and that Ayende Rahien reviewed my fork :)

Pete Weissbrod
03/09/2012 08:58 PM by
Pete Weissbrod

I imagine that most of the reactions javascript programmers have with coffeescript sounds just like the same reactions assembly programmers used to have with C

Demis Bellot
03/11/2012 09:07 AM by
Demis Bellot

Nice overview Oren.

I love the CoffeeScript language and culture which is aimed at expressing your intent as succinctly and readable as possible where un-necessary abstractions are shunned in favour of simple, elegant and functional solutions. Refreshing change from the over abstraction fetish I constantly run into with C# culture.

Jeremy Ashkenas is the master mind behind CoffeeScript who is also the author behind the very popular js libraries Underscore.js and Backbone.js - the choice js libs for building Single Page Apps with.

CoffeeScript is also included in Rails with the 37 Signals elite now preferring to use it over JS for their client side development, here's a good introduction to CoffeeScript from Sam Stephenson (of Prototype.js and Rails fame): http://vimeo.com/35258313

The weird thing about the deliver() method above is that CoffeeScript actually has support for splats that automatically convert the remaining javascripts functional arguments into an array so this:

deliver: () -> name = arguments[0] createCache name if ! cache[name] args = [].slice.call arguments, 1 args = [] if !args args = [args] if !isArray args

Can effectively been rewritten to:

deliver: (name, args...) -> createCache name if ! cache[name]

Which is even more readable and terse.

Aaron Powell
03/11/2012 09:14 AM by
Aaron Powell

Awesome, 15 seconds of fame! :P

I'm not sure what's more baffling, that of all my code (across Umbraco, FunnelWeb, docpad, tbd, etc) this is the one that gets reviewed or that Postman actually has forks (in fact it has 6)!

Just a few points, the lose declaration of 'postie' was because I wasn't familiar enough with "fat rocket" in CoffeeScript. I'm pretty sure you could fix that by using the function binding properly, but oh well, live and learn ;).

With regards to your final point it's a common practice in JavaScript to "mix and match" your arguments, since they are untyped you can get away doing that. If you take a look at jQuery you can pass in are:

  • A function
  • An array
  • A selector
  • A DOM element
  • Nothing

And many jQuery methods will take different argument types in the same place (values or functions is the common one) to do different actions. I'd say you're right in your assessment that you're applying C# practices to JavaScript, which isn't a good idea ;).

But none the less I'm glad you liked Postman :D

Joe
03/11/2012 10:46 PM by
Joe

Nice one!

Comments have been closed on this topic.