Things I've Learned from my Coworkers

The job continues to go well. Yay! I've even managed to pick up a few lessons.

It's not bad code, it's just different
As someone who has been historically quick to declare code crap, it's a refreshing change of pace to pick up on the attitude that maybe this code isn't crap, maybe I just don't understand it very well yet. And I'm trying to take that to heart: there's plenty of things in the code base that aren't the way I'd have written them, but that doesn't make the way they're written any less valid.
It's okay to go home
In spite of working at a start-up, all of my coworkers are older than I am, and nearly all of them have families. That means they go home; they understand being sick and prefer you stay home and not infect everyone else; they get that sometimes you need to call a plumber and will be working from home that day.
Bring up issues, then fix them
Being a lone developer for so long, I got used to "see thing I think is problem, fix thing I think is problem". I'm still trying to get the hang of when I can just do something and when I need to discuss it with other developers first.

Of course, my coworkers aren't perfect

Sometimes they worry about micro-optimizations

Is it better to use autoloading, or explicit requires? That leads to the question of which is faster, and regrettably, I fall into the same trap and respond in kind "Well, X is faster because of Y.". The real answer, of course, is that it's a micro-optimization which is entirely irrelevant to the speed of our application1 and we should be worried about which is easier to maintain.

(NB: We've since switched entirely to autoloading for code maintenance reasons.)

Limited experience "at scale"
Nearly all the other developers worked together at a prior company building a C++ application where each installation served maybe a hundred users. Naturally, this affects their perception of how to structure a program and what things are efficient, so there's a lot of functions which do things like return a resultset instead of a data structure to avoid the extra loop. Much of the code passes around row ids, rather than objects or arrays of data, so the db gets queried for the same data a lot. (We are making progress on this front, but new features tend to take priority.)
Limited web experience
I've found and either closed, or built tools which help avoid, numerous classes of web-specific security vulnerabilities.

But overall, I have the distinct privilege of working with some intelligent people who are passionate about their work, have strong opinions formed through years of experience, who nonetheless still maintain an openness to trying new ways of doing things (and that's no platitude: I've spearheaded at least half a dozen major changes thus far2).

But then, neither am I

Have yet to fully assimilate the formatting convention
The biggest annoyance to my coworkers is probably my habit of doing
if (condition) do_thing();
rather than
if (condition) {
But it's certainly not the only formatting difference I haven't managed to avail myself of. And even without formatting differences, I tend to write code in a very different style―if you ever come across the words 'curry' or 'filter' in our codebase, there are very good odds I touched that code.
Or, really, any of the existing conventions
Lowercase file names was the convention, until I introduced a lib/ directory and started filling it with mixed-case filenames which matched the case of the class names.
Accidentally co-opted the name of the mobile API
The API used by the phones was referred to as "the mobile API", or often just "API" for short. I introduced a new convention for routing AJAX requests to controller methods, and called it the "web API", or usually just "API" for short. This caused enough confusion that the mobile API was renamed "services". I still wince a little whenever somebody says "services" because it's my fault.

Of course, liking work does have some downsides

Because work is fulfilling, it's much easier to spend time working on work, rather than taking the hit of context-switching to a side-project on the weekends. I sometimes manage to not work on weekends, but that's very different from working on something else. So the various projects I maintain, or have plans to write, make no progress.


  1. Our deployment servers have APC turned on and configured to not even bother checking the filesystem for updates. That's a bigger performance win than any quibbling over autoloading-vs-require_once we could do, and even that is a pretty negligible difference.
  2. Our most recent hire has begun to spearheading a few, as well. Hooray for new hires not yet being numb to the pain points!

Don't you just love it when people move to a new blog? I'd 301 redirect you if I could, but since I can't you'll have to click through to read comment count unavailable comments or leave your own.

FTP: Apparently, It's Not Dead Yet

(Why yes, I am still alive. Just very bad at writing lately. :'()

Much to my surprise, the FTP protocol has managed to not die yet, and I recently received a patch from Rafael Jesús Alcántara Pérez to get cl-ftp running on ABCL.

So thanks to Rafael's patch, I've finally taken the time to convert cl-ftp from darcs to git, and tossed it up on github like all the cool kids are doing these days. Supposedly it even now runs on ABCL.


Don't you just love it when people move to a new blog? I'd 301 redirect you if I could, but since I can't you'll have to click through to read comment count unavailable comments or leave your own.

A Minor burgled-batteries Update

Or: burgled-batteries isn't dead or forgotten, I've just been busy.

One of the downsides of liberally relying on CFFI internals is that changes to those internals can easily result in breakage, and some of the cffi-libffi changes did so. It took me entirely too long to get around to it, but I've finally updated burgled-batteries so it will actually run against CFFI in Quicklisp. Actually moving to the new style of (:struct *) and (:pointer (:struct *)) identifiers remains to be done, so there are a fair number of style warnings to ignore, but at least it will run.

I've also moved burgled-batteries to git. The official repo URL has not changed (it remains, however there is also a github mirror, which may be moderately more useful if you'd like to browse the source or changes without cloning the repo, as it will undoubtedly be a while before I've got time to set up gitweb on my own host and get it functioning seamlessly in parallel with darcsweb.

New year, new job, new blog. I'd 301 redirect you if I could, but since I can't you'll have to click through to read comment count unavailable comments or leave your own.

Making a Bootable USB Drive for Linux

Conveniently timed to my previous entry I recently upgraded my laptop to Debian Wheezy. This involved redoing my backup boot drive to contain bootloader updates, so I can detail the process I used.

Partition the USB drive

Use whatever partition manager you're comfortable with. cfdisk, fdisk, gparted, whatever.

# cfdisk /dev/sdb

If you want to use the USB stick on Windows normally, note that Windows will only see the first partition of a thumbdrive. This is great for hiding the fact it's a bootable drive!

# fdisk -lu /dev/sdb
Sector size (logical/physical): 512 bytes / 512 bytes
/dev/sdb18064142598157125876bW95 FAT32

Don't start the first partition at the very beginning. Here I've got it started about 4k in. This gap is important: grub will install itself into the gap--if there isn't enough room, grub won't install.

You'll also notice that I've allocated 512MB to what will become /boot (sdb2). This is serious overkill, but also means I don't have to be particularly cautious about uninstalling old kernel versions to avoid running out of room.

Format the Partitions

Naturally, we should format these partitions:

# mkfs -t vfat /dev/sdb1
# mkfs -t ext3 /dev/sdb2

Install grub

Then mount our soon-to-be /boot drive into /boot (if you're familiar with grub-install, you can mount it elsewhere):

# mount /dev/sdb2 /boot

And install grub:

# grub-install /dev/sdb

Naturally, your next step should be to test that it boots. And maybe even test that it appears as a normal thumbdrive on a Windows computer.

When Doing a Fresh Install

NB: This is from-memory. I have not done this recently.

If you're doing a fresh install, partition the USB drive from another computer. Make sure the thumbdrive is plugged in during the install process, and when configuring drive partitions and directory locations, simply select /dev/sdb2 (or whichever is appropriate for the USB drive's second partition) as the device on to which to put /boot.

New year, new job, new blog. I'd 301 redirect you if I could, but since I can't you'll have to click through to read comment count unavailable comments or leave your own.

Upgrading the Linux Kernel when Using a USB Boot Disk

In order to protect any sensitive data on my work laptop, I use full-drive encryption. To aid recovery in case of theft, it normally boots to a honeypot installation of Windows with Prey installed. To boot into Linux, one must use a USB boot disk[1] which contains the contents of /boot.

Once in a while, it is necessary to upgrade the kernel. I don't do this very often, so it seems like the sort of process which should be documented.

  1. Mount /boot read-write: `mount -o rw /boot`
    I generally have /boot mounted read-only, in part because I don't usually have the thumbdrive plugged in (I don't boot very often, after all), and to ensure I don't accidentally make changes to it without being prepared to undergo this full process.
  2. Install kernel updates: `sudo aptitude full-upgrade`
  3. Reboot. Pray it works.
  4. Insert backup boot disk. (Just in case the thumbdrive on my keychain goes bad or gets lost.)
  5. Copy files from the updated boot disk to the backup: `rsync -av /boot /media/usb2`
  6. Remove the original boot disk. This will help prevent unfortunate mistakes.
  7. Alter grub.cfg of backup boot disk to refer to the proper UUID: `sudo sed -i s/$UUID_OF_BOOT/$UUID_OF_BACKUP/ grub/grub.cfg`
    `blkid` comes in handy for finding the relevant UUIDs.
  8. Reboot. Pray it works.

Assuming both boot disks successfully boot the machine with the updated kernel, congratulations! You have successfully updated the kernel!

[1] It's not quite as much a waste of a thumbdrive as you might think. The sticks have a FAT partition of ~90% or so of the advertised capacity, so they can still be used to transfer files between computers or for data storage.

New year, new job, new blog. I'd 301 redirect you if I could, but since I can't you'll have to click through to read comment count unavailable comments or leave your own.

A Public Service Announcement About rm and tildes

If you happen to be lax in upgrading software, you might have an older version of magit where if M-x magit-status is allowed to initialize a git repository where none was before, it has a tendency to create said repository in the directory '$HOME/repo/~/repo'[1].

If this happens, and one wishes to remove that annoying and non-useful '~' directory, do not, I repeat, do not run the command:

rm -r ~

That is bad. Remember shell expansion! You need to quote the tilde:

rm -r '~'

But also note that even the latter should not be done within eshell, as it seems to be intent on expanding the tilde anyway. Use a real shell.

Also, always do `ls $dir` before you do `rm $dir`, just to double-check what you're deleting. Even if you're sure, check anyway.

Because otherwise, you might accidentally delete your home directory.

On the bright side, I can now confirm my backups work.

[1] see bug 383

New year, new job, new blog. I'd 301 redirect you if I could, but since I can't you'll have to click through to read comment count unavailable comments or leave your own.

Live from the DMV! (This Program was Recorded Earlier)

I recently renewed my driver's license. There were a few changes from the last time I did it, and they aren't really for the better.

First, they now require removal of glasses, hats, and human expression from your picture, to aid the facial recognition software used. While I offered a mild objection to removing my glasses and having a blank expression, it regrettably did not occur to me to state my objection to the usage of facial recognition software at all until after I was done.

Wish I had, though. For several reason: first, because I do object to the government using facial recognition software on my pictures, or really storing any biometric data on me at all; and second because I want to know if there's a process to handle such objections. Obviously the DMV is not the place to effect change, but knowing if there are procedures in place for objections would at least give me a place to start.

Well, I had always planned on moving out of state eventually, anyway. I guess I'll add "DMV uses facial recognition software" to the list of reasons to leave, and the list of things to check for any place I might otherwise be inclined to move to.

Second, they no longer provide your actual license. Instead, they provide a temporary paper license and mail the real one. So now, instead of potentially being lifted by someone showing their face who would have to look similar enough to fool the person giving it to you, your license can be lifted anonymously by someone within the postal system, or anyone with access to your mailbox. This is apparently so they can take time to more carefully verify your identity to prevent identity theft, so the fact it makes licenses easier to steal is hilarious.

Third, unless you specifically object, signing up for a license now automatically enrolls you into the selective service database if you're eligible. While I object to the very existence of that database, auto-enrollment makes vastly more sense than the manual enrollment that was supposedly mandated when I was within the eligible age range.

It gets harder and harder to keep a low data profile. Le sigh.

New year, new job, new blog. I'd 301 redirect you if I could, but since I can't you'll have to click through to read comment count unavailable comments or leave your own.

Getting a Job, a Retrospective

Being largely burnt out on the skin cream business, I decided near the beginning of 2012 it was time for a change of pace and decided to look for a job.

Step one: Leave the house. Achievement unlocked!

What I heard from people in these groups, and from various places on the Internet, is that now is a great time to be a programmer. Jobs are easy to come by, they said! The pay is great, they said!

As it turns out, there are a few things that make it somewhat more difficult for me to find work: first, is location. This town, which I would love to leave but not quite yet, thanks to the banks and insurance industry which dominate it, is a Java and .NET shop through and through, and they demand experience in those languages. Also, banks and insurance companies are very stodgy, and maintain a considerably stricter dress code than I can bring myself to adhere to. So for multiple reasons, this town's two primary industries are almost entirely out.

So I'm largely left looking at the PHP, Python, and Ruby shops. PHP because however much I hate it I have experience in it, and Python and Ruby because places which use Python and Ruby are enlightened enough to realize programmers can learn new programming languages. That's a relatively small number of places in this town, but at least it's non-zero.

Attending meetings is fun, but I'm terrible at networking (it requires talking, which I am wont not to do), so wasn't particularly helpful in terms of finding work. But a conveniently-time presentation by one of the CIALUG members on how he got a $20k/year pay hike with his new job proved interesting.

First was the suggestion that, contrary to the opining on Hacker News, recruiters were not all terrible people, and a recommendation of the people at Palmer Group.

First sign of trouble: their baraccuda was doing deep packet inspection and rejected my e-mails on the basis of my home IP not being authorized to act as an SMTP server—that it isn't being used as one is, apparently, entirely irrelevant. Had to craft a special rule to remove the Received: header before I could relay mail to them. (Alas, postmaster@ was completely non-responsive.)

Once I got through, my initial contact was quite nice. Then I got handed off to a fellow who clearly was not interested. But, with some encouraging from my initial contact, I met with him anyway and ... it did not go well. We parted ways mutually unimpressed, and I never heard from him again.

So much for that recruiting agency.

Second was the presenter's resume (alas, I cannot now find it), which I thought was pretty cool and modeled mine after. Which is a pretty high compliment, actually: I've looked at resume examples online, and they all result in pretty much the same reaction: "This is boring and stupid. Why the hell would anyone read this?". That abundance of awful resumes kept me from even trying to make my own for years, and it wasn't until I saw the presenter's that I realized they could be not-terrible.

Unfortunately for my desire for privacy, my resume isn't terribly impressive if restricted solely to work-related items, so I had to pad it out with a little open-source work. I'd have vastly prefered to keep those lives separate (hence my not linking to a copy of my resume, though I've actually mentioned most of the things on it here), but felt I needed the extra oomph. I expect my resume post-new-job to better hold up without violating that separation.

There's not a lot of privacy in job hunting, actually. People want things like your name. Dice has the audacity to require a phone number and street address. I'm an introverted nerd: I don't take phone calls, and I sure as heck don't want mail. Fortunately, "000-000-0000" and "Undisclosed" are considered valid inputs for those fields.

Anyway, privacy issues aside, and resume in hand, I start looking for work. So I peruse Craiglist want ads, and post my resume on Dice (the trick, of course, is that unlike last time, I'd actually like to end up with a job), and browse job sites.

Great googly moogly are help wanted ads ever awful! I can't even read more than a few a week, they're just so terrible. They either leave me wondering what the job even is, or they leave me wondering why anybody would want it.

So I send my resume out to a few places. Nobody bites. One actually sent me a "hey, thanks for sending us your resume", but otherwise I get nothing. I periodically adjust my info on Dice, and see from my server logs that some of the links I helpfully included in my resume are being clicked on.

Dice nets me two contacts at this point. A recruiter and an interview request.

The company requesting an interview doesn't sound all that interesting—just basic PHP site development—but I figure I could use the practice and go. And I was right about needing the practice, because I bombed the interview, hard. Couldn't even accurately define MVC. Naturally, they passed.

The recruiter was a nice lady who tried to get me a job at WebFilings as a "Scrum Master", whatever that is. I wasn't terribly thrilled about the commute, but she made a convincing argument for giving them a try. But, after a month or two of her contacts being out of the office, they eventually decided to fill the position from within.

Visibility supposedly helps, so I gave my presentation at Pyowa. That netted me an interview—and their head guy from Chicago seemed to really like me—, but for whatever reason, they too passed. Which made me sad, because I really liked them and would likely have accepted in spite of the non-stellar pay because the work that was 3-6 months out (converting their monolithic architecture to a service-oriented one) sounded really fun.

Somewhere in here I also send my resume to a company which hosted one of the CIALUG meetings, because they said they were looking for people. They do a little googling, end up on my father's personal site, and peruse the pictures page, presumably trying to remember who I was (I'm not recognizably there, but they don't know that) and possibly confusing me for my dad. I get a polite brush-off.

Monster is mentioned at a Pyowa meeting. I sign up and post my resume. And, while it results in vastly more contacts than Dice, they're all offers to become an insurance salesman. And they have unsubscribe links, which should give you and idea of how personal they are.

Suddenly, another recruiter contacts me through Dice. She loves my resume, then proceeds to ask questions which can largely be answered by reading it or my profile. I grate my teeth and point this out as politely as I can while I answer the questions. During the phone conversation, "How much do you make now?" "I'd rather not say." "Well I understand and maybe you'll tell me later." (paraphrased), which I think is a little odd (the only thing about money anybody else has asked is how much I'd like to get) but don't worry too much about. I get asked to fill out a form online to get into their system. This makes me not happy, but people aren't exactly beating down my door with money, so I go for it. And their form wants information I can't give it (What month did I start? It was nine years ago, I don't remember!), and information I won't give it (current pay). Not to be deterred, I e-mail the recruiter asking for suggestions. That went something like this:

"You should tell us your current salary."
"No. Stop asking or we're done here."
"Okay, bye."

The exchange was somewhat more politely verbose, of course, but that's the gist of it.

And then I pretty much forgot about Dice until I get an interview request from a little startup which enticed me with things like private offices and no dress code. So I do the interview, and I have no idea how to judge it. No real technical questions, no coding on the whiteboard, just "tell me about yourself / your work" (after a long pause: "I don't normally talk about myself, help me out here and ask me some questions!"), and chumming with a few of the existing coders (during which I did very little of the talking).

But they made an offer, and it wasn't half bad in terms of pay, either. They agreed to a significant narrowing of the scope of their non-compete—which was originally so vague you could construe it as prohibiting clipping coupons from the newspaper—, and I accepted.

So new job for Pixie! It's not perfect—the commute is longer than I'd like (about 20 minutes), the company-provided computers are laptops of all things, and they use Google apps1—, but it should be interesting.

Here's some things I learned during this experience:

  • Recruiters "love my resume", but if I could just go ahead and make it completely boring that'd be great.
  • You can e-mail a link to your resume, using the e-mail as a cover letter. Links to resumes do, in fact, get clicked. (Handy for tracking!)
  • Links on resumes also get clicked. (Also handy for tracking.)
  • Visibility is a really good way to get companies interested. It's also the most work.
  • Monster may get you more contacts faster, but Dice will actually get relevant contacts.
  • Like dating, you get much better response rates from those who come to you.
  • Wearing a t-shirt and shorts to an interview will not prevent you from getting an offer.
  • Every interviewer will bring up Lisp if it's on the resume.
  • Questions about the technology stack and development process tend to elicit a response of "that's a good question".

And now, some months after accepting a position and working for a while (this entry was in my drafts folder so long I forgot about it!), I can add a few things to the list:

  • Somewhere along the line, my Dice-tagged e-mail address was acquired by spammers. Ugh.
  • While I was worried having coworkers would reveal I'm a terrible programmer, turns out I'm not half-bad. (Assuming my measurements are correct, my net effect on our primary repository has been roughly -74,000 lines, in spite of numerous feature expansions and improvements.)
  • Working on a laptop isn't so bad. My only real complaint is that they cheaped out on the screen, so it's got even fewer pixels than the already-pathetic "full HD" so many laptops tout as if it were decent.
  • Working 40-50 hours a week kills nearly all of my free time. I have yet to figure out how other people manage full-time work plus side projects.
  • Having an office is awesome. How anybody gets work done without the ability to make quiet something which was noisy is beyond me.
  • I really like the new job. Yay!

1 Good T.B.Lee, people use this crap? None of it works with JavaScript disabled, and with JavaScript enabled it brings my computer to a griding halt. And then some of it still doesn't even work (go go Groups infinite redirect!). Fortunately, I've managed to almost entirely avoid it.

New year, new job, new blog. I'd 301 redirect you if I could, but since I can't you'll have to click through to read the comment count unavailable comments or leave your own.

The Reunion

I wouldn't have expected it ten years ago, but I've found myself curious lately1 where my high school peers ended up and if I was the biggest loser among the class2, so I made one of my rare trips outside the house to attend the ten-year high school reunion.

Regrettably, my camera is currently in Chicago undergoing repairs, so I was unable to document the event with pictures. From what I saw of picture-taking, there likely won't be many pictures for posterity. That's unfortunate, but we can at least document the event in words, so here goes:

Men of the 2002 graduating class, we have gotten fat! Some of the women have too, of course, but not nearly in the staggering proportions of us men: by rough estimates, I would say 90% of us men have grown in girth, to maybe 50% of the women.

Well, at least we're well-fed.

Facial hair is surprisingly popular for the men. I was additionally surprised at how many people remarked on my beard; apparently people do not recall that I was much too lazy to shave in high school and generally had a beard back then as well.

I was quite pleased to see many of the women wearing comfortable shoes, rather than high-heels. Still, there was no shortage of women wearing shoes which essentially forced them to spend the evening on their tippy-toes. 8+-inch heels are crazy, ladies!

I felt about as short as I did in high school, though a number of people I remember being taller than I was are now much closer to eye level. Either I've gotten taller, or some of you have gotten shorter.

Facebook is not only the most popular method of keeping in touch, as far as I can tell it's the only method. There was not one "Hey, what's your e-mail?", not one "Hey, what's your phone number?", not one "Hey, what's your blog?", not even an "Are you on Google Plus?"—just "Are you on Facebook?".

No. No I am not.

A special note to their husbands: You bastards! You decimated the reunion hookup market!

Much to my surprise, a number of the ladies who were in my social circle are married and have kids now. Bucking both the trends of highly intelligent women waiting until mid-thirties to have children and of women failing to lose the baby fat, because they are lookin' fiiiiiiine. *ahem*

More people than I expected are still in town. I thought I was the only one! You'd think this town would be small enough I'd have run in to one of them at some point, but apparently not. (Though that may also be explained by my disinclination to leave the house.)

Many people are still in the midwest, even if not in Iowa. Omaha, Kansas City, South Dakota, and Chicago were all represented.

IT was well-represented as a professional group, though there's undoubtedly some bias towards it given my high-school peers. Lawyers were also quite well-represented.

Nobody advertised what they were paid, myself included, so I do not know how we all rank in terms of wealth, but I think I can safely surmise that those of us who showed up are doing okay. Not spectacular, but well enough.

On a more personal level (and boy I really hope I'm getting the names right, because I'm trying dagnabbit):

Amy A. said hi to me! Okay, that sounds a little weird when I say it like that, but we never hung out back then, and I may have had a crush on her at one point. She's a sexy lawyer now, which would have been nice to know a few weeks ago when negotiating the non-compete for my new job, but is nonetheless something to keep in mind for the future.

Chris K. still tells the best stories, which will serve him well in the criminal justice system.

Tori L. is a teacher now, and mad props to her for it. As someone who sometimes thinks about trying his hand at teaching, but knows he'd be terrible, I've got a lot of respect for those who can actually do it.

Congrats to Josh C. on surviving so many years of retail. You're a better man than me, my friend. Also congrats on getting out of it! :)

Sri, me and Laura both miss you and hope you're doing well.

A big congratulations to Lauren H. for sobering up during the past ten years. That kind of successful life change is truly inspirational.

Andrew W., whom I did not get a chance to talk to, was looking quite dapper. Way to show up the rest of us men and get more handsome, rather than more rotund, Andrew!

A big Ha ha, suckers! Congratulations! to those of you who have chosen to join the ranks of parenthood, as well as congrats to those of you who are now permanently off the dating market. There are more of you in both categories than I really expected, but I'm happy for you all the same.

If you weren't there, you were missed, and you should come next time! I didn't even get an invite and still managed to show up, so the rest of you have no excuse. :P

And, of course, a big thanks to Pete L. for arranging the whole affair. He got a 10+% turnout for our class, which I thought was pretty darn impressive, and could not have picked a nicer night for it. Hopefully next time I'll be included in the list of invitees. ;)

P.S.: If you're wondering what I've been up to, it amounts to "not much" punctuated by a few interesting excursions. Also, if you'd like my e-mail address, just ask Pete; he's got it.

  1. curious I found out about the reunion on Friday, because I googled for it. Fortuitous timing!
  2. loser Yes. Yes I am.

Introducing clavatar

Earlier this week I discovered Libravatar, a federated Gravatar clone. "Neat.", I said to myself in a very Bender-like tone.

Then I found myself in need of a GitHub account and repo to play with BountyOSS's progressing GitHub integration. A test repo would be boring, so I thought to myself "Hey, this federated avatar stuff is pretty neato, I'll do a repo involving that.". So I did.

And the result is clavatar.

If you're building some sort of site with users, and you want to add avatar support without having to host all those pesky images yourself, you can use clavatar to find an appropriate avatar URL for a given e-mail address or OpenID/URL. It supports libravatar-style federated avatars, Libravatar-as-a-service, Gravatar, and even Unicornify.

(clavatar:get-avatar-url "" :size 120)
; => #<URI ...>
(clavatar:get-avatar-url "")
; => #<URI ...>

Most of the dependencies are readily available through Quicklisp, but you will need a more recent copy of iolib. And I do mean recent—the patch required for clavatar to work landed earlier today.