As an update to this post, I wasn’t able to sneak the GhettoDoro app by the App Store review process. I intentionally left the UI just about as rough and barebones as possible because the idea of getting Apple to publish an intentionally bad-looking app of mine would be funny. I think this is mostly The Smart-Ass 8th Grade Version of Me that thinks things like having an app named GhettoDoro is glorious.
After getting totally rejected by Apple, I decided to take GhettoDoro and use it as a platform to learn about unit testing and TDD in the Cocoa and Objective-C world, namely the OCMock and XCTest frameworks. It was pleasant using TDD to drive the process of design and refactoring — the timer logic is now in a model class so that the view controller can stay unpolluted.
I would have been perfectly content to leave this project unreleased, but after a week, I found myself using GhettoDoro more and more often. It’s actually useful! That meant it was worth polishing up and having its interface be more than just a juvenile punchline.
One thing that stuck out at me while reviewing the iOS 7 UI design recommendations from Apple is that they champion a full-screen design modality where the entire screen is used to express information. Their Weather app is a great example of this. I wanted to take a swing at an interface like that as well.
My thinking was that the user should be able to look at the screen and tell how much time they had left without actually looking at the time left. What I came up with was to have the background turn from green to red as it ticks down. Green and red are universally known as stop/go — hilarious to a colorblind person like myself — and it also fits in with the theme of tomatoes in the Pomodoro Technique, like how a green tomato is fresh and a red tomato is ripe.
One complication to implementing this feature was that the color needed to be based on the proportion of the time left vs. how much time was added to the timer. For example, if you start a 5-minute timer, it should be just as green as starting a 1-hour timer. And if a timer is almost red, adding 5 minutes to it should not push it back to full green. That meant that the color had to be calculated with a ratio multiplier, where the ratio is based on the current time left and the total time added to this timer.
There’s also a lot of behind-the-curtains trickery involved to support background notifications and pausing/resuming the timer. It’s was a bit challenging in the sense that there are a lot more potential cases to have to consider. The timer can be started/stopped/paused/resumed, but the app can be in the foreground or the background as well. And when it’s paused and and started again, does the notification get rescheduled to the new timer end date? That sort of stuff.
These different use cases and scenarios can be tough, but taking a TDD approach helped immensely. It allowed me to really focus on the app requirements, while writing the production code was almost a secondary concern. The beauty of TDD is that it lets you really build your system to do what you want it to do.
As I am finding out in a current project however, there’s one exception where it makes sense to drop TDD, and that’s during a spike when you need to explore a problem that you don’t have enough experience to know how to design, approach, or solve. You can’t write a test to specify what your code should do if you just don’t know what it should do. Even if you think you know what it should roughly do from a black-box, outside-in, functionality perspective, your initial assumptions about your code’s API and its expected behavior is likely to change.
I feel like a good way to tell if you should drop TDD temporarily is if you’re writing a unit test and you say to yourself, “I am pretty sure I will need to drastically rewrite this test.” In that case, there’s no point writing something you’re likely to junk entirely. Of course, the rub is that you have to circle back and make sure you write that unit test afterwards.