software for job hunting

So I’m hunting for a job right now. (See my résumé, also posted on the front page of this site, if you happen to be hiring coders who travel, eg as sales engineers. 🙂

I’ve been hunting on and off since, err, gosh, I guess since September of last year. At this point I’ve talked to at least a dozen companies — some just at the level of trading a couple e-mails before one of us decided the other wasn’t a good fit, all the way up to one whose (thankfully non-exploding) offer I’ve been sitting on for a while. I’m at various stages of the interview process with enough companies that I’ve stopped being able to keep track of them all in my head, and we jump between enough communications mediums (phone, e-mail, in-person interview) that I can’t rely on my e-mail client to keep it all together. I started thinking about this a few weeks ago, and I played around a bit with the free trial version of Salesforce.com, but it pretty quickly became obvious that Salesforce was way more complicated than I needed in some ways and not featureful enough in others. Also, expensive. But the cognitive load of keeping track of all of these opportunities was starting to be a serious stressor, so I knew I had to do something. Then came spring break this past week (yay unscheduled time!), and so I broke down and started writing my own CRM (well, Potential Employer Relationship Manager) to manage my job-hunt.

I sketched out the basic data model pretty quickly, and it was obvious from that that I was going to want a database to back the system. I wanted it to be web-based, because I was going to need to be able to access it from anywhere over the public Internet, so that meant a web framework of some kind. Python is my default language these days for projects which don’t obviously require something different (text processing? Perl; manipulating binary data? C), and I’d walked through the Django tutorial before, and knew I could get something up quickly, so those both seemed like good choices. I used Git for source control because it’s my default these days, and it’s so stupid-simple to set up a repository for something that I’ve stopped even thinking about it.

At the beginning, I laid out the key requirements of the system, which were:

  • I wanted a dashboard view which would show me, on a single page, the status of every potential job opportunity I was tracking, so I could easily see who I needed to respond to and who I hadn’t heard from in a while and needed to poke.
  • It needed to accept e-mail and use that to update the dashboard view.
  • It also needed to support action items which weren’t e-mail messages, so I could eg. put my interview dates in the app.
  • I needed integration in my mail client so I could quickly send entire threads to the app.

Partway into the project I realized that Django’s default support for schema migration is basically non-existent, so, since the details of the data format were still seriously in flux, I was going to potentially be rebuilding the entire state of my app from e-mail every few days. That added a couple more requirements:

  • The app needed to save all e-mail sent to it outside the database so I could rebuild its state quickly.
  • I needed tools in the app that would let me quickly categorize a large amount of e-mail.

I got the dashboard up very quickly, relying entirely on Django’s very nice built-in admin interface to handle the heavy lifting of actually creating objects in the database. After a false start trying to make the app run a custom SMTP server using Python’s built-in smtpd library, which didn’t seem to actually work, I realized that my MTA, Exim4, would pipe incoming mails to a process specified in a user’s .forward file, so I set up a username for the app to run under and got it accepting e-mail. Python’s built-in mailbox library let me easily create a secondary mail store for rebuilding, and I kludged the ability to forward threads to the app onto the Sup hook script I use to forward spam to my spam filtering provider. Then I built a form for categorizing messages, the biggest innovation of which is the “associate all other correspondance with this contact with this opportunity” button. That all was basically my week, and by the end of it I was able to process a few hundred e-mails into a dozen or so job opportunities in the span of twenty minutes or so, giving me a dashboard that looks like this (censored, obviously):

 

It is not very pretty — I’m not a web designer or a leet CSS+HTML haxxor, and it shows — but that’s not the point. Now I Bcc: my app on all the job-related e-mails I send, and I can see at a glance what I need to take action on.

The code is very very alpha right now, and needs docs, tests, everything you expect from software that wasn’t written over spring break by a hosed MIT student. I’ll clean it up and do something with it after I’ve graduated. I’ll also probably hack more on it as I need new features or find existing bugs — I’ve adopted kcr‘s rule that whenever I feel like accomplishing something by frobbing the database directly, I’ll instead write the code to automate the process. Right now it meets my minimum requirements, and I’m pretty happy with that.

A few observations on the tools I used, mostly Django (caveat: I’m using 1.0 because it’s what Debian stable has):

  • Django is in fact awesome for rapid prototyping/development of web apps.
  • Django would be even more awesome for rapid prototyping/development of web apps if it had any kind of discernable story around schema migration.
  • The Django admin interface is awesome for rapid prototyping/development of web apps.
  • The Django admin interface would be even more awesome for rapid prototyping/development of web apps if there were some middle ground between “using the admin interface” and “writing HTML forms by hand, sucker”.
  • More generally, I was surprised and disappointed that the framework didn’t give me more help with the UI, or anything remotely AJAXy. (The app as it currently stands is AJAX-less. Too much work for too little reward.)
  • Wow, Django is really big on keeping views and templates separate. I can’t embed arbitrary Python code in my templates. Weeeeeird.
  • Django is blessedly well-documented and easy to pick up.
  • Python is a language made for writing ORMs, and Django’s is a nice one.
  • I’m impressed at the breadth of Python’s standard library. Everything I’d have gotten off CPAN if I were using Perl — eg. e-mail (RFC822) and mbox handling — was shipped with the Python interpreter. I didn’t have to pull in any external libraries besides Django.
  • Not so impressive: the smtpd library shipped with the 2.5.something Python interpreter was poorly documented and didn’t seem to work. I expect better QA of things which are included in the standard distribution. (Though maybe that’s less reasonable to expect when everything is included in the standard distribution? I don’t know.)

It was a good learning experience and a pretty good use of my spring break. I’m now much less stressed about things falling through the cracks in my memory, which makes the entire project very much worth the time it took.

Now I just need to find a job. 😉

richard iii

With the knowledge that posting a review of the last night of a show is not particularly useful… I went and saw the MIT Shakespeare Ensemble's production of Richard III this evening. I'm still kind of awash in the catharsis right now and don't feel like making this a proper review, and, well, see above about its utility. But I have some history with this play in particular, and I've nattered on about it here before1, so bear with me as I natter on some more.

It was a really good show — on par with the Ensemble's best. To be sure, a few of the minor characters weren't superb, and the doubling of characters to actor was confusing to me on a couple occasions, but it's still among the best theater I've seen at MIT. In Richard's opening monologue, he was displaying a distressing tendency to Channel. William. Shatner. And. Punctuate. Every. Phrase. With. A. Gesture. (Here picture the actor milking the giant cow.) Thankfully he smoothed out a lot as the show went on, especially in dialogue with other characters, and such tendencies only briefly appeared in a small number of subsequent monologues. (And dear ghu Richard has a lot of monologues in the beginning of the show.)

The lighting designer had too much of a fondness for shadows, IMO, which made it hard to read the actors' lips occasionally, but that was only very occasionally necessary — in general, despite not using mics, everyone was easy to hear and understand. That is doubly impressive given how poor the space was — it's a multi-purpose room in the Student Center, so it has hard floors and no attention to acoustics. It's really a shame that MIT doesn't have and hasn't seen fit to build more, better performance space for its theater groups. The wooing of Lady Anne scene was appropriately creepy, as was the parallel scene towards the end of the play where Richard tries to persuade the queen whose husband and sons he's killed to help him woo her daughter to be his queen, using similar logic to the first scene. Creeeeeeepy, and as surprisingly potentially effective. The whole royal family dynamics were awesome, very well-acted, and very dysfunctional. Richard was magnanimous and vengeful in equal measure. It was a relatively low-tech production — the dream sequence towards the end of the play was nicely done, using an impromptou screen on stage to project the faces of the ghosts over Richard's tossing and turning form, and lighting and incidental music were used to good effect — but the focus was clearly on the excellent acting. The director reset the play in the style of modern America, with the king as approximately the President, evoked through a portion of the set reminiscent of the Oval Office and a number of subtle visual cues on the part of the actors which I thought were nicely done. She also regendered a couple of the characters, which I barely noticed and even less minded. Resetting the play also allowed her to dispense with swords, using knives and guns as appropriate, and she and/or her fight choreographer kept the fights short, which let the production avoid the comically affected fights which plagued the Ensemble's Fall 2005 production of Macbeth. The closing fight between Richard and Richmond was I thought particularly nicely done — a very effective climax. The director also brought the deaths of the princes and Buckingham on stage, which I thought was better to build Richard's calumny than leaving them off-stage, though I wished she'd done the same for Lady Anne, who got a lot less stage time than I had expected. All told it was a really good production.

I got the sense from watching the play that it was one of Shakespeare's earlier plays, and Wikipedia agrees with me. (Despite having performed a scene from it, I hadn't actually seen the play the whole way through. I'd read bits of it, but I find Shakespeare really hard to just read — text is not the medium of expression it's intended for.) The structure of the play felt more obvious than in other Shakespeare I've seen — the explicit parallels of the two wooing scenes, a number of ongoing obsessions in Richard's remarks, and the unambiguity of his evil all pointed me towards a less mature work. Still it's an interesting play, and one of my favorites.

I miss having theater in my life. Maybe when I graduate. :-/

1: It's really odd that the thing I remember most, five years on, about that scene night — the really excellent rendition of the scene where Lady Macbeth persuades Macbeth to kill the King — is represented nowhere in that review. I wonder if I just imagined it. It was awesome — the chemistry between the two was so there, the dialogue and their presence were so right it all practically crackled.

for always roaming with a hungry heart

You may have noticed that things look a little different around here! That's because I've switched to new blogging software, which is actually now powering the whole site — ikiwiki. I've done my best to ensure that people reading this via feed aggregators will not notice any interruption in service, nor should external links stop working. Please let me know if either of these things is not true. The unholy mixture of tables and CSS which is responsible for this site's appearance will hopefully not break on anyone's browser, but I haven't exactly tested it exhaustively, so please also let me know if it does.

This will hopefully make the site easier for me to maintain going forward. (No more ghastly PHP mess! No more trying to keep page templates in sync! No more Blogger warning me they're turning off my service in a month!) The old code dates to my senior year in high school, back in the dark days of 2004, so this redesign is really long overdue.

At the very least it will let me procrastinate porting the site to modern HTML and CSS a little longer. ;>

Tables forever!

Edit: Forgot to mention that I used Bradley Wright's blogger-export Python class in my own script to get the bulk of my data out of Blogger's custom XML export format, plus a bit of elbow grease for the comments and things. It saved me a good bit of trouble.

a break-even analysis of Amazon Prime

Recently for no readily apparent reason I've been hearing a lot from my friends about Amazon Prime — I blame synchronicity and/or the increasing yuppieness of my friends. (One friend described it as one of the three big technological advance that had significantly changed his life, on par with e-book readers and smartphones. Another friend thinks that breaking down the Amazon boxes for recycling on a weekly basis may be one of his son's chores when his son gets old enough, on par with doing dishes or taking out the trash. It seems to me that Amazon Prime is basically an early version of a matter compiler.)

It's an interesting program — pay Amazon $80 a year and receive free two-day shipping on everything you buy that is sold or fulfilled by Amazon.com. This means that Marketplace purchases are out, eg. used books, as are goods for which Amazon is just providing a web storefront for another company and that other company is doing the shipping themselves rather than relying on Amazon's fulfillment system. It's fairly easy to tell what's available through Prime (there's a prominent icon), and there are a couple Prime-only search engines available. But you are limited to giving money to Amazon, basically, so if you have issues with them, you're pretty much out.

That said, I've been finding myself using Amazon more and more lately. Since I live in a dense urban area, I can do a lot of my shopping locally, but I don't have a car, so if I want to buy things in bulk because I go through them fast enough — granola bars, for example — I have to either get in on a friend's Costco run or rent a Zipcar, which is hassle and expense that usually negates the advantage of buying in bulk. The same applies to most big-box stores — Ikea, Home Depot, Staples, etc. They're all only really accessible by car. (And when I'm buying big things I don't want to lug them back by hand anyway.) It's all much easier when these things show up at my front door. So I've been using Amazon for bulk purchases — big boxes of Clif bars, which are blood sugar-support in lab and usually breakfast, other different granola bars which make a good snack, a few pounds of crystallized ginger, that kind of thing. (The Clif bars I'm actually subscribed to — Amazon has a Subscribe-and-Save program, so every month two big boxes of them show up on my doorstep, and I get a discount and free shipping in the bargain. It's separate from Amazon Prime, so Prime wouldn't give me any advantage there, but when I was buying them a box at a time as I needed them, I sure wouldn't have turned it down.) So I've been considering getting an Amazon Prime membership, and in so considering, I wondered if anyone had done an analysis on what the break-even point was. How many orders do I have to make with Amazon in order for a Prime membership to cause me to spend net less money? It wouldn't surprise me if someone inside Amazon has done this analysis — in fact I'd be surprised if Amazon hasn't — but I couldn't find one with a decent amount of Googling, so I did my own. Here's what I came up with:

The easiest situation to figure this for is the straight-up equivalence — anything after this has complicating psychological factors that are hard to quantify and account for. Amazon Prime gives you free two-day shipping on all your Amazon purchases, so if in a year you make enough purchases with Amazon on which you choose two-day shipping for which the shipping charges are in sum equal to or greater than the cost of an Amazon Prime membership, you're better off having bought the Amazon Prime membership. The shipping rate is of course going to vary depending on how bulky or heavy or fragile or hazardous the item you're buying is, so I have to calculate the rate for my "standard purchase load", but having spent some time adding and removing things from my Amazon cart last night I've figured out that my average Amazon purchase would cost me $12 to ship with two-day shipping. So divide $80 by $12 and voila, I break even after seven Amazon purchases with two-day shipping.

(A complication I didn't account for: Amazon Prime gives you free two-day shipping and your items ship as soon as they're available,, which costs more, rather than grouped into as few shipments as possible, so if you would have purchased those items with two-day shipping and ship-as-soon-as-possible then you break even even faster. Also there's no minimum order for you to get the free shipping with Amazon Prime, but I don't usually have trouble with that.) I've easily made seven purchases from Amazon in the last six months, so Prime is obviously a good deal for me! Except I almost never choose two-day shipping, save maybe for Christmas or birthday gifts or the like. Lately I seem to be choosing standard shipping, which costs about $5 for my average purchase, so I'd need to make 16 purchases in a year on which I chose standard shipping in order to break even. I placed 13 orders in 2008, 15 in 2009, and I'm on track to make at least that many this year (not counting the Clif bar subscription), so it's still a pretty good deal for me!

(A complication I didn't account for: Amazon has started occasionally giving me free standard shipping. I don't know why, there's no explanation on the page or in the item description, my order history has no record of which orders it applied to, and I haven't checked my bank statements to see if they're actually charging me for shipping, but I'm not complaining. I assume it's because I've spent enough money with Amazon that they're willing to upgrade my shipping sometimes, which led to the question of just how much money have I spent with Amazon, and would I be better off with a Prime membership?)

Except well over half of the things I buy from Amazon are things that I want but don't need right away, eg. books I'm only going to donate to my local library, and so I take the free shipping option, knowing that the variance on delivery times for that is huge. (Sometimes I get free-shipping packages within three or four days; sometimes it takes up to two weeks.) If I'm willing to take the chance of waiting two weeks, free shipping is a great deal. With Amazon Prime I'd get those things faster, for sure, and sometimes I do realize a week in that I actually wanted that thing faster than free shipping got it to me, but here we're well into wishy-washy psychological territory. Would I in retrospect have paid for faster shipping on enough orders that I would have saved opportunity cost had I had a Prime membership? That's even quantifiable, but without having journaled it throughout the year I don't think I have any reliable way of backtracking to figure it out. So it's really hard for me to say whether Amazon Prime would actually be a net win for me.

Now, for full disclosure, I have started a Prime membership, though I'm still in the one month free trial period, and I didn't include any of the purchases I made after getting the Prime membership in the above data, on the chance that getting the Prime membership has changed my purchasing patterns somehow. I don't think so, but, y'know, remove or account for as many potential sources of error as possible. I got the membership because I'm a senior at MIT, absurdly hosed, and any time or stress I can save is hugely valuable to me if I'm going to graduate with my sanity intact (heh). Now, money is also a stressor, to be sure, and I'm mostly living off savings, so I can't afford to be profligate in my spending, but I know I've been stressing about being around stores at certain times when they're open to pick up things I need, and the ability to buy them at 4 AM in my pajamas and have them show up on my front doorstep within a few days is I think going to help a lot with that. It still doesn't work for things I need to try on or see in person, but hopefully I won't need too many of those things in the next two months anyway.

hugo nominations for 2009

Here's what I'm nominating for the Hugos, in all the categories where I feel like I've read or watched enough to be even vaguely useful. (Which is surprisingly few, really, but I spent five months of the year chained to MIT.)

Best novel:

  1. Palimpsest, by Catherynne M. Valente, Bantam

Best novella:

  1. Pelago, by Judith Berman, Asimov's February 2009

Best novelette:

  1. "The Qualia Engine", by Damien Broderick, Asimov's August 2009

Best short story:

  1. "Sleepless in the House of Ye", by Ian McHugh, Asimov's July 2009
  2. "As Women Fight", by Sarah Genge, Asimov's December 2009
  3. "Mr. Penumbra's Twenty-Four Hour Book Store", by Robin Sloan, robinsloan.com
  4. "Bridesicle", by Will McIntosh, Asimov's January 2009
  5. "The Horrid Glory of Its Wings", by Elizabeth Bear, Tor.com

Best dramatic presentation, short form:

  1. "Belonging", Dollhouse season 2 episode 4
  2. "Man on the Street", Dollhouse season 1 episode 6

…and that's all I've got. So many good candidates for best short story — far more than I can actually list — and so few for anything else, and so many categories left completely empty! But no time to fix that now. Maybe next year.