Paul Hammond's Journal
Some things of interest to Paul Hammond, arranged in a reverse chronological order with a feed
I spent a chunk of today catching up with the state of public data for the San Francisco Muni.
Minimuni has been broken for a few months now. At some point NextBus changed their website slightly and it broke the screenscraper. Mike told me he had some updated code that worked, but he never sent it to me and I never got round to asking for it.
Today I noticed (via lhl) that NextMuni has an API, so I spent an hour or two exploring it. It's really good.
It has all of the data I was scraping from the website and then some, including current locations of trains, the lat/long of every stop on the network, detailed description of routes, and most importantly expected arrival times. Most of the time spent making Minimuni was getting the scraper working, so I can see how easy access to data will encourage more transit based apps.
So Minimuni works again (with the updated source on github) and if you're interested in getting data about SF Muni you should go look at the SF Muni API.
Posted 2009-11-09
Google released XMPP support for App Engine a few days ago and I spent a couple of hours playing with it last night. The result is Pingr, another app that solves a problem for me and me only.
My wonderful wife Amy has only one annoying habit; when she's at home she often leaves her phone in her bag next to the front door and doesn't notice when I'm trying to call or text her. We don't have a home phone, so when this happens I have to log onto IM to send her a message, and at some point she'll notice it on her laptop and get back to me. Pingr reduces this to one step, a "ping" message is sent whenever I press the button on my iPhone home screen:
Of course the app is completely pointless, it's just a good excuse to play with the technology.
As with the rest of App Engine, the XMPP support is (mostly) well documented, and just works. Treating incoming messages the same as incoming HTTP requests is a nice abstraction, having both in the same framework makes writing apps that bridge the web and XMPP easy. It reminds me of the hacking I did on POE 5 years ago, but much much easier.
There were a couple of rough patches:
- There's no documentation on how to test XMPP handlers locally. I found the test page in the SDK console at
/_ah/admin/xmpp/ by accident, until then the only way I could think of to test was to deploy it to Google's servers and test in production.
- The handling of JIDs is less polished than I'd expect. There's some documentation on "JIDs", "Resources" and "Bare JIDs", but the sample code ignores the details entirely and there's no convenience functions to handle them. It's nothing that a
split('/') can't handle, but it's something that will trip up people not already familiar with how XMPP works.
- The "Oops. Something went wrong." message gets really annoying really quickly. If I have debugging on it'd be nice to get some kind of error in context without having to go to the admin console and check the logs.

Nitpicking aside, it took me longer to pick colors for the icon than it did to learn the framework from scratch and write the code. That alone makes XMPP in App Engine very interesting.
Posted 2009-09-05
Inspired by Delta909's Pixel Matrix wallpaper, I've been playing with layering randomly generated alpha transparent PNG grids on top of photos:
This is three images layered on top of each other:
- a photo
- a grid of white squares with random opacity
- a grid of black squares with random opacity
The grids are different sizes to decrease obvious tile repetition. They were generated using a small ruby script.
Posted 2009-07-06
I spoke at Velocity 2009 on Tuesday with my friend John Allspaw about how we work together at Flickr to make a lot of changes to the site without breaking it too often.
This is the third talk I've given with others around how to work together, but the first time I've tackled the ops/dev connection. It seems this relationship is easier to reflect on; it felt more natural giving direct advice in our talk instead of vague handwaving about designers and developers being nice to each other.
The slides are available as a PDF, or you can look at them on slideshare. A video of the session is up on blip.tv, and there's even a code.flickr.com post about the whole thing.
Posted 2009-06-29
I've had a new version of webkit2png ready to release for over 4 years now. Until today I'd just never got around to pushing it out the door.
The new version includes a bunch of random bug fixes and some new options. The most interesting change is a --delay flag that makes it possible to take screenshots of websites that do things after the page loads, which is particularly useful for sites that use flash.
While I was at it, I also spruced up the instructions, relicensed the code under the MIT license, and uploaded the complete revision history to GitHub.
Go get it.
Posted 2009-03-29
Behind the scenes, Minimuni is written in Python and hosted on Google App Engine.
My initial impressions of App Engine have been good. Really good. Everything just works good.
Like Rails, Django and Merb you're up and running in minutes. But unlike those frameworks, once you're done building an app there's no long complex deployment tutorials to follow, you just type appcfg.py update and your app is live.
The tutorials and documentation are also clear and easy to follow. I spent much longer remembering how Python works than I did learning the nuances of the AppEngine APIs. I wish more developers (particularly the Ruby crowd) remembered how important documentation is; it doesn't matter how awesome a library or framework is if nobody can work out how to use it.
The only problem I had was that the process to get things running under my own domain was stupidly over-complex. This is mostly because the flow was set up to sell me Google's domain groupware hosting, even though I'm just not interested in it. This is big company thinking in action - making individual products worse in an attempt to cross promote, and forcing code reuse even when it doesn't make sense. Compare it to Tumblr's awesome implementation of custom domains to see how easy this process could be.
Minimuni is deliberately not a complex application. It stores no data behind the scenes, so I've missed some of the problems other's have had with App Engine. On the other hand, I've developed plenty of small one-off applications over the years, and I'm bored of running a server underneath them. Every time I upgrade Apache or MySQL or a random Perl module something breaks in another project which I then need to fix. Of course, the App Engine API is going to change over the years, but hopefully in a much more controlled and backward compatible way.
App Engine is pretty much perfect for apps like this, and I can see me using it a lot more in the future...
Posted 2008-12-05
I live near Duboce Park in San Francisco:

Every SF Muni streetcar line runs within walking distance of my house, but they all stop in different places. I can't wait in one place and be sure to catch the next train that goes past.
I used leave the house and hope that I wouldn't have to wait too long for a train to turn up. I'd often get to Duboce Avenue just in time to see a train disappear into the tunnel. I'd then end up waiting 10 minutes at the corner of Duboce and Church for the next J or N, wondering the whole time if I should walk to Church station and catch a K, L or M.
That got a bit much for me, so I made this:

It puts arrival information for all the stops near me on one page, and puts the emphasis on when I need to leave the house to catch a train. It tells me whether I need to get going right now, or whether I have 5 minutes to play with my kid before leaving.
I've had a beta version running for a few weeks, and it's completely changed my mornings. I'm getting to work earlier and a lot less stressed.
As the about page says, if you live exactly 6 minutes from Sunset Tunnel East Portal, 8 minutes from Duboce and Church, and 10 minutes from Church Station you may find it useful too.
Posted 2008-12-03
“Management’s job is not to prevent risk but to build the capability to recover when failures occur.”
— Pixar (via Timo)
Posted 2008-10-28