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:
Pretty, readable and to the point. I like that.
Then I got to a head scratching piece:
There are various things that refer to postie, but it wasn’t until I got to the bottom of the code that I saw:
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:
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:
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.
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.
Comments
I should point out that this project belongs to Aaron Powell (https://github.com/aaronpowell/Postman) and that Ayende Rahien reviewed my fork :)
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
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.
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:
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
Nice one!
Comment preview