Realigning the Azimuth

The (Library) Upgrade Dilemma

The idea of staying up to date with your platform is one which seems to gather its controvery for so many reasons.

It sounds reasonable – lock your application against stable versions of your platform & support libraries to ensure nothing breaks over time. Whilst it’s perfectly valid to support this during production, I’m not sure it’s a good idea when you’re in the middle of doing maintenence work on a project.

I’m not saying that you should rush a deployment just because the foobar library went up from 1.0.1 to 1.0.2. Certainly not – that’s a dangerous situation. But if you’re in the middle of working on a release which is going to include some new functionality, I think it’s another story.

I’ve actually ran into the consequences of not doing this myself rather recently. With Eventbook, I’d not bothered to upgrade the version of the Facebook Connect library until rather recently. Part of this was due to the difficulty in determining when an upgrade was out, simply due to how releases were managed (a binary zip file sitting on one of their servers).

I also (foolishly) didn’t bother grabbing it when it was released, as simply it was a case of if-it’s-no-broke-then-don’t-fix-it. In fact, that’s a fairly conservative idea to follow with, but it’s reasonably easy to track source changes and rollback in required.

But I learned my lesson. As I was going through the notions for preparing for release, I discovered that I needed to upgrade the library in order to fix one big bug with user accounts having very high UIDs. Oops.

I’ve also seen that static behaviour in larger projects – projects which had a significantly extended genesis. They’d grab the current versions of their libraries as they were required, and kept them frozen as long as possible.

I personally don’t believe it’s the best option anymore. In some areas (particularly in my experience with doing Ruby on Rails development), keeping to a particular version too long has the potential to leave you trailing in the dust, due to the rapid progression of Rails as a platform.

Unlike other forms of engineering (if we are to get all serious for a moment), software development is significantly more fluid. A good software developer will always have a good Version Control tool by their side. A good platform will include ways to manage library dependencies (which does frustrate me doing iPhone development). Both of those are powerful tools to ensure that you can upgrade and rollback if things don’t quite work properly.

But most importantly: This isn’t an absolute. It’s just my opinion based on my recent experiences. In fact, if you need a significant amount of code auditing – it’s probably not that wise to rapidly upgrade unless necessary. But it’s always discretionary, and you need to weigh it up on your own projects.

Why you should avoid foresight in code

A large part of software maintenance is simply handling unexpected changes… Whether that’s due to client requirements, or even just compensating for incorrect assumptions made during development. The worse case is trying to deal with the case of being a little too prepared for a feature.

A case where this happened to hit home for me recently, was whilst I was working on some features for the 2.0 release of Eventbook.

The biggest feature I’ve been working on is the ability to cache a user’s events as they’re retrieved from Facebook. This was a feature I had planned to put into 2.0 for some time, having decided that learning Core Data on top of the rest of the UIKit basics for my 1.0 was probably a bit too much.

That sounds simple enough, right? However, I made one mistake. Knowing that I had planned to do this, I had done some investigative work into ensuring I was able to track when the last request to Facebook was, in order to determine when the next fetch request should be performed.

You should be able to see where this is heading. With the current cache time check, when a user upgrades to 2.0, Eventbook will perform the check as normal, but with the cache database empty, there won’t be any events to register.

Of course… solving that raises a number of questions. If I were to ignore anything, it would look poorly upon the application, as it would result in a false display.

An easier solution might be to replicate the functionality using a different value. The upside is that it will result in the correct experience for the user, and it is likely the easiest fix to implement. The downside is that I now need to handle tidying up the original value. This is likely a single call to NSUserDefault’s removeObjectForKey: method.

The third option (which is probably the cleanest), also requires the most stuffing about.

In this case, I’d put out a 1.1 release, the goal of which is to disable the code which sets the time. In addition, I’d also flush any current value from the user default’s object, which would then set the ground for 2.0 to be able to use it properly, without requiring additional sanity checks or clean-up code.

But, if I were to consider going down that route? I’d need to go through the list of tasks, and consider at least one feature to add into it so there would be something new. The major downside of that, is simply that it diverts time away from the 2.0 release.

I’m tempted at this stage to see about a simpler feature (just a single one), and see if I can add it to the 1.0 release (in addition to adding the revised application icon) to make a 1.1 release.