The Second Wave

Lifehacker is one of my favorite blogs. I hadn’t thought to submit a link to GuitarCardio.com to them, mainly because GC seemed to me to have a niche appeal, rather than being the sort of general-interest productivity tool that LH usually features.

So imagine my surprise when I saw GuitarCardio turn up on Lifehacker’s RSS feed!

Thanks to the Lifehacker crew for thinking enough of the site to post about it.

And I’ll tell you what, I can’t WAIT to log into Google Analytics tomorrow.

Lessons from an Unintentional Launch

As I mentioned previously in this space, I’ve written a web app called GuitarCardio.com. Of course, posting about it here informs nobody but a few family and friends, and then only a few days later when they get around to checking the site. Likewise with my Twitter feed (which as an even more circumscribed set of people who care), Facebook, etc.

I also post to a few guitar-related blogs and fora, and I got a few hits from that. It’s not lots of traffic, but the people who came were at least interested in the topic.

The other night night, on a lark, I put GuitarCardio on StumbleUpon, which is a neat little tool for finding new stuff on the web. Within hours, I had over 5,000 new visitors. In the past 48 hours, it became over 12,000 new visitors, many of whom were staying at the site. GC peaked at #2 on the del.icio.us popular links, and made the front page of popurls. People actually gave pleasant, useful comments on the blog, and I got linked on Twitter and on multiple blogs.

I’m not so much bragging about any of this, but more expressing how agog I am at the whole notion. It had not occurred to me that any of that stuff might happen.

The even better news is that the site stayed hyper-responsive (within the limits of a good shared host) through the whole traffic wave. A few 500 errors or “sorry, my database is bogged” messages, and you’ve dug a pit of negative goodwill from which your site might never emerge.

So, lessons learned:

  • The site stayed responsive in part because currently there is no database component to the site (though this will change soon). Response codes for every one of the tens of thousands of requests over the past 48 hours have been either 200 or 302 - no 500’s, which is the bane of Rails apps on shared hosts.
  • I host no graphics on the page, which I think also helped performance. It is possible to make an eye-catching design with just HTML and CSS.
  • If you’re going to use a service like StumbleUpon, be ready. If my site weren’t able to handle the traffic, I wouldn’t have been able to do anything about it from work yesterday morning. I kind of lucked out there, due to my minimalist design decisions.
  • Services like StumbleUpon can work for you, if you’ve made something people actually want.

All the activity was really a surprise to me, as this is the first time I’ve put something (of my own, anyway) on the web that anyone I don’t know was actually interested in. (This is no great surprise - my interests and priorities intersect with those of the general population only rarely.) So thanks to all those who did care enough to say something nice about GuitarCardio - who voted it up on StumbleUpon, and who tweeted, blogged, and bookmarked it.

Now, I need to digest some of the great feedback I’ve gotten on the GuitarCardio blog, pore over the Google Analytics data, see how my ads performed, &c.

And then, I’ll be making the site even better. The GC blog will cover the features I add and when I’ll be unveiling them, and I’ll be posting about technical lessons learned here.

w00t!

How Many Pushups Was That?

Here’s something for your pecs: hundredpushups.com. This site offers a six-week program that claims (plausibly, I’d say) to be able to get you from your current fitness level to the ability to do 100 pushups in six weeks. I started a little over a week ago, and the workouts seem well-calibrated, because I sometimes struggle to get to the end, but I can make it. At the beginning, I was able to do 16 pushups at a go. There’s another test at the end of this week, and I’ll be interested to see how much progress I’ve made.

Anyway, if you’re looking for something to shake up your exercise routine, give it a shot.

Guitars and Software

My guitar practice sessions were getting a little stale, so I did what any serious geek would do - I wrote a tool to generate random exercises. Enough guitar-playing friends thought that sounded like a good idea that I put it up at GuitarCardio.com.

Share and enjoy.

Painful Ruby Inheritance Quirk

Let’s say you have a class Foo:

class Foo
  THE_CONST = 'parent_const'

  def get_val
    'parent_val'
  end

  def show_const
    puts THE_CONST
  end

  def show_val
    puts get_val
  end
end

Further, let’s say you have a class Bar, derived from Foo, that redefines a couple of things:

class Bar < Foo
  THE_CONST = 'child_const'

  def get_val
    'child_val'
  end
end

It seems kind of obvious that:

f = Foo.new
f.show_const  # => parent_const
f.show_val    # => parent_val

But would you have guessed that:

b = Bar.new
b.show_const  # => parent_const WTF!?!?!
b.show_val    # => child_val

This caused me no end of headaches during a weekend bout of refactoring. Pushing default constants up to the parent class completely hosed me up in those child classes that tried to override them. Overriding dumb getter methods that just return constants, though, works fine.

I’m sure there’s some computer-sciencey reason for this that Matz could explain to me, but I had really expected the every-call-is-a-message nature of Ruby to handle those two cases more consistently.

Migrations for Java

One of the coolest things about Rails is Migrations - the database-agnostic framework for building and versioning your database. A conversation at work today spawned a bit of googling which led me to a nice-looking Java equivalent: Migrate4j.

Share and enjoy.

How are sitcoms like gin?

…besides the fact that they both give me headaches?

Clay Shirky may have succeeded in drawing a very bright line between the people who Get It and the people who don’t in the post-Internet media age. (Hint: Most television producers are on one side of the line; most four-year-olds are on the other.) This was the most fascinating goddamn thing I’ve read in 2008, and I am set on buying his new book.

TDD and Proliferation of Edge Cases

This gets a little into the psychology of programming, at least as it applies to me.

Here’s why I’m a fan of Test Driven Development: When I’m adding a new feature - especially a new decision branch - and I’m not doing TDD, I will often only test the “happy path”. That is to say, I check what happens with the expected/normal inputs, and rationalize to myself that the change is small, and the likely error conditions are already handled. (Yes, I know. But if you’re reading this, chances are that you do it to.)

In contrast, when I’m doing TDD, I tend to triangulate compulsively, check boundary conditions, and generally dream up piles of test cases that would never come up if I were doing code-then-test rather than test-then-code. I suspect it has to do with the fact that writing an automated test at the beginning is far cheaper than spending my time clicking through every possible bad input in my UI, to say nothing of manually mocking up all the possible defects in a GET or POST request. I even find it kind of fun to spend a few minutes thinking up new edge cases for my code to handle gracefully.

And when I’m done, that code never gets deployed in a broken state again - at least for the paths I’ve tested.

As an example, consider putting your site through an invitation-only beta period. Perhaps you’re using something like Restful Authentication or some other prepackaged user signup & login code, and you have to add on the invitation validation process as a bag on the side. (In fact, you want to implement invitations as a separate model and code path so that you can easily cut it out later when the site opens to the public.) So you throw some extra code into the signup process to check a submitted invitation code, boot the user out if the code is invalid or used, and mark it as used if the signup is successful.

What if the signup is not successful, because the user put in a mismatched password and password confirmation? Does the invitation code get marked as used anyway, thus booting the user out and confusing him when he submits the form a second time with corrected input? That’s the kind of path that I often wouldn’t (and I’ll admit here: didn’t) think to test manually if I’m just coding away, but would take me 30 seconds to code a test case for when I’m working test-driven.

And that’s why I’m going to try to stay more disciplined about test-driving my development.

Sitealizer Issues

I had recommended Sitealizer (a Rails plugin) to a friend for monitoring stats on his website. Normally, I consider Sitealizer to be a pretty slick package - it has everything a smaller site needs (uniques, referrers, search terms, breakout by browser, etc.) and not a lot of cruft.

The downside: It appears that under certain conditions - like if you’ve used the standard deprec deploy (at least using the instructions at Slicehost), where Mongrel serves the app and Apache talks to the outside world - Sitealizer records all incoming IP addresses as 127.0.0.1. Not good.

And when the choice comes down to debugging the interaction of someone else’s code with arcane configuration issues or just going with Google Analytics? Sorry, Sitealizer..

New Iteration

So, it’s happened again - as with any of my interests, this blog has been through a fallow period and is back again, different, changed according to my interests and inclinations as they exist today.

If you’ve been a reader of this blog in the past, expect less personal material. If you’re here for the first time, expect lots of rumination about the craft of software development, nuts-and-bolts material on Ruby on Rails and Java, thoughts on personal productivity, links that amuse/interest me, and the rare rant.

Cheers.