October 1 2009
The feature I alluded to in my "Rereading Info.plist" post is a logging preference. It has two requirements: user-configurable (i.e. not code) but not immediately visible. When a user starts having technical issues and calls tech support, they find out how to turn on logging, and with that output, development has a better idea of what the issues are.
A year ago, when I first implemented it, I was averse to adding a secret preferences window, because I couldn't think of a natural place for accessing it. Instead, I added a quick key-value pair to Info.plist. Users wouldn't happen across it; most of them probably don't know app bundles are folders. But the preference was there if needed. So, I shipped that. Multiple times. Recently, I decided this preference needed to be dynamic, for those times when a user wants to enable logging without restarting the application. I set up an NSTimer to read the key-value pair from Info.plist every minute. After finding out the dictionary was cached, I figured out how to manually read it. Problem solved.
And yet, I completely ignored all the signs that pointed to a bad user experience. The workflow for setting the preference was complicated to explain to other developers (who know app bundles are folders). Non-developers asked for the specific steps multiple times. And yes, the Info.plist dictionary is cached, implying it's for general application information, not debug settings. Still, it took two thoughtful comments on my other post to snap me out of my developer haze and think about the feature from a user's perspective.
The goal of the feature was to hide the user-configurable preference from immediate view, not to bury it completely. The Info.plist workflow didn't work, so I started brainstorming. How about a secret preference window? Fine, but where would it go? Perhaps an NSMenuItem, but that's not hidden. Then I realized an alternate NSMenuItem was the perfect fit: hold the option key and "Preferences..." switches to "Secret Preferences...". A user won't stumble across it, but the menu item is a key away. Moreover, an NSTimer isn't necessary; Cocoa Bindings make a preference change instant. That's what I implemented today.
Never be afraid to iterate your design. The product I work on went through many iterations before arriving at its current form. Apple agrees. When I've talked to their UI evangelists, John Geleynse and Eric Hope, both consistently cite design iteration as one of the most important processes for developing award-winning applications (along with product definition statements). Most apps start out looking mediocre; the best user experiences are the culmination of many iterations. Keep iterating.