Monday, September 14, 2009

The Simplest Thing That Could Possibly Work

One of the maxims of Agile development — and especially Extreme Programming — is to write the simplest thing that can possibly work.

There are a few driving forces behind this motto. First, a core tenet of Agile development is to get testable, functional code up and running as soon as possible. If you don't spend a lot of time writing complex code, you can get it running sooner. And complex code is harder to maintain and thus more likely to have subtle bugs. Second, Agile assumes that requirements will change. This in part because requirements always change, but also because the mere act of showing a user a current piece of software will give them new ideas for the features that will really solve their problems. Users aren't good at articulating what they need until they see something "tangible" that isn't what they need. If you get a piece of code up sooner, you give your users the chance to steer the application in the direction they really want, not the direction they thought they wanted. And when they present this abrupt change in direction — as they inevitably will — you don't have to dismantle a complex system.

A close cousin of the "simplest thing" motto is "You're Not Gonna Need It." Experienced programmers tend to think in terms of frameworks they can build, good object-oriented principles, and so forth. But if you spend a lot of time building a nice, modular system with layers and abstraction, you may have wasted your time and effort if there will only ever be one module, one implementation of a given interface, or one class in a layer.

This is not to say that you should be sloppy, or churn out quick and dirty, copy-paste code. You are a professional and should act like one. Your "simplest thing" should be tested and it should be clean code. As the requirements change beyond what your "simplest thing" can do, you can then start to build layers on top of it, refactor to make it more modular, and so on.

All these arguments came back to me when I had to implement templatable text at work. I wanted text that a non-programmer could modify, but it needed to allow variable substitution.

Java's localization system allows this to some degree, except that its variables are numeric, not symbolic. So item zero is always the same, item one is always the same, etc. regardless of where they show up in the string. This makes sense for localization, but is fragile for more general templates. What if we wanted the text to use a different set of variables from one week to the next?

There are a number of general-purpose templating systems for Java: Probably the best-known is Velocity. As I started researching what it would take to implement it, however, the "simplest thing" motto came back to mind. Not that Velocity is difficult to implement, but we only needed to support five variables, and we didn't need any of the flow-of-control logic that Velocity offers.

So I wrote a very simple set of methods that allows me to do string replaces on the five symbolic variables I allowed. The (internal) user can write any text, using some or all of those variables once, twice, or whatever they want. And just in case we ever need to move to Velocity, I used the same variable naming syntax to define our variables.

The code is simple. It has noticeable restrictions (can't use undefined variables, can't define new ones), but in this case, it works exactly the way I need it to. It satisfied the business need, and truthfully, will probably never need to support more. When I needed to add an additional piece of templated text with the same variables, it took about 15 minutes including 10 minutes of testing.

Friday, September 4, 2009

Tutorial System, Part 2: Variadic Methods

In my last post, I mentioned a simple tutorial system that I wrote for my iPhone app: When I pass a key to the system, new users get a text box explaining the purpose of each screen, tap to close it, and then never see it again.

It worked well enough, though my testers have some usability comments that I need to address. But as I started working on version 1.1 of my app*, I realized that I had new needs. I had written, as I try to remember to do despite the temptation to overdesign, the simplest thing that could possibly work. That no longer fit the bill. (Writing the simplest thing that can possibly work assumes that design requirements will change. But since you can't predict those changes, even when you're the one creating them, you shouldn't waste time designing for requirements that don't yet exist. Address the problem in front of you, get functional code up and testable, and then refactor to simplify.)

I wanted the system to handle upgraders, so that upgraders would see text just about the new features, while new users would see a screen giving an overview of the page, including the new features. The key was that when a new user dismissed the tutorial box, s/he would never see the one for upgraders (because there would be no need).

I toyed with a few ideas, but I finally settled on one: Rather than passing a single key to the system, I'd pass a list of keys. The system would iterate through the keys until it found one the user hadn't seen, show the tutorial text for that key, register that the user had seen the key, and then register every subsequent key in the list.

In order to make this work, I used a variadic method, one with an indeterminate number arguments. It's been a while since I've been deep in a C-based language, so I had to refresh my memory about implementing them. (Curiously, the Objective-C bible, Programming in Objective-C, doesn't tell you how to implement them. Perhaps the new edition does.) They rely on the stdargs.h macros, va_start, va_arg, and va_end. In Objective-C, the convention is that the last item in the list be nil. For example, see NSArray's initWithObjects: method.

If you want to implement your own variadic method in Objective-C, here's the basic pattern (you don't need to import stdarg.h if you're importing the Foundation classes):


- (void) method: (id) arg, ... {
va_list argList; // special datatype for the argument list
va_start(argList,arg); // sets up the iteration

id curArg = arg;
while (curArg != nil) {
// do something
curArg = va_arg(argList,id); // pass the datatype you expect to find
}
va_end(argList);
}



Here's the code in the context of my Tutorial system:


+ (void) showTutorialForKey: (NSString *)key, ... {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
va_list argPtr;
va_start(argPtr,key);

NSString *curArg = key;

while (curArg != nil) {
if ([TutorialSystem userHasSeenKey:curArg]) {
curArg = va_arg(argPtr,id);
continue;
}

NSString *titleKey = [NSString stringWithFormat:@"%@ Title",curArg];

NSString* title =
[[NSBundle mainBundle] localizedStringForKey:titleKey value:@"" table:@"Tutorial"];
NSString* text =
[[NSBundle mainBundle] localizedStringForKey:curArg value:@"" table:@"Tutorial"];

TutorialController *controller =
[[TutorialController alloc] initWithTitle:title tutorialText:text];
[[[self appDelegate] window] addSubview:[controller view]];

// clear the user for all the rest of the args
while (curArg != nil) {
[TutorialSystem registerUserSeesKey:curArg];
curArg = va_arg(argPtr,id);
}
}

va_end(argPtr);
[pool release];
}



* I should note that 1.0 of my app is not yet out, despite being published on the App Store, because of some bureaucracy with my employer. Assuming it's going to get resolved. I've started on 1.1.

Sunday, May 31, 2009

Tutorial Mode For An iPhone App

One of my testers suggested that I have a "tutorial" for new users of my app: Help screens that pop up the first time a user visits a feature. There are many ways to do this, of course, but here's the implementation I designed. A client invokes the tutorial system in a simple way:


[TutorialSystem showTutorialForKey:@"Welcome"];



The TutorialSystem class takes over the rest through a series of class methods. (There's never an instance of a TutorialSystem object. Not a very object-oriented approach, but the tutorial system doesn't need to maintain state between invocations.)

Obviously I only want to show a tutorial screen once, so showTutorialForKey: first checks to see if the user has already seen the screen. I have an "application state" dictionary file that gets used for miscellaneous persistence: the last tab the user looked at before shutting down, the date they were looking at in the "by day" view, and so forth. The tutorial system uses the same dictionary to keep track of which tutorial screens the user has seen. In particular, it looks for a key named "hasSeen" followed by the name of the key passed in to the showTutorialForKey method. For the example above, the dictionary would have a key named "hasSeenWelcome."


+ (BOOL) userHasSeenKey: (NSString *)key {
if (ALWAYS_SHOW_HELP) {
return NO;
}
NSMutableDictionary *prefs = [[TutorialSystem appDelegate] appState];
NSNumber *didSee = [prefs objectForKey:[TutorialSystem prefsSeenKeyForKey:key]];

return didSee != nil && [didSee intValue] != 0;
}



(I have a #define that lets me always have tutorial screens show up. This is helpful for testing.)

If the system decides that it needs to show the tutorial screen, it uses the passed-in key as the key for a line in a strings file, the resource files Cocoa uses for localization of text. It also uses the key plus the text " Title" as the key in the strings file for the title of the tutorial screen. That means there's a line in my strings file that maps the tutorial body text to the key "Welcome" and another line that maps the tutorial screen title to "Welcome Title."

From there, it loads an xib file that I built in Interface Builder and lays it over the existing view. That file contains a screen-sized view that doesn't allow user interaction, but has an opaqueness level of .4. That way the underlying screen will still be visible. The xib file also contains a "tutorial screen" view that contains three subviews: a UILabel for the title, a UITextView for the tutorial body, and a UILabel that says "Tap to continue." The tutorial screen view handles all the user interactions, and interprets any touch to mean "go away." Here's what it looks like.



Finally, of course, I register that the user has seen the tutorial screen by placing the appropriate entry into the application state dictionary.

Here's the full showTutorialForKey: method:


+ (void) showTutorialForKey: (NSString *)key {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
if ([TutorialSystem userHasSeenKey:key]) {
[pool release];
return;
}

NSString *titleKey = [NSString stringWithFormat:@"%@ Title",key];

NSString* title = [[NSBundle mainBundle]
localizedStringForKey:titleKey value:@"" table:@"Tutorial"];
NSString* text = [[NSBundle mainBundle]
localizedStringForKey:key value:@"" table:@"Tutorial"];

TutorialController *controller =
[[TutorialController alloc] initWithTitle:title tutorialText:text];
[[[self appDelegate] window] addSubview:[controller view]];

[TutorialSystem registerUserSeesKey:key];

[pool release];

}

Thursday, May 28, 2009

Simulator Versus Device

I had an amusing realization this morning as I finished up a feature for my iPhone app. I implemented a "touch and hold" mechanism (see this excellent description of how to do it) and tested it last night on the simulator, Apple's "virtual iPhone" that makes it faster to turn around and test new code. It worked perfectly.

This morning, I put it on my phone, and it barely worked at all. It took me a few minutes, but I finally figured out the issue.

In my original code, touchesMoved dismissed the timer that eventually puts an indicator in place that you're in editing mode. On the simulator, that's not a problem: You take your finger off the mouse. But in the real world, your finger does not sit perfectly still. Mine doesn't, at any rate. So I had to add literal wiggle room. If you stay within a small radius of touches, the code won't dismiss the timer. Now it works just the way I want.

Sunday, May 24, 2009

I Am Not a Graphics Programmer

I consider myself a good programmer. I can comfortably chat about anything from high-level topics such as methodologies and architecture to the minutiae of multithreaded code and Java virtual machine idiosyncracies. I understand how to solve a wide range of scalability issues. I have a good eye for the subtle details that cause bugs. I know at least the basics of when one algorithm is better suited for a task than another.

Put me in front of a graphics library, however, and I freeze up. I've been doing some simple graphics work in my iPhone app — filling an area with a gradient, for instance — and it's been slow going. I don't have the terminology in my head for this work to come naturally. Transforms, alpha channels, drawing paths, blending modes. I might as well be reading Greek. And it doesn't help that Quartz, the graphics drawing system on the iPhone, is all based on C, a procedural language, instead of Objective C, an object-oriented language. It's been a very long time since I've worked in a low-level procedural language on a regular basis. (I will say, though, that Quartz tries its best to encapsulate the C code in macros that provide a straightforward coding experience. The graphics folks around me at Maxis think that it's pretty sweet, which makes me wonder what sort of libraries Microsoft gives to Windows programmers.)

Some of my frustration comes from simple lack of experience. I didn't used to know a lot about server-side programming, after all. As I do more graphics programming, I suppose more of it will come naturally, and I will learn more of the subtleties. But I've also never been drawn to that side of the coding fence. I like to say that I have no design sense. This isn't strictly true: I did the design work for Obsession With Food, and I've got some stunning quilt tops that I designed. But I'm always surprised when something I design comes out well.

Yet here I am, literally a one-man development team for this application. I can manage the architecture just fine — and it's pretty good — but there's no one I can hand off the graphics work to. It's just me. I speed through the object-oriented development side and slow to a crawl when I'm dealing with Quartz. In the long run, it's good for me to expand my horizons. But in the short term, the part of me that's used to quickly getting code up and running is growling at the long periods of time it takes me to implement the simplest little things in the graphics world.

Back to figuring out why my transparent blue is sometimes the only thing in the rectangle and is sometimes on top of the gradient that's supposed to be gone at that point. And why doesn't my grey rectangle show up at all? All this for a tiny-but-necessary bit of visual feedback on an already functional feature.

Friday, May 22, 2009

Federal Data Coming to a Web App Near You

The Federal government is releasing tons of data in web-friendly formats. See the perfectly named data.gov.

Must. Finish. One. App. Before. Starting. Another.

Friday, May 15, 2009

Real-World iPhone Rotation, Part 1

When I researched the techniques for supporting rotation (portrait vs. landscape) in my iPhone app, I found a few tutorials that all did the same thing: Stick a label in the middle of an otherwise unadorned view and override one method.

Simple, yes? Yes. If you're writing a boring application that just has one line of text in the middle of the screen.

My application has a tab bar. It has multiple screens. It has custom views that pop up from the bottom of the screen. It is not well served by the tutorials I found. Here, then, is one part of my tutorial, based on my own experience.

First, the default mode for any UIViewController is to not support rotation. It's easy to change that if you have a custom class that inherits from UIViewController: Override shouldAutorotateToInterfaceOrientation: to return YES. (You can get fancy with the argument passed in and only support certain orientations, but I didn't.)

But what if you're using a UITabBarController? The same idea applies, unfortunately. Make a subclass of UITabBarController and override that method. In Interface Builder, then, set your custom class as the handler. My class, RotatingTabController, does nothing except override that method and return YES. Yay for class bloat! There may be some way to just set a property in a normal tab bar controller and have it magically start handling rotation, but I haven't found it. So a brand-new class that exists solely to override a boolean return value it is.

However, once you've overridden that method for UITabBarController, you don't need to do it for all the views that hang off of it. But you do need to make sure your views behave when rotated.

The rotation animation on the iPhone is snazzy: Views arc around the screen and rearrange themselves. Get too wrapped up in the idea that you're rotating the view, however, and you'll hurt your head. Instead, think of it as resizing the view, since that's actually what it's doing. It's much easier to grok if you imagine going from this:


to this:


If you're using a built-in data view (table view, image view, etc.) as the sole item on the screen, it probably already behaves the way you want. If you're using a custom layout like this one, which includes a UITableView, controls, and buttons, you'll need to use the Size Inspector in Interface Builder. To control positioning, the Size Inspector uses the "springs and struts" metaphor: Views are locked to superviews (or not) based on the "struts" around the edge , and they expand or contract within their superview based on the "springs" on the inside of the rectangle. Click a strut or spring to enable it or disable it.

The first step in reocnfiguring your view is to set up the autosizing for the main UIView that contains all your subviews. This one's easy: Just enable every strut and spring. That ensures that each edge of the view stays a fixed distance from the corresponding edge of the superview (the application window) and changes its width or height as the window resizes.

I set up the UITableView in the picture the same way: Its top edge is a fixed distance from the top edge of the view (to make room for those other controls), and I want it to expand or shrink based on the containing view. It will expand to fill the width of the superview in landscape mode, and it will add height (and shrink its width) in portrait mode.

I wanted the button in the upper left to stay in the upper left, regardless of the orientation. In that case I enabled the strut on the left side and the strut on the top. I disabled every other strut and every spring. That ensures that the button doesn't change its size based on the orientation and that it stays in the upper left. Not surprisingly, I set up the add button in the upper right and the Today/All control next to it to be locked to the upper right corner, again without shrinking or growing.

A little bit of tinkering got all my views to look nice in either rotation. But I add my own custom views to the UIWindow object, and that is simply not working yet. The view pops out of the edge next to the home button, regardless of the phone's orientation, and it resizes in a sloppy way. When I figure that out, I'll post part 2.