A Year(ish) at the Coal Face

Reflections on working with a legacy Rails app

03 May 2014

The title of this post, to the uninitiated, is a reference to the UK television comedy The Thick of It, where a minister is coerced into committing to work for a week in a Job Centre to show his dedication to his own policies - bear with me a second.

I’ve just finished my first full-time Rails gig and besides a lot of cool JS-heavy UI features on the front-end, I also ended up doing a lot of back-end almost infrastructure-type work. This is what I mean by the ‘Coal Face’; the unglamorous, hard work that it takes some discipline (I flatter myself) to undertake. For instance, before I joined, we had no tests whatsoever - one of my biggest pieces of work was getting tests in (leaving code coverage at about 40% when I left, 50% for models, and 70-80+ for the new things I’d written, no small feat for such a large app), especially for the rather complex scheduling engine, which was bug-prone, very brittle and, terrifyingly, mostly held in a 600+ loc controller. It was something that gave me a bit of a shock as a book-taught, best practice, joined-the-party-at-Rails-3 guy; I didn’t know whether this was simply a result of not seeing why you shouldn’t have a 200 loc method in a controller, or whether that simply wasn’t a best practice well understood when this app was first written (Rails 2.0.x).

This all finally came to a head when trying to implement a glamorous Ember app for real-time copying of schedules and all sorts of other shiny. Basically the Rails app fell apart at trying to give a consistent interface, and the wheels came off quite badly. Back to the Coal Face it was then. TDD-first, all of the scenarios that were expected of the engine were written out in specs, and painfully, line-by-line the code was moved to the models. Eventually, several pieces of functionality were delegated to another model and I was finally able to implement a flashy and important feature (arbitrary times for events on each day of the week). All of this work took up over three months, which goes to show that one small decision (I suspect some years ago, a little bit of logic in the controller being amended with some extra logic that should have been refactored to the model was enough to get this snowball rolling) can lead to a huge problem down the line. There have been some great, slightly tongue-in-cheek articles on HN lately about how code becomes ‘legacy code’, but it was incredibly instructive - in fact, arguably as instructive as the actual work which I did - to see exactly how these problems can compound. More than ever, I now see the wisdom of ‘convention over configuration’, consistent APIs, good, thought-out architecture, and, as a bit of a testing enthusiast before, I’m nothing short of a testing fanatic now.

There’s a chap from Soundcloud (his name escapes me, for that I am sorry) who I used to run into at music conferences pretty often. Every time I saw him, he was threatening (planning) to write a book on how startups were essentially the same as bands. There’s something in that idea - there’s the same hero worship, the same headbutting of creatives within tribes, the same co-founders continuing for years despite hating one another, or dramatically going their separate ways.

I’d go one step further actually - I’d flip it and say that bands are actually relationships. Anyone who’s ever been in a band knows that there’s a dating phase, then a commitment (“we’re in a band, and we’re calling it xxx, but only for now…”), then a honeymoon period. You get the idea. The thing is, as soon as you see it like that, and hang around with musicians, trading stories of bands that failed to launch or collapsed dramatically (and I have the pleasure of hanging around and interviewing musicians a lot in my journalist guise) it all seems kinda obvious. So - that being the case, startups, and jobs more generally are just relationships, with the same distinct phases.

I will now arrive at the point: in looking at any job, or indeed any project you’ve been a part of, or any relationship, objectively you can see the flaws, the patterns, and whether or not it was a supportive or abusive relationship. That’s easy to see in hindsight - it’s why you don’t often keep in touch with exes - but in the moment it can be pretty hard to see. Of course, you know this, you’ve had to talk a friend through a rough breakup where they didn’t want to let go.

In being able to reflect on my last job objectively then, I’m pleased to find little to be upset about; I learned a huge amount and was given the freedom to develop and re-develop some cool (not to mention tricky) stuff. That said, it has given me a first-hand appreciation for just why a lot of things are best practice. REST APIs, for example, only become a concern when you don’t have them - want a consistent interface to hook a JS app up to? You’re flat out of luck if too much logic is in controllers or say, models need intermediary ‘build’ steps after instantiation but before persistence. Quite quickly these things get out of hand and that’s how small mistakes become a legacy code nightmare.

As a final point, I’m now driven to delve a lot deeper into architecture and in particular patterns and anti-patterns for web software, as it’s clear to me that while ‘fat models, skinny controllers’ is better than ‘logic soup in views and massive controllers’, it’s still not perfect. Moving on professionally I feel means I have to get straight in my head what a solution would be to all of these problems; refactoring into models with the help of tests is an improvement, but on a grander scale is still just a better sticking plaster, not a complete solution, and I think I’ve learned enough to recognize that.

Fork me on GitHub