CocoaHeads Silicon Valley at Apple on Thursday, April 17, 2008
[info]chanson
The next CocoaHeads Silicon Valley meeting will be on Thursday, April 17, 2008 — that's tonight! — at 7:30 in the De Anza 3 auditorium at Apple. That's just inside the south side of De Anza 3, right across Mariani Avenue from Apple's Infinite Loop campus in Cupertino. See the web site for directions.

This month's presentation is all about designing and implementing your human interface. User experience and human interface design are critical for Mac OS X software to get right. To that end, there's even going to be a UI makeover as Scott describes in his post on the meeting!

Thanks a ton to Scott Stevenson, Steve Zyszkiewicz, Michael Jurewitz and Joar Wingfors for organizing!

In general, at a CocoaHeads meeting we do some introductions, have a presentation including Q&A time with the presenter, and then have an open Q&A and demo-your-cool-app period. After the meeting there's more independent mingling and discussion until it's time to go at 9:30. Often a subset of the meeting moves to BJ's Brewhouse in Cupertino, which is right in front of the Apple Infinite Loop campus on De Anza Boulevard.

OLPC chat bug (and fix)
[info]chanson
One thing that became apparent as I tried out the collaboration features is that there's a bug in the Chat activity on the OLPC. As you chat, it will continually scroll to the end. It's very easy to fix though, just follow the directions here.

Furthermore, if you actually take a look at the fixed chat.py you can see a little bit of what goes into an Activity in Sugar, the OLPC human interface and high-level software stack.

Unit testing Cocoa user interfaces: Cocoa Bindings
[info]chanson
About a year ago, I wrote about unit testing target-action connections for Cocoa user interfaces. That covers the traditional mechanism by which user interfaces have typically been constructed in Cocoa since the NeXTstep days. However, with the release of Mac OS X 10.3 Panther we've had a newer interface technology available — Cocoa bindings — which has presented some interesting application design and testing challenges.

Among other hurdles, to properly use Cocoa bindings in your own applications, you need to ensure that the code you write properly supports key-value coding and key-value observing. However, since the release of Mac OS X 10.4 Tiger, the necessary APIs have been available to easily do test-driven development of your application's use of Cocoa bindings, following a trust, but verify approach. (It's also been quite easy from the start to test your support for key-value coding and key-value observing, to ensure that your code meets the necessary prerequisites for supporting bindings. I can write more on this topic in another post if anyone is interested.)

The key to writing unit tests for Cocoa bindings is the -infoForBinding: method in AppKit's NSKeyValueBindingCreation informal protocol. Using this simple method, you can interrogate any object that has a binding for all of the information about that binding! It simply returns a dictionary with three keys:
  1. NSObservedObjectKey, which is the object that the binding is bound to;
  2. NSObservedKeyPathKey, which is the key path that is bound — in Interface Builder terms, this is the controller key path combined with the model key path, with a dot in between them; and
  3. NSOptionsKey, which is a dictionary of additional binding options unique to the binding. These are all of those additional checkboxes and pop-ups in the Interface Builder bindings inspector for setting things like a value transformer.
By specifying what this dictionary should contain for a particular binding, you can describe the binding itself and thus start doing test-driven development of your Cocoa bindings-based user interface. Note that all of the system-supported binding names — as well as the binding option names — are specified in <AppKit/NSKeyValueBinding.h> and are documented, too!

Let's take a simple example, like the one in last year's target-action example, of a window controller whose window has a static text field in it. The field should have its value bound to the name of a person through an object controller for that person. Assume that I've already created the test case and set up some internal methods on my window controller to refer to the contents of the window via outlets, and to load the window (without displaying it) in -setUp just like in the target-action example.

First, to see that my text field has a value binding, I might write something like this:
- (void)testPersonNameFieldHasValueBinding {
    NSTextField *personNameField = [_windowController personNameField];

    NSDictionary *valueBindingInfo = [personNameField infoForBinding:NSValueBinding];
    STAssertNotNil(valueBindingInfo,
        @"The person name field's value should be bound.");
}
Of course, this tells us nothing about how the binding should be configured, so it needs some fleshing out...

Let's check the object and key path for the binding.
- (void)testPersonNameFieldHasValueBinding {
    NSTextField *personNameField = [_windowController personNameField];

    NSDictionary *valueBindingInfo = [personNameField infoForBinding:NSValueBinding];
    STAssertNotNil(valueBindingInfo,
        @"The person name field's value should be bound.");

    NSObjectController *personController = [_windowController personController];
    STAssertEquals([valueBindingInfo objectForKey:NSObservedObjectKey], personController,
        @"The person name field should be bound to the person controller.");

    STAssertEqualObjects([valueBindingInfo objectForKey:NSObservedKeyPathKey], @"name",
        @"The person name field's value should be bound to the 'name' key.");
}
Not very exciting, and a little verbose, but it'll easily lead us through what needs to be set up in Interface Builder for this binding to work. If you want to cut down the verbosity, you can of course extract a method to do the basic checking...
- (BOOL)object:(id)object shouldHaveBinding:(NSString *)binding
            to:(id)boundObject throughKeyPath:(NSString *)keyPath
{
    NSDictionary *info = [object infoForBinding:binding];

    return ([info objectForKey:NSObservedObjectKey] == boundObject)
            && [[info objectForKey:NSObservedKeyPathKey] isEqualToString:keyPath];
}

- (void)testPersonNameFieldHasValueBinding {
    NSTextField *personNameField = [_windowController personNameField];
    NSObjectController *personController = [_windowController personController];
    
    STAssertTrue([self object:personNameField shouldHaveBinding:NSValue
                           to:personController throughKeyPath:@"name"],
    @"Bind person name field's value to the person controller's 'name' key path.");
}
If you're writing code that needs, say, a value transformer, it's a simple matter to extend this model to also check that the correct value transformer class name is specified for the NSValueTransformerNameBindingOption key in the binding options dictionary returned for NSOptionsKey.

You can even extract these kinds of checks into your own subclass of SenTestCase that you use as the basis for all of your application test cases. This will let you write very concise specifications for how your user interface should be wired to the rest of the code, that you can use to just walk through Interface Builder and connect things together — as well as use to ensure that you don't break it accidentally by making changes to other items in Interface Builder.

This is the real power of test-driven development when combined with Cocoa: Because you can trust that the framework will do the right thing as long as it's set up right, you simply need to write tests that specify how your application's interface should be set up. You don't need to figure out how to create events manually, push them through the run loop or through the window's -sendEvent: method, how to deal with showing or not showing the window during tests, or anything like that. Just ensure that your user interface is wired up correctly and Cocoa will take care of the rest.

Twitterrific!
[info]chanson
Thanks to Khoi Vinh, I actually see the interestingness in Twitter now! It's all because of his post Writing and Sizing Twitter:
Twitterific puts a persistent kind of ‘heads up display’ right on your Mac OS X screen so that your friends’ posts are immediately available, and that you can easily add new posts yourself. No more having to load the Web site, or remembering to visit that tab in your browser where you’ve got Twitter.com running.
So it's really Twitterrific from Iconfactory that I have to thank for using it, because they've put a reasonable user experience atop it.

Anyone who wants to send me a friend request should go to http://twitter.com/eschaton. And be prepared for mutual friendingness.

User Experience Radar: More radar charts!
[info]chanson
Peter Morville was obviously thinking along the same lines a few years ago as I've been lately with the axes of usability. His User Experience Honeycomb model is another way of quantifying the usability of an interface, this time along seven axes:
  • Useful
  • Usable
  • Desirable
  • Findable
  • Accessible
  • Credible
  • Valuable
As Morville describes in User Experience Radar, Erez Kikin-Gil has taken Morville's approach and built a radar chart schema around it that he calls, appropriately, the UX Radar.

Perhaps the coolest thing about Kikin-Gil's design is that he doesn't just show it, he actually provides tools for it! Specifically, he has a downloadable Excel spreadsheet that you can use to create your own such charts very easily. You can even create a chart with multiple data sets and see them overlaid in different colors! This will let you compare multiple products, multiple designs, multiple measurements from different test users, etc. very easily. Check it out!

One Billion Buttons Please
[info]chanson
Lost Garden, One Billion Buttons Please: Should we build features for experts of newbies?
Tonight's stream of thought kept returning to the question: What level of expertise should we target with our product feature? On one hand, web savvy designers swim in a warm sea of learned gurus preaching the religion of simplicity; how it entrances new users, increases our reachable audience and leads to happier customers. At the exact same time our expert users, the ones paying the bills, are screaming for cybernetic time travel juggernaut creation tools complete with one billion intricately labeled switches.
Danc's Lost Garden is a great weblog for anyone interested in human interface design and the creation of complex but easy-to-use applications. (And since I work on an IDE, I fall pretty solidly into that category.) He gets the tension that you have to deal with right above — you must support the expert users because they're the ones who rely on your product the most, but at the same time you must create something approachable for new and casual users that neither abandons them on their way to becoming expert users nor reserves its power only for those who work hard to obtain it.

He follows an approach similar to the one suggested by Kathy Sierra and Dan Russel of Creating Passionate Users. He breaks down users' approach to software into three levels of mastery that correspond to feature sets and skill levels among the users: Intro, expert, and meta. To me this seems like another good use for radar charts in product design; if you have a way to produce them automatically, you can start listing and categorizing your feature set along the three axes (in addition to the three axes of usability that I've talked about) and break it up according to who it's intended to serve. This will let you determine whether you're achieving the right balance in your product given your target market, and what you might want to change if you aren't.

Also, don't miss Danc's great article on the Nintendo Wii Help Cat, which is easily the most innovative and engaging "tip of the day" system I've ever heard of.

IndieHIG
[info]chanson
IndieHIG is a project to put together human interface guidelines by and for small third-party ("indie") Mac developers creating innovative, useful applications.

The work is being done on the IndieHIG Wiki and is being reported via the IndieHIG Blog. It's always really interesting to see what elements of the Mac OS X user experience a project like IndieHIG tackles, and the process by which the participants decide on what to do and how to accomplish it.

I just hope nobody forgets about Uli Kusterer's mac-gui-dev Mac User Experience Development mailing list. If you're an indie Mac developer and you're looking for human interface ideas or feedback, be sure to join. It has a pretty sizable, interesting, and skilled membership.

Interaction design and the three axes of usability
[info]chanson
I've been doing a bit of reading about interaction design lately. Two of the books I've read recently are Designing for Interaction by Dan Saffer and Interaction Design for Complex Problem Solving by Barbara Mirel.

Saffer's book is a very light, easy read that covers the gist of interaction design, its applicability to different problem areas, and some details about the various processes and issues involved in actually doing interaction design work. It felt like a miniature survey course on ID, rather than an introductory textbook. And I think it worked very well as that.

Mirel's book, on the other hand, is all about the detailed process of creating software for high-end professional users who need to work in very open-ended ways. In other words, it's all about pro apps for pro users. It has quite good coverage of just what the needs of pro users are, generally speaking, how they approach their work versus novice or intermediate users, and what their software scalability needs are. The big problem with Mirel's book is its academic tone; it's both dense and wordy at the same time, and while there's a ton of good information in it, it's presented in a very hard-to-digest fashion. Mirel's content and Saffer's writing would be a killer combination.

A third book I've read recently is User Stories Applied by Mike Cohn. In addition to a lot of useful information on how to actually structure user stories and their creation, it also has a great overview of user role modeling. User role modeling can be treated as a sort of lightweight persona creation, where user roles are personas are whittled down to their bare necessities.  You may not care about where a particular user role's wife went to grade school, but you'll definitely care about what a particular type of user that you're targeting wants to accomplish with the software and the typical background of that user when you design for them.

When combined with user role modeling, the most important concept from Mirel's book — distinguishing between ease of learning, ease of use, and usefulness — shows a lot of promise as a way to guide the development of an application's user experience. You can consider each one of these a single axis of usability: Ease of learning is all about how intuitable the application is, and whether the application can be learned systematically. Ease of use on the other hand covers how straightforward it is to perform a particular task within the conceptual framework of the application. Finally, usefulness describes how achievable a task is with the application, without going through contortions or otherwise working around the software.

When you combine the above with user role modeling, you get an easy way to do score your features with respect to how your anticipated users will see them. For example, you can say that for user role A, feature 1 scores (2, 3, 5) indicating that despite being somewhat hard to learn and moderately hard to use, it's incredibly useful for users in role A. But for user role B, that same feature may score (1, 2, 2) indicating that it's really hard to learn, pretty hard to use, and not very useful to boot. Then you just need to judge the relative importance of different user roles to your product, and you can get a pretty good idea of where and how to polish your features. For easy visualization, just imagine each score as a simple three-spoke spider graph or radar chart.

Office 2007 UI Bible
[info]chanson
Jensen Harris is "Group Program Manager of the Microsoft Office User Experience Team" (About Jensen Harris). As a result, he posts a lot of interesting stuff about the Office user interface to his weblog.

Patrick Schmid has collected links to a ton of these posts into an Office 2007 UI Bible, which Jensen reprinted.

If you want to see some of the philosophy, design, and development process behind the Office 2007 user interface, it's a great place to look.

The Design of Everyday Games
[info]chanson
Tea Leaves, The Design of Everyday Games
I've been playing a lot of Advance Wars lately. It is a perfect little gem of a game, and I'd like to use it to make some points about good game design.

Good game design increase richness, but eliminates complexity. Good game design emphasizes content over form. And, all things being equal, good game design favors mainstream technology over the cutting edge.
Read this. Peter's advice isn't just for game designers — everyone designing software can benefit from it.

Unit testing Cocoa user interfaces: Target-Action
[info]chanson
It's really great to see that a lot of people are adopting unit testing for their projects and dramatically improving their quality. Test-driven development and agile development methodologies built around it are really taking off. However, a lot of people still feel that their user interface is difficult to test through code, and either requires a capture-playback tool or requires a different design approach based heavily on interfaces/protocols to get right.

In last year's post Trust, but verify. I tried to dispel some of the mystery of testing your application's user interface when using the Cocoa frameworks. However, I've still had a lot of (entirely well-justified!) requests for examples of how to put it into practice. So here's a simple example of what I'd do to write a unit test for a button in a window that's supposed to perform some action.

First, when implementing my window, I'd follow the standard Cocoa pattern of having a custom NSWindowController subclass to manage my window. This window controller will have an outlet connected to each of the views in the window, and will also wind up with a private accessor method — used only within the class and any subclasses, and in testing — for getting the value of each of its outlets. This design flows naturally from the test which I would write to specify that the window should contain a button. First, here's the skeleton into which I'd put tests:
// TestMyWindow.h

#import <SenTestingKit/SenTestingKit.h>

@class MyWindowController;

@interface TestMyWindow : SenTestCase {
    MyWindowController *_windowController;
    NSWindow *_window;
}
@end

// TestMyWindow.m

#import "TestMyWindow.h"
#import "MyWindowController_Private.h"

@implementation TestMyWindow

- (void)setUp {
    // MyWindowController knows its nib name and
    // invokes -initWithWindowNibName: in -init
    _windowController = [[MyWindowController alloc] init];

    // Load the window, but don't show it.
    _window = [_windowController window];
}

- (void)tearDown {
    [_windowController release];
    _window = nil; // owned by _windowController
}

@end
That's the infrastructure into which I'd put my other test methods for this window. For example, I'll want to specify the nib name for the window controller and ensure that it actually knows its window:
- (void)testNibName {
    STAssertEqualObjects([_windowController windowNibName], @"MyWindow",
      @"The nib for this window should be MyWindow.nib");
}

- (void)testWindowLoading {
    STAssertNotNil(_window,
      @"The window should be connected to the window controller.");
}
Now let's check that I have a "Do Something" button in the window, and that it sends an action directly to the window controller.
- (void)testDoSomethingButton {
    // _doSomethingButton is a private method that returns the button
    // conected to the doSomethingButton outlet
    NSButton *doSomethingButton = [_windowController _doSomethingButton];
    
    STAssertNotNil(doSomethingButton,
      @"The window should have a 'Do something' button.");
    
    STAssertEqualObjects([doSomethingButton title], @"Do Something",
      @"The button should be titled accordingly.");

    STAssertEquals([doSomethingButton action], @selector(doSomething:),
      @"The button should send -doSomething: to its target.");

    STAssertEquals([doSomethingButton target], _windowController,
      @"The button should send its action to the window controller.");
}
You'll notice something I'm not doing in the above: I'm not simulating interaction with the interface. This is the core of the trust, but verify approach to unit testing of your user interface.

I can trust that as long as I verify everything is hooked up properly that Cocoa will cause the button to send its action message to its target — whether it's a specific object or, if the target is nil, the responder chain — whenever the button is clicked while it's enabled and not hidden. I don't need to simulate a user event, and I don't even need to display the interface while running the unit tests. All I need to do is inspect, through code, that everything is wired up correctly.

Note that I can do way more than the above in testing my interface design, too. For example, I can ensure that the control layout is correct according to what my interface designer has specified, by checking bounding rectangles for example. But testing only the functionality of my interface has significant advantages, too. For example, it doesn't matter if I wind up using a custom kind of button to achieve exactly the kind of look and feel or behavior I need. It doesn't matter if I wind up changing the layout in response to feedback. No matter what I do, I'll know that functionality won't accidentally break while I'm messing around in Interface Builder — even if I completely rip out my interface and replace it with a new one!

This approach can also be used for testing Cocoa bindings using the -infoForBinding: method that was introduced in Mac OS X 10.4 Tiger. I hope to write up a post soon on how to approach Cocoa bindings using these same techniques, but it should be fairly straightforward given the above and the above documentation.

Update: I've struck through the check of the button's title above, because you may or may not want to do that. For example, if you're primarily running your unit tests against your development localization, you may want to put it in. But if you want to run your unit tests against a localized build of your application, you'll probably want to avoid checking a localized title against an English string. A "have your cake and eat it too" strategy might be to keep a variable somewhere in your application that can be used to selectively disable checks of only localized strings.

Update July 7, 2007: I've finally written a post, Unit testing Cocoa user interfaces: Cocoa bindings, on how to write tests for Cocoa bindings. Now there's no excuse for not doing test-driven development of your Cocoa user interfaces!

Aperture
[info]chanson
I've started playing with Aperture and I have to say it's really sweet.

I only have a four-year-old Canon PowerShot S110 (2Mpixel, pocket camera, only supports JPEG) so I'm not shooting in a raw format and I'm not shooting very large images. But it runs nicely on my 1.67 GHz PowerBook, requires very little disk space to itself since I only installed the app, and if nothing else provides me many more interesting organizational options than iPhoto.

What I'm most interested in is exploring Aperture's human interface design, data organization, and workflow structures. It's a tool designed for a specific set of professionals who perform specific sets of tasks, but with a lot of flexibility in mind too.

Open Source Human Interface Design
[info]chanson
Peter Trudelle, Shall We Dance? Ten Lessons Learned from Netscape's Flirtation with Open Source UI Development (CHI 2002 - Getting to Know You) We wound up spending longer getting requirements in the form of bug reports, and doing design by accretion, backout and rework. Don't let rushed coders drive things, design the product. [via Joel on Software]

I don't agree with Joel that it's impossible to do good design with a geographically distributed team. I think it's entirely possible for distributed collaboration to work. The big problem with Mozilla was too many cooks spoiling the broth; everyone thought they were a human interface expert, and everyone had different goals, and everyone pushed as hard as they possibly could to achieve their goals. A small, tightly focused team would have done just fine, even if they were distributed.

I really, honestly believe in the effectiveness of distributed collaboration, when it's done properly. But trying to do human interface design with in an open and ever-changing and questionably-qualified group doesn't sound like a recipe for success.

Slashdot on Ars Technica on Mozilla
[info]chanson
In this article on Slashdot, there's a very clear expression of the Open Source community's continued lack of clue when it comes to interface design:
The major detractor was the user interface, since it didn't feel like a Windows application. This was probably due to a poor understanding by the authors of XUL. (Emphasis added.)

Uh, no. An application running on Windows should look and feel and act like a Windows application. An application running on a Macintosh should look and feel and act like a Macintosh application. Saying "if you have a problem with the way it works, you must not understand it" is just insane. Then again, Open Source advocates tend to do this any time you have any issues with anything in their domain: "You don't like it? You must not understand it! Here, let me explain it to you in great detail!"