The Development and Evolution of Fairway
November 8th 2008
In late August I released my first official iPhone application named Fairway. You can read the product page or see it on the AppStore.
I’ve been meaning to put together a posting entailing my journey to 1.0. Needless to say it’s been 2 months and I’ve recently released version 1.0.2. Despite Matt Gemmell beating me to the punch, and writing an great article, I felt that it was finally time to write-up my experience.
Backstory
One of the principle drivers for why I write software applications is to solve interesting problems or make my commonly performed activity easier. If I consider myself an average person then I will in turn be solving a problem that others are having as well.
I’ve been a golfer for nearly 20 years now. Of that time I was a caddie for about 7 years as well as the recipient of the Evans Scholarship. During my time as a caddie I developed an appreciation for the decision making process involved in club selection. The casual observer (and likely the higher handicap golfer) would see the problem as simply your X yards from the hole which means you use club A. What they aren’t likely factoring in is the wind, temperature, location, environment of the ball (grass height, dirt on it, etc), pin position, landing area on the green, line of sight, etc. Any number of factors are involved in selecting the right club to use in making a “golf” shot which aren’t immediately obvious.
Personally I enjoy attacking most things in life analytically, and golf is no exception. I think this analytical approach is was why I’ve been drawn to the Pelz school of swing thought. In his book, Short Game Bible, Pelz provides a detailed analysis of the technique he’s evolved over the years to improve shotmaking. He recommends creating a single consistent swing tempo and then dividing that swing into 4 different sub-swings by varying the distance one takes the clubs back and through the ball. Using this technique you can take your short game clubs (Gap Wedge, Sand Wedge, Lob Wedge, X Wedge) and extrapolate 16 (4 x 4) different swings that will go 16 different distances thus giving you the ability to attack the pin from almost anywhere under 100 yards. There are slight variations you can make to this swing to handle other obstacles like sand or deep grass but the foundation of the approach is simple, consistent tempo combined with 4 distinct swing distances. It’s this simplicity that makes the Pelz approach interesting.
Now imagine taking this Pelz approach and applying it to your entire swing. Not all clubs need 4 swings but lets say you have 2 per club that aren’t short game clubs. That’s (14 - 4 - 1 (putter)) = 9 x 2 = 18 swings. Doing simple math we now have 18 + 16 = 34 swings for attacking a normal game of golf. Wait, what about those other situations I talked about earier? Hitting into the wind? In the rough vs. the fairway? Sand? Lets suppose that you have 2 more swings for each of those situations … that’s 9 x 3 x 2 = 54 more swings, add that to our current 34 and you have 88 swings. What I hope your quickly seeing is one of the problems that Fairway is attempting to solve. You quickly cringe at the mountain of numbers you need to remember extrapolate this technique to your entire game. Even if you don’t agree to applying the Pelz approach to your entire game just about any golfer will admit that there are a huge number of swings involved in playing golf that Fairway can help manage.
Paper Fairway
My first attempt at solving this problem was low-tech. I did what any card carrying 43 folders reader would do, I used an index card!!! Actually I used grid index cards on which I created rows for each club and then columns for each swing. This worked well for each of the simple swings but quickly got out of hand if you tried also handling various location based swings. Then there was the wear and tear I hadn’t accounted for on the cards from constant holding and putting in my pockets. Each card lasted me 2-3 games of golf and I either lost it or it was beaten to a wrinkled pulp. Losing it was obviously bad as I lost important data about my game.
Design via Moleskin
My second attempt at solving this problem was high-tech. I did what any good Apple developer would do, I wrote an iPhone application. Before I get ahead of myself though I did start designing Fairway in low-tech way, sketching in my Moleskin. Below are some of my initial sketches:
As you can see from the first image I tried directly applying the grid technique to the primary view on the phone. The obvious problems with this are that the iPhone doesn’t have the horizontal room to clearly display 4 columns along with club information. Even if icons were used it would have been a very busy view and it was hard to figure out how to handle more than 4 swings per club within this layout.
You can also see in the first image some ideas on swing icons as well as paging controls for bags. I wanted to be able to mange more than one bag of clubs at a time.
In the second image you can see my initial design for the primary views rounded corners along with initial thoughts on a vertical distance scrubber. While it would have been more precise using a vertical scrubber (longer distance to slide) I had issues with cleanly laying out the other controls needed for the current and future versions of the application with this layout.
Early Design & Revisions
Once I had done some sketches and played around with the beta versions of the iPhone SDK I began coding up some initial screens. At the same time I started coding I began talking with Fernando Lins about creating graphics and to get feedback from a designer on my UI. Here are a few of our early mockups.
I’m willing to bet you can easily identify the ones designed by me and those designed by Fernando. While I’m “decent” at designing and laying out user interfaces I’m not a professional designer. It’s however important to realize a few things about revising and designing your early user interfaces.
First and foremost your initial designs should try almost everything that comes to mind. Enter your early brainstorming sessions with your mind open to any and all possibilities because you never know what path a design will take you down. As you can see from my early mockups I was still stuck on the grid design. What was highlighted from actually mocking it up was how tight the iPhone 320×480 screen is (funny considering it’s the largest screen out there). I really wanted to try implementing it on the device despite the fact that I thought it wouldn’t work. It taught me quickly about what I as a golfer wanted and needed to see in this first screen which was detailed club information. Quickly and succinctly seeing the swing, club, and distance information was far more important than seeing everything possible on one screen.
The second thing to realize when designing and revising your user interfaces is how important it is to involve a graphics designer early in your development process. I know other people have said the same thing but it bears repeating. Not only do they bring color and spacial design experience to the table but they really start visually extracting some of the essence of your application in ways that you likely can’t do on your own. For me it was a huge motivation during development to see high quality design mockups of my application. The earlier you engage a designer the earlier you’ll being to see the reward.
Interaction Design
Whenever I’m working with someone on a user interface one of the first things I try to do is make them forget about the computer and show or draw the problem for me. I know this sounds simple, but how often have you actually done it? What I usually find is that I can solve the problem in a way that is comfortable and meaningful to the user and not an obvious product of a developers interpretation of the problem.
For Fairway I had to put myself in the shoes of the user being sure to put myself into the environment in which Fairway was to be used, on the golf course. What I wanted first and foremost was to see all of my swing options as quickly as possible. To me this translates into the smallest number of interactions with the richest set of usable data possible.
Interaction with an iPhone or iPod Touch requires pressing the on or home button and then a single slide to unlock the phone which I had to take into account if I wanted my users to use Fairway ~ 50+ shots per round, more like ~70+ if they use it for putting as well. From here I assume Fairway is running so I wanted to allow them to find their club in 1 - 3 additional clicks depending on details. The primary control for Fairway is the distance slider which is used to dial in the distance from the pin. The secondary control (along the bottom) is a location filter which allows you to quickly reduce your swing options based on preassigned swing locations.
In the above screenshot you see the primary, secondary, and detail controls highlighted. In it you can clearly see that the controls them selves are larger than they seem. Each and every controls size and position was meticulously selected, tested, and reselected to get what you now see.
- The distance slider being the primary control is likely the first control the user interacts with is easy to hit and prominent. Also important to note is that a user is likely using their thumb to interact with the distance slider. Given this, their thumb should not hide the distance label which is just above the slider in large easy to read text. In the initial mockups above you can see that their thumb may have covered their distance.
- The secondary controls seem like simple text labels at first but are in fact buttons that are larger than their text making them easy targets yet not cluttering the view.
- The swing details control, which is much larger than the icon itself, flips up the list (like in Maps) and shows club & swing details when pressed. This also happens when a recommended or other club is touched in the table.
- The gear settings control which I use instead of the “i” icon you see in most applications is the only exception to the rule in terms of size. It’s still plenty large to hit when your intending to but I wanted to make sure it wasn’t accidently selected during play so it’s a bit smaller than the details control button.
At the last C4[2] conference the keynote talk was given by Craig Hockenberry. During the talk he really drove home that this device is not a laptop and that designing software for the iPhone is different than other devices or computers we’re familiar with. He also reiterated something I had been trying to do which was design the software by actually using it. I know it sounds simple but so many apps in the AppStore seem like they missed this step.
I do have to admit though that I missed something fairly important in Fairway until I used it one day at the range. It somehow slipped my mind after playing golf for 20 years that we wear a glove on the course (not usually while putting though). Gloves are typically worn on the hand opposite our dominant hand and are used to improve control over the club. Since I’m a right handed person I wear my glove on my left hand which is also the hand I primarily use for my iPhone. This poses a problem since you can’t use the iPhone wearing a glove. I now had to take into account that my application was going to be used in the hand opposite that which most users were comfortable. To address this potential problem I made the distance and detail controls invertible on the main screen (flipped left to right).
It’s a small touch but if it makes a small fraction of my users a bit more comfortable with my application I’ve done my job. Thanks to Twitteriffic and Craig for the idea of control inversion.
GPS Not Included
I wanted to take a second to address some initial shock people had using my application at first, there’s no GPS. I know it may seem forboden for an iPhone application to not be tricked out with every bell and whistle. My primary concern with writing Fairway was quickly recommending clubs and swings to use. I don’t want to detract from the beauty and grandeur of the game by playing with your iPhone waiting for the GPS to attain a lock. It can sometimes take minutes to get an actual lock on your position, minutes you should be spending focusing on your swing. Also don’t forget that this application is designed for the iPod Touch, iPhone, and iPhone 3g. I’d lose 2/3 of that audience if I leveraged GPS to a huge degree.
Creating Custom Table Cells
After the data entry controls the most important view in the application is the club & swing list. In it the user can see all of the clubs and associated swings that are “usable” based on their distance and location information. This list needed to be clear in direct sunlight conditions as well as the shade you may encounter on the course.
As you can see I chose a slight white gradient behind the default cells with dark green text for the text. I did this to add some textural perspective and dimension to the interface itself. I think it looks clean and offers subtle hints to touch it. Adding these effects also helps them clearly see the data in both bright and shady situations by adding contrast to the contained text and graphics. The recommended swing (green) and touched swing (blue) are drawn using the CGGradientRef Core Graphics API. Though the original gradients were designed by Fernando I chose to render them using code instead.
Within each row is a swing icon that can have optional text associated with it. It also contains the name, brand, and model of the club associated with that swing. Finally it contains the distance you can hit that particular swing in the selected format for the user (yards, feet, or meters). This is all of the information a golfer needs to identify the swing type (icon & text), club, and expected distance the swing is meant to produce.
I tried to give people a huge selection of icons to use to represent their swing. Because I didn’t know what creative ways people might come up with to help them remember their swing I provided 1/4, 1/2, 3/4, and 4/4 (full swing) icons as well as a large set of gem of various colors and shapes.

Because of the variety of icons and the fact that I allow text (2-3 characters) to be entered on both dark and light icons I had to figure out where the text was being drawn and then make the text and shadow an appropriate color. This enabled the text to be easily and quickly readable in any situation. It’ a small detail that can have a dramatic impact in terms of usability.
Rounded Tables
My goal for the list view was to make it familiar and fun to use. The first app in my mind that was easy and fun to use on iPhone OS 1.0 was the Stocks application. I really enjoyed how you could slide that list up and down and not only would it bounce but it would appear to be etched/sunken into the background because the rounded edges were always visible. I thought for sure that Apple would have this in their SDK and smiled when I saw the UITableViewStyleGrouped style. I was then immediately disappointed when I saw that it didn’t have this expected behavior. This left me with no options in the early NDA days to do anything but to roll my own. If you look at my sketches up top you can see I had thoughts of an early version sketched out. Here is how it was finally implemented.
In this image I’ve highlighted four small views that are positioned above the UITableView. The background of the view is clear and the arc and the area opposing the table is filled in black. An example of the code needed to draw the upper left arc and to fill it is:
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSaveGState(context);
[self.color set];
CGContextBeginPath(context);
if (WARoundedTopLeftCorner == self.position) {
CGContextMoveToPoint(context, CGRectGetMaxX(rect)/2,
CGRectGetMinY(rect));
CGContextAddLineToPoint(context, CGRectGetMinX(rect),
CGRectGetMinY(rect));
CGContextAddLineToPoint(context, CGRectGetMinX(rect),
CGRectGetMaxY(rect)/2);
[WIShapeView addArcToPath:rect
context:context
startAngle:180
arcAngle:90];
}
CGContextFillPath(context);
CGContextRestoreGState(context);
Note - for the addArcToPath code see the quartz docs.
I chose to use code in drawing these shapes instead of using images because I could and I suck at most graphics tools. In fact wherever I could I chose to render something via code over using images. Obviously there are places I “could” have written code to render that I didn’t. It was more a comfort factor than an exact science. I chose to leverage Fernando on some of the larger problems and not these smaller ones.
Using the implementation of the overlay of the views on top of the table view will only work if the background color of the table view itself is set to black. This requires that you write a custom UITableViewCell to draw it’s background and inset it slightly so it looks like the grouped style people are familiar with. This will allow the table to slide under the corner views and give it the effect of being inset into the foreground much like the stock application. The only remaining piece of code to be done is to create 3 categories of table cells. Those cells that are at the top, middle, and bottom of the table. The ones at the top and bottom can reuse the view you created above to draw rounded edges on the top and bottom. This will provide the effect of the table being rounded on all sides. Be careful to put the rounded views at the far corners of the cells. You may need to play with the placement of all of the views to get them exact.
Crashing the UITableView
When a golfer is on the course they rapidly scrub in their distance from the pin and expect the table to update appropriately. My first implementation accepted real time updates from the slider and on each update added and removed the appropriate cells from the table view using animation. The code was straight forward enough except for one small flaw, it crashed the application after a few seconds of use. I submitted radar 6020225 detailing the issue with example code but it has yet to be fixed. I tried a number of creative ways to work around this problem but still keep animation and the real-time updating.
So what was I going to do? After meeting with Apple at number of different WWDC labs I finally got the idea to introduce an artificial delay that while not perceivable to the user would allow me to reload the table without crashing it. The code is rather easy using:
performSelector:withObject:afterDelay:
I introduced a 0.25 second delay and within the called selector I just setup the underlying data structures of the table and the told the table to reload. The unfortunate impact of this implementation is that it isn’t animated. While not ideal it is actually very performant and after using it for a long time I actually prefer it to not animate. The animation felt distracting at times and seemed to prevent the user from quickly getting their recommendation. Another note on this implementation, be sure to not enqueue all of the scrubber changes to the selector, if one is already enqueued then ignore the others.
One final thing I wanted to mention around the animation of the UITableView was performance. While it animated smoothly in the simulator (it still crashed) it was actually slow and dropped frames on the iPhone. Because the table wasn’t designed to be updates that quickly and the fact that I was trying to do it with animation in real-time caused it to stuttered and drop frames. I didn’t see this side effect though until after I tried running on the device. Don’t assume because you tested your application in the simulator that it will run just as well on the device. You will likely have to iterate to attain a solid user experience.
Tolerances
Something you may have noticed in the list view is that there are often many more swings shown than you might at first think are necessary. If the user selected 182 yards why are there clubs going from 162 - 202 yards. On the golf course there are other conditions like elevation of the green relative to the golfer, wind direction, etc. that are hard problems to solve in a user interface yet still need to be taken into account. Because of this I allow the user to select a tolerance for the application that is applied to their suggested clubs.
This tolerance allows them to see a wider range of clubs that they can mentally decide to ignore or perhaps use. I can’t make all of the decisions but I could help narrow down their options.
Many-to-many Relationship Editing
One of the larger problems I encountered with Fairway was managing the relationships between bags and clubs. Because I knew I wanted to give users complete control of how they grouped their clubs (into bags) I needed to ensure that the user experience was still simple yet powerful. To do this I wanted to allow them to add any arbitrary club to a bag and then when editing a club quickly see and edit which bags it was in. Below you can see an example movie that shows first adding an existing club to a bag and then going to that club and editing the bags that it’s in.
As you can see for the additive portion of bag and club management I leveraged the modal view functionality on the UIViewController. This encouraged a simple familiar workflow of choosing the item to add and then updating the list based on the selection. Everyone who’s used Mail for deleting or moving is familiar with this interaction. The only variability to the workflow was when adding a club to a bag I first had to ask the user if it was a new or existing club and act accordingly.
The other interaction when managing a many-to-many relationship is the deleting or removing from the relationships. When I first implemented this I used the built in delete functionality of the UITableView that everyone was familiar with. When you clicked the red minus button on the left it rotated and then presented you with a Delete confirmation button on the right. Simple enough but I was very bothered by something with this action.
The user was not deleting the club or the bag, instead they were “removing” the club from the bag or vice versa. It’s a subtle difference but a few of the people I showed it to thought it was deleting the club and were either confused or concerned about deleting. Unfortunately the current UITableView from Apple doesn’t support customizing the delete behavior or widgets. Again I had no other option than to roll my own.
I really liked the behavior of the existing delete interface and didn’t see the need to create a new technique and have to train the user how to use it to remove something. Because of this I simply strived to reproduce the existing behavior of the delete within a UITableView to manage my removal of clubs and bags. Sounds simple enough but here are the interactions:
- Switching into editing mode is the primary driver of showing the remove controls for the table. Mail has a swipe feature as well but for the purposes of this implementation I did not implement that behavior (due to release constraints but I will soon).
- Leaving editing mode should hide all editing controls and resets their state.
- The default editing state, lets call it the “zero” state, of the cell presents a circular remove button on the left and then some other content like labels on the right.
- Selecting the circular remove button should cause it to rotate 90° and at the same time reveal from the right hand side of the cell a confirmation button. During the animation all of the content on the right needs to also resize to make room for the confirm button. Lets call this the “confirm” state of the cell.
- Selecting a circular remove button in the confirm causes the right hand confirm button to reverse the animation and disappear while at the same time rotating the left hand circular remove button -90°, resizing all of the content to take up the new room, and placing the cell back into the zero state.
- Selecting the confirm button from the confirm state causes the row within the cell to be removed and appropriate action on some delegate to be performed.
- Selecting a circular remove button on any other cell should cause any cell that is currently in confirm state to animate out and back to zero state. At the same time it should transition that new cell into the confirm state.
- Scrolling any table should cause any cell currently in the confirm state to animate back into the zero state.
The simple elegant behavior that a user experiences while interacting with these cells is backed by a complex orchestra of interactions within the code. As you can see there were quite a number of behaviors that aren’t 100% obvious when you first use a table. Only after playing with them for a while was I able to note their exact behaviors and once I had recorded my observations implementing them was fairly straightforward. Here is a small movie showing the final interactions I described above using Fairways remove cell.
I think the hardest part of the implementation for me was getting the confirm button to reveal properly. I toyed with core animation on that buttons layers over and over again and was never able to get it quite right. It doesn’t slide in from off screen and it doesn’t just fade into being, it fades and reveals concurrently. I don’t know if this is considered a hack but I placed a small view where the button would reside, behind any views in the cell but above the z-order of the confirm button and then animated the resize left and right. The image below highlights where the view would have been in green.
If there are other more elegant ways of accomplishing this I’d love to hear about them.
First Launch
When the user first opens Fairway I thought it was important that they be able to see it in action in it’s full glory. The only real way to do this is to seed the users application with sample data. Because I thought it was so important I shipped the application with an entire sample database containing all of my actual club data. When the user first launches the application they are presented with this question:
Assuming they answer Yes they will have 17 clubs with 67 swings. Just as easily as they were added the user can goto the settings and remove them at any time. If they happen to choose No they will be presented with the following screen:
This is also the dialog they are presented with during normal usage of the application whenever Fairway can’t suggest a swing for their distance and filter criteria. It animates in from the top of the screen and centers itself within the list view. When criteria is entered that matches a swing it swoops off the screen out of view. Wherever possible I wanted the user to receive some type of feedback, even when I had nothing to show them. The more they feel at home using my application the happier they are.
The Grass is Greener
No golf application can be complete without a little flair. Throughout the use of fairway you’ll find bits of golf spread throughout. From the golf ball on the distance slider, to the club on the main screen to show / hide swing details, to subtle and not so subtle hints of grass throughout. When I was working on the application I used a number of different background textures for my club management views. From green pinstripes to the default gritty look I tried them all, that was until Fernando gave me something more. I wanted something to pop and yet really pull the user into the application, when confronted with this problem he gave me a nice grass texture to place behind my views.
It’s different and distinctive and I think not to distracting. I really love the color ranges of the iPhone and think using the grass texture really lends well to classifying Fairway as a golf application.
Wrapping it up …
I’ve covered a number of the features within Fairway in this article but I’ve mostly stuck to the challenging problems I encountered during it’s development. It really takes a lot of put together a complete application with all of it’s rough edges filed away. For me it took at least a month longer than I had anticipated. My release guidelines were very simple, don’t release with bugs. Not a single known bug or glitch of any kind, zero, nada. If you noticed it then odds are someone else will as well.
I had a bug at the end of my release that only occurred when you added and removed samples from the application more than 2 times. Despite the fact that this was something no one is likely to ever encounter I held the release a few days until I fixed it. Had I released with that bug, odds are that a user would have encountered it and they would have been the first comment on my application in the AppStore.
I appreciate that you’ve made it this far in the article. I really do enjoy sharing my ideas and solutions with people and hope you took some tidbits away from this article. If Fairway is an application you think you would like or want to support then you can read more about it or check it out on the AppStore.
My biggest goal releasing this application wasn’t just to release a golf application that I would use. It was to release a golf application I was proud of, one I didn’t cut corners on, one that I could recommend to any golfer with an iPhone. Heck even one I could recommend to someone interested in user interface design and interaction. I highly suggest you set similarly high bars for your release. It’s not enough to release an average iPhone application, you should instead strive to push the envelope and make your application distinctive and innovative.






