In June 2011, I published a very simple looking App that displayed departure boards for London Underground trains. Here are some screenshots of how it looked (on an iOS 6 simulator).
Aside from showing the departure times, the App also gave status information about station and line disruptions. The crowning jewel of UI was the "Line View" that shows the which stations a train has and will call at, along with the timings.
Thanks to Apple featuring the App in the travel section as "New and Noteworthy", the App gained a little bit of attention and over a year, about 1000 people had downloaded the App. A few emails would trickle in and some request features, like a journey planner or the Tube map, but for the time being, the App wasn't going to change. Most of the updates were server side, with only six native updates in 18 months.
Time to Add More Functionality
However, as the months went by and the App became less new and less noteworthy, I decided to spend the Christmas break introducing a boatload more features. Here are some screenshots of how v2 ended up looking (on an iOS 7 simulator).
As you can see, the amount of functionality increased dramatically between v1 and v2, but the way in which this functionality was added was hugely rushed and ad hoc. Also, although v2 only supported iOS 5 and above, many parts of the original code base were never refactored (beyond adding ARC support) and therefore there was still lots of old, redundant, archaic code. View code was the worst - when iOS 7 arrived I never did quite manage to make it work delightfully on iOS 5, 6 and 7 simultaneously. I consider this App to be a great prototype, but if I ever wanted somebody else to work on it, it wouldn't be practical in its current state.
A Complete Rewrite
So, in February 2014, I started a complete rewrite. Of all the projects I have worked on, this one was probably the most demoralising. Each night I'd look at what I had achieved and wonder why I was bothering with the rewrite. In the first few weeks, where much of the work is setting up the network layer and model classes, very little UI can be demonstrated. It certainly felt like an uphill battle to get just one tab done.
In total, it took 17 weeks of spare time to complete the App. The new App also has extra functionality that the old version didn't have, for example, iCloud backups. These extra features were the secret to finishing the project; they kept me interested and motivated. When it came to releasing this version, 80% of the release notes were devoted to these small features, and allowed others to value the last 17 weeks of my life more easily, which made me feel like I had accomplished something.
If you'd like to see what the App looks like now, take a look in the App Store.
Now the question remains:
Was it Worth It?
The codebases between v2 and v3 are hugely different, but if I were running this App as a business, would the work have been justified? This is difficult question to answer with conviction, but here are some of the ways I've rationalised the work to myself:
- v3 works with iOS 8 out of the box, whereas v2 has numerous issues; solving them may take a few days.
- Implementing the extra features would probably take a couple of weeks. Some of the features would be particularly nasty to implement in the old code base and only add to the technical debt.
- Hiring a dev or designer to work with me on this project would have been embarrassing with v2. It may have made hiring difficult.
- Getting help with project (e.g. with a Technical Support Incident) would have been similarly embarrassing. In fact, there were so many odd patterns in v2 that I could imagine being told to solve them first before receiving help.
- v3 no longer depends on ASIHTTPRequest, which is now no longer supported, which means I do not have provide support for that library in house.
- Future updates are much easier; since releasing 5 weeks ago, I have shipped 5 updates. This includes full accessibility support, which would have taken longer to implement in v2 due to the unconventional controls used (e.g. v2 didn't use a UITabBar, but a custom control).
Probably the biggest irritation is that if I had waited until after WWDC, v3 would be written in Swift.
Below is a technical summary of how the code has changed between each major version.
| | v1.0 | v2.5.5 | v3.0.5 | |------------------------------------|---------------|---------------|---------------| | Number of lines of code | 16,049 | 50,464 | 28,662 | | Number of images | 11 | 473 | 8 | | Number of XIBs | 0 | 19 | 11 | | Number of Storyboards | 0 | 0 | 10 | | Average lines of comments per file | 77 | 45 | 26 | | Total file sizes | 692.1 kb | 10.9 mb | 1.8 mb | | Number of code files | 67 | 305 | 267 | | Deployment Target | iPhone OS 3.0 | iOS 5.0 | iOS 7.0 | | Number of minor/patch updates | 6 | 14 | 5 so far | | Programming Language | Objective-C | Objective-C | Objective-C |
- If you treat your code like a throwaway project, you're going to need to throw it away.
- When reimplementing a project, there is a long period at the beginning where it feels like nothing is happening, however, the features come through thick and fast once you have solid backing layers.
- You don't need to reimplement everything. Some of the original code is probably fine the way it is; focus on the important pieces.
- The feeling of accomplishment is important. When refactoring, introduce some small, quick-win features to keep you motivated.
- In a few years, I'll probably decide that this needs rewriting again (if only I had waited a few more months, v3 would be 100% Swift).