As lisp programmers have know for a long time it is better to have a smallish number of ubiquitous data types and a large number of small functions that work on them, than to have a large number of data types and a small number of functions that work on them.Joe Armstrong
Lessons In Software Design
I originally wrote Gravtastic, a library for using the Gravatar API, to learn a bit about Ruby and how to publish gems. It was a fun project which I did during my exams in 2007. The project has a few people watching it on Github so it is the best public representation of my abilities (other than my proposed enhancement to Rails). I looked back on it the other day and it struck me just how much I had learnt in the last few years. None of my code was bad, but I’ve been living and breathing binary since late 2008 and my opinion about everything has changed. Hang on, who am I trying to protect? The code was bad and here is what I learnt from re-writing it.
Lesson 1: Results
Firstly, the spec suite was massive. It was disgusting to work with. Sitting down to some refactoring I made one little change and three tests broke (all for unrelated features). The library still functioned correctly, but the specs were too closely coupled to its internals. To fix this, I went through and made specs that only tested the result, not the implementation. To help choose what features to cover with the specs, I singled out methods that were more than 4 lines long. Anything less than that, really, can probably be tested by inspection. In an ideal world, your software should be so simple that you know it works just by looking at it.
Despite the current Cucumber craze, this lesson shouldn’t be confused with writing integration tests: it specifically applies to how you write your unit tests. Each method I was testing was essentially mocking out the execution of the rest of the library. Here are some particularly bad examples:
it "changes .gravatar_source" do
lambda {
@klass.is_gravtastic :with => :other_method
}.should change(@klass, :gravatar_source)
end
it "returns the value of @gravatar_defaults" do
@klass.instance_variable_set('@gravatar_defaults', :foo)
@klass.gravatar_source.should == :foo
end
Theoretically doing this meant that one method could be tested in isolation without anything else working. I mean, that’s how tests should be, right? No. In reality, this just resulted in a big mess of interweaving dependencies. There were originally 34 specs and I ended reducing them down to 10, the core functionality.
it "source is :email" do
@g.gravatar_source.should == :email
end
it "options are { ... }" do
@g.gravatar_defaults.should == { ... }
end
It was actually better just to ignore the perfectness of the tests and go with testing the outcomes that I cared about. This process had the added bonus of also making the specs a readable source of documentation.
Lesson 2: Power
The code had prided itself on being strict: every option passed to the #gravatar_url method was checked and any invalid keys thrown out. This, however is the wrong way to approach software. If you are designing a system to be used by others, it needs to be as open as possible.
Let’s say, for example, that Gravatar brings out some new feature which is activated by the parameter xtra=extreme, so a developer would call it using gravatar_url(:xtra => 'extreme'). Before the Great Refactoring, the library would just filter the xtra parameter because it wasn’t defined in the list of valid parameters. That would mean that every time Gravatar released an update I’d be there, playing catchup. Fixing this was easy: I just don’t give a shit anymore. Users can pass whatever parameters they want. If the user passes an argument which I know a shortcut for (like r for rating) then great, it’ll use that.
I know there will be the people who think “what about developers who don’t test”? Fuck them. If they are not testing the code they write and don’t pick up on a poorly passed parameter, then their app should blow up. I’m not going to sacrifice power and flexibility to fix the mistakes of a minority. I guess this is why I prefer dynamic languages.
Lesson 3: Marketing
As I mentioned before, the last thing I want to be doing is maintaining software like Gravtastic and supporting its users. Yeah, I’m lazy. I spend all day surfing StackOverflow. Until, that is, when I saw a question from somebody who couldn’t use Gravtastic because the README was confusing. I love the ego trip of somebody discussing my library, however they were discussing how they couldn’t use it. Part of me says “screw them, if they can’t figure out the README, then they probably shouldn’t be using the software”. At the same time, I’d like to make software that will actually be used (I don’t want to be absolutist). That’s the reason I released it in the first place and the whole point of open source software. So I decided to help.

When I looked at it, the README was atrocious. I’m the only person who could have understood it. The main problem was that it wasn’t targeted at the correct audience. In the end, I spent more time rewriting the damned README than coding. Version 2.1 of Gravtastic is more an update in it’s marketing than anything else.
Not having practised writing in years I found it very fucking hard. Yes, I’m an “arts” student who has to write essays on things like Tocqué’s interpretation of Maria Leszczyńska or the Japanese avante-garde in the 1920’s and 30’s, but that is hardly writing to entertain someone. If you find shitty painters and pretentious sculptures interesting then you probably won’t understand what I mean by “entertainment”. Most users don’t know what they want, let alone know that they want your product. Getting someone to think that what you offer is fun is the easiest way to get them to want it. And that’s why working very hard on writing good READMEs is the easiest way to get people to like your software.
Of course, the best way of getting people to appreciate whatever you do is by doing a good job. It’s a shame I’m not a good programmer, because then that would be easy. I constantly have to force myself to reflect on what I’ve done wrong. It’s never pretty, but neither is your Mum.
The Third 500
When I used to row in high school, we always talked about the dreaded “third 500”. In a normal 2 km race, we usually split our race plan into 4 parts, each 500m long. When the calmness of the water was broken by the starting gun, our brains got loaded with so much nervous adrenaline that nobody really remembered the first 500m. We would then level out to a comfortable pace in the second section, slowly regaining our composure. For the last 500m we all wanted to die. Hearing the crowd and feeling the pain, we’d fucking hack on the oar until collapsing at the end.

But those weren’t the hardest bit of the race. That was always the third 500. By then, the lactic acid had truly set in and your arms and legs are on fire. Most good crews make their move then, because this is a time when they can be psychologically stronger than everybody else. Rowing was not so much about being strong and fit (of which I was neither), it was about overcoming every instinct telling you to stop tugging on that oar. And the third 500 was the killer.
Software development is much the same. Often the first half of a project will be filled with excitement and interesting problems, and the last bit, actually shipping a polished product, is fun. It’s that third quarter, where the team gets tired and the tough bugs lie, which can make or break the race.
Metalpoint
A tool to help draw and compose vector images in SVG and VML.

Think Illustrator or Inkscape except that it’s purely in the brower. At the moment you can only edit points and move shapes around, but that’s fucking cool in itself. The technology is based on Dmitry’s Raphaël, so it works in all major browsers. My longer term goals (subject to your interest) are:
- Animation. It’ll be really easy doing frame based animation but I want to get the actual editing a little usable first.
- Host it. Perhaps have accounts for save/export features, not sure yet.
- Get the UI working well. This may mean moving to canvas for speed, but I’m going to have to go to HTML5 anyway. This will probably be a bitch.
At the moment there is a small Sinatra app running the code, but all it is doing is processing HAML. There is, however, a static demo in public/demo.html. You can check out the source on GitHub.