Archive for the 'Usability Design' Category

How not to design a menu

O2 Menu

I just got a 3G iPhone and signed in to the O2 website to take a peek at my account, only to be greeted by the menu you see here.

My, my, my..! :)

It's completely unscannable, with each line starting with the same prefix ("My"). As I try to scan it, my brain initially refuses to think that they're separate menu items. It runs contrary to my natural ability to distinguish patterns by homogenizing the visual appearance of each item.

Simply removing the "My" prefixes alone is a big step forward. That, and removing O2 from "O2 FAQs", leaves us with a much more scannable list:

My O2

  • Profile summary
  • Tariff & services
  • Allowance
  • Bill
  • Payment details
  • Recent charges
  • Orders
  • FAQs

Much less cognitive effort, much easier to scan.

They could have avoided this menu mishap completely if they'd read through Robert Hoekman, Jr.'s excellent new book, Designing the Moment. (And, yes, I'm very psyched that Robert's going to be speaking at Singularity!)

stu.pid.us password usability is.su.es

Hmm, I need to log in again to del.icio.us after clearing out my passwords. I wonder why my regular passwords don't work... oh well, time to start the forgotten password process.

Cool, got the email and now I'm on the site -- this should be simple:

Delicious password stupidity - screen 1

I enter a weak password -- this isn't too important an account after all. Submit.

Delicious password stupidity - screen 2

What's this? It's too short? Well why didn't you tell me on the first screen? Mumble, grumble... I type a longer password. Submit.

Delicious password stupidity - screen 3

Aaaaaaaaargh!!! You fool!

  1. Why does a simple social bookmarking service need such strong passwords?
  2. If you do need them, give people the criteria on the first screen!

This is how the form should look:
Delicious password screen alternative

I love you, del.icio.us -- please fix this!

The GAE SWF Project

The GAE SWF Project: Knowledge and tools to help you build Flash and Flex apps on Google App Engine

Today I'm releasing The GAE SWF Project, a resource of Flash and Flex-related knowledge specifically aimed at getting you up and running quickly with Google App Engine. If you want to skip all the details and start playing with it, skip to the Getting Started section.

Everyone else, read on!

When Google announced Google App Engine last week, I couldn't believe what I was hearing. It was as if someone had said, "Hey, Aral, tell us what your perfect development environment is and we'll build it for you."

In recent weeks, I had started playing with Python and Django and experimenting to see whether I could use it to build the web application for the Singularity web conference that I'm organizing at the end of October. Turns out that I could not have picked a better time to invest in learning Django and brushing up my Python as Google App Engine is heavily influenced by (and supports) Django and is written in Python.

A framework for the Singularity Conference

Singularity is shaping up to be a really great conference. I'm honored to have a constantly-expanding stellar line-up of speakers and yet the sessions are just one very important aspect of the conference. I find that you get as much out of your social interactions with speakers and other attendees at conferences as you do from the sessions. And Singularity is no exception.

The Singularity conference application is not something you will login to on October 24th and never visit again beyond October 26th. On the contrary, I plan to launching the application as early as possible and add features as we go so that we can start building the community around the conference. This is essential for the organization of the local conference hubs, for building friendships months in advance of the conference, and so that you can influence what the conference ultimately becomes (you do not have to attend the conference to join the online community.)

When I initially announced the Singularity conference two months ago, I stated in the About page that Singularity would have a "focus on open source, the community, and on giving back."

Today, I'm taking the first step towards delivering on that promise by releasing the initial underpinnings of a framework that will eventually power the Singularity conference web application. I present to you The GAE SWF Project.

The GAE SWF Project

The GAE SWF Project (hey, Google chose the name, I only provide the juvenile attempts at humor) is a resource of Flash and Flex-related knowledge specifically aimed at getting you up and running quickly with Google App Engine. The initial release contains a proof-of-concept Flash 9 client showcasing a pre-alpha version of The GAE SWF Framework. The framework is a very light-weight combination of Python and ActionScript 3 that uses some of the best open source components available today on the Flash Platform and Python ecosystem. It is inspired at its core by best practices and a pragmatic approach to application development.

The proof of concept (and, indeed, the whole project) specifically targets Google App Engine. This is by design. The framework is not a generic one (although, by all means, feel free to get inspired and port it if you wish). The dedicated focus is part of the appeal. It means that we can make things simpler.

There will be no abstraction for the sake of abstraction and no premature abstraction; the framework will evolve by encountering real-world problems and solving them.

Finally, keep in mind that you are viewing the fruits of three days of work at the moment (this, in itself, should be testament enough to how easy -- and fun -- Google App Engine makes development). It is early days but I feel that we've made a good start. I hope to hear your thoughts and feedback in the comments.

The Proof of Concept

The proof of concept is built on Google App Engine using Google's webapp framework.

It showcases several fundamental architectural considerations, the most important of which I've outlined for you below.

HTML and Flash in a tree...

You use handlers in app.yaml to host a mix of Flash and HTML content, including the Flash Remoting gateway, in a single Google App Engine app.

Embed Flash content using SWFObject

SWFObject is the way to embed Flash and Flex applications in your HTML. Use it. 'Nuff said.

Deep links

You implement deep linking using a combination of server-side Python and SWFAddress so that both SWFAddress-style and regular URLs are supported. Regular URLs are translated to SWFAddress-style hash/anchor URLs on the server.

Thus, both of the following URLs are valid ways to reach your profile page on the proof of concept Flash 9 client:

Regular URL:

http://gaeswf.appspot.com/examples/initial/profile

SWFAddress-style URL:

http://gaeswf.appspot.com/examples/initial/#/profile

Flash content that obeys browser text-size changes

Users with poor eyesight or in environments with reduced-visibility (such as bright sunshine outdoors) may want to increase the size of the text displayed in the browser. By default, Flash and Flex content does not react to these text-size changes. However, it is possible to make Flash content obey browser text-size changes and the proof of concept implements one such method that does not involve any alterations to the Flash app.

(You can read more about similar issues -- and see some juicy Flash myths debunked -- in my review of the talk I gave at Highland Fling this month titled Bare-naked Flash: Dispelling myths and building bridges.)

PyAMF

PyAMF is a Flash Remoting implementation for Python. It has a dedicated and responsive group of passionate developers working on it, led by Thijs Triemstra, Nick Joyce, and Arnar Birgisson. On Tuesday, the team released PyAMF 0.3 with support for Google App Engine.

The GAE SWF Framework uses PyAMF as a core component to communicate with the server and the various Google App Engine APIs. It is currently running PyAMF 0.3.

The PyAMF gateway is setup as a regular mapping, and mapped to /gateway in app.yaml.

Users API

You use the Google App Engine Users API to login and out of the Flash application. The current Flash 9 proof of concept implements one of three possible ways of handling logins (see the note in my earlier blog post about the other two ways.)

Intelligent forwarding after login

When you hit a deep link in the application without logging in, you are automatically forwarded to the link after you login. This is a behavior that you are accustomed to seeing (and expect) in HTML-based applications but I have rarely seen it implemented in Flash and Flex applications.

DataStore API

The Google App Engine DataStore is a massively scalable database based on Google's Bigtable (the same distributed database that powers their search and services like Google Earth).

The proof of concept has a profile section where you can fill in your name and a URL (the Users API currently does not provide your GAE app with the user's name, just their email address). This data is saved via PyAMF and the DataStore API.

(All server-side services are in the /services package.)

Client-side and server-side validation

The Profile Screen shows you how to implement two different types of validation: simple client-side validation and server-side validation.

The Name field performs simple client-side validation that stops the user from submitting the form without entering a name.

The URL field, on the other hand, actually hits the server and asks the DataStore to verify that the URL is valid. When you think about it, it makes sense to use server-side validation code to validate more complex data types using the exact same code that the DataStore API uses.

The user experience is managed via visual cues that are carefully scripted using the excellent KitchenSync AS3 sequencing library by Mims Wright. (Mims just added me as a project member so I can contribute a small update I blogged about earlier.)

(I'm still working on tweaking the timing of the type wait duration for firing the server-side validation code to make it as seamless as possible.)

As the framework develops, I know that the KitchenSync library is going to be an essential, core element, and I look forward to contributing back as much as I can to the project.

Mail API

The proof of concept also makes use of the Google App Engine Mail API to send email confirmations to your Google Accounts email address after you update your profile.

When initially working with this, I was searching for a simple way to monitor the mail that was being sent from the app. Although the Development Web Server allows you to specify an SMTP server when you start it, I couldn't get it to work with either GMail or my web host's mail server. And setting up sendmail or postfix was a pile of worms I didn't want to sample.

Instead, I found a simple, open source SMTP server written in Python that's perfect when developing locally with the Development Web Server. It's in The GAE SWF Project app that you can download. To start it, simply change to your The GAE SWF Project folder and type:

./monitor_mail

You will see all email sent from your application in the Terminal window. (Note: I run on a Mac and all the commands in this article are meant to be run in Terminal on OS X. You may need to tweak them slightly for your operating system of choice.)

CSS, etc.

I may introduce myself as a Flash Developer but that doesn't mean that I don't care about the rest of the web. With good friends like Andy Budd, Richard Rutter, Paul Annette, and Jeremy Keith living almost a baseball-bat-wave away from me, I'd be scared silly implementing a new site with anything less than pristine markup. So that's what I've strived for here and I hope I've at least come close. (I did use one <br/> tag, for which I feel very dirty indeed!)

Nearly all of the credit for the CSS goes to the excellent YUI Grids CSS library that Rob Knight clued me into via Twitter last week when I was battling with altering the K2 theme on Singularity to make it into a cross-browser three-column fluid layout.

(The scale9-esque fluid download cell is courtesy of the even more rounded corners with CSS technique.)

The HTML content is structured using several Django templates, which are supported by Google's webapp framework.

Finally, the Flash client uses the TabBar component from the open source Yahoo Astra Flash components and Uza's AS3 Global Object to implement several global convenience properties (like the current SWF's URL).

Getting Started

Getting started with The GAE SWF Project couldn't be easier.

1. Download and unzip

First off, download the Google App Engine SDK (includes the local Development Web Server and webapp framework.)

Next, download the latest release of the The GAE SWF Project and unzip it.

(Or, you can check out the unstable, bleeding-edge version from The GAE SWF Project Subversion repository's trunk on OSFlash.)

2. Start the server

Open up Terminal and navigate to the folder you unzipped The GAE SWF Project to. To start the Development Web Server type:

./start

This is a convenience script that I made that starts the Development Web Server and sets the mail server as localhost:5000. You can change these in the script of just use dev_appserver.py . to start it up without mail support.

If you want to monitor the email that gets sent, open up a separate Terminal window and, in The GAE SWF Project folder, type:

./monitor_mail

3. View the app and start hacking!

Now that the app is running, view it in the browser by hitting http://localhost:8080.

You can now open up the source folder and start exploring!

Trace you, trace me, trace it for always...

Wow, did I just paraphrase Lionel Richie?

Anyway, I find it useful to tail the Flash trace log (especially to see trace results in the browser and online). Here's how you do it:

Before you start, you need to enable logging by creating a file called mm.cfg in /Library/Application Support/Macromedia.

In it, enter:

ErrorReportingEnable=1
TraceOutputFileEnable=1

You only need to do this once. After that, whenever you want to tail the log, open up a new Terminal window and type the following, replacing USER with your home folder:

tail -f /Users/USER/Library/Preferences/Macromedia/Flash\ Player/Logs/flashlog.txt

Play, enjoy, share, have fun!

As I state on The GAE SWF Project site, I hope that this open source effort will help you to get started quickly with building Flash and Flex application on Google App Engine. In the past few days, I have had more fun developing this than I can remember in a long while. I love Python, I love Django, I love Google App Engine, and I love Flash and Flex. To have them all together... well, that's a dream toolset, right there!

And, there's something to be said about writing your app and then letting Google handle the rest. Personally, I can live with that.

(Oh yes, and I do desperately need to talk to someone at Google about hosting the Singularity conference web application on Google App Engine with regards to the quotas -- if you know whom I should contact, please either let me know directly at aral {at} aralbalkan(.)com or leave a comment below -- thanks!)

The GAE SWF Project is currently a proof-of-concept; it's a three-day old baby that I hope will blossom into a useful resource.

I hope you you enjoy it and I hope that it makes your life a little easier or at least gives you food for thought.

Play with it and let me know what you think in the comments.

Do you suffer from premature validation?

Seesmic Form Validation Error

It seems like everyone is getting form validation wrong.

Seesmic is a social vlogging app that's built in Flex and is currently in alpha testing. I got invited a few moments ago and went to sign up. On the site, I clicked in the First Name field and started to type. And stopped just as quickly, because, after the first letter, the field went red. Mousing over the error, I saw a message informing me that the First Name field must be greater than two characters long.

Ah.

You see, my name actually happens to be longer than two characters (though I guess my friend R Blank won't be signing up anytime soon) and I was in the process of typing it when I got distracted by the erroneous error message and stopped. Paradoxically, by stopping, I validated the error message's raison d'etre. Could it be that there are quantum mechanics at work here? :P

Seriously, though, as I've mentioned before, this is not the way to do form validation.

When implementing forms, you should Prevent, Not Scold. This is why validation is important. Validation is meant to prevent you from making mistakes instead of letting you make them and then scolding you about them.

However, implemented incorrectly, form validation can violate the Innocent Until Proven Guilty principle and present a usability anti-pattern, which I'm calling Scold Unfairly.

I remember a great example of Scold Unfairly (though not related to forms) in Windows XP a while ago. Before they changed the message, Windows would scold you quite harshly when it started up if you hadn't shut it down properly. Unfortunately, it would also do this when it crashed/Blue Screened. In other words, it would scold you for not shutting down properly when you hadn't done anything. Of course, this made Windows look quite dumb.

Similarly, you shouldn't Scold Unfairly when implementing form validation.

The ultimate no-no is to initially present a form to a user with all sorts of validation errors. Believe me, I've seen this done. The user hasn't done anything and thus could not possibly have made a mistake yet. Remember, the user is Innocent Until Proven Guilty.

One step up from that is scolding prematurely. No one likes premature validation. And it seems that Seesmic's form validation in this case gets a little too excited too quickly.

Technically, it is triggering the validation based on the wrong user gesture. Validation is tied to the text box's change event. Instead, it should be tied to the focusOut event so that it fires when the user leaves the field. Leaving the field is a strong indication that the user has finalized the contents of the field. It is the right time to carry out initial validation. Of course, the change event should still be listened for on fields that already have validation errors so that once the validation rule is met, the user is instantly notified and rewarded with the removal of the validation error.

For more details on how to properly implement validation in forms in general (but with examples specifically for Flex), take a look at the following resources:

zsoldout

Zsoldout: Bad usability in SXSW signup form

I'm trying to book a hotel for SXSW and I see that the Hampton Inn is available to Gold, Interactive, and Film registrants. I know Andy had told me that it was sold out so I'm feeling great (someone must have dropped out!) Not believing my luck, I give Andy a call to double-check that it's the same hotel then hastily hang up to finish my order before someone else gets it.

So, I click on the Bedding drop-down and see "zsoldout(3/7-3/11)"

zthanks!

zreallybadusability.

Better form validation in Flex

Flex comes with a built-in form validation system that unfortunately uses mystery meat tooltips to display component validation errors.

To see what I mean, take a look at the example I wrote a while back in the Validating Data Quick Start.

Mystery Meat Error Messages

If you tab around that example, you may notice that you are probably doing something wrong (as indicated by the red borders around the form items that begin to appear) but you have no idea what you're doing wrong. In order to find out, you have to mouse over the form field. Only then does a tooltip appear to tell you what the problem is.

Needless to say, having the user switch input devices and exert additional effort in order to see a form validation error does not make for good ergonomics or usability.

A better alternative is to actually display the error message beside the control.

You can, of course, do this simply by having the error message in a label.

For example:

<mx:FormItem label="Your name">
    <mx:HBox>
        <mx:TextInput id="yourName" change="validateNotEmptyTextInput(yourName);" focusOut="validateNotEmptyTextInput(yourName);"/>
        <mx:Label id="yourNameError" visible="false" text="Your name cannot be empty."/>
    </mx:HBox>
</mx:FormItem>

The validateNotEmptyTextInput() method, in this example, is not a Flex Validator (as used in my Validation Quick Start), but a simple method.

For example:

private function validateNotEmptyTextInput(target:TextInput):void
{
    (this[target.name+"Error"] as Label).visible = (target.text == "");
}

In the above example, I'm using a pragmatic naming convention to create a generic validation method that works with TextInput components. Nothing too spectacular visually, but usability-wise already better than the default Flex behavior.

Creating an error Label for each component, though, is not very practical. We can overcome this limitation and add a little visual flare by using the Flex error tooltip instead of a label.

Kyle Quevillon has a post in which he details how to use the Flex Tooltip Manager to create Error Tooltips. Referring to Kyle's post, we can alter the validateNotEmptyTextInput() method as follows:

// If the TextInput is empty, display an error message.
if (target.text == "")
{
    // Has the error message ToolTip already been created?
    // (A reference to created ToolTip instances is saved in a hash called errorMessageToolTips.)
    var toolTipExists:Boolean = errorMessageToolTips.hasOwnProperty(target.name);
 
    if (toolTipExists)
    {
        // Error message ToolTip has already been created, just show it.
        (errorMessages[target.name] as ToolTip).visible = true;
    }
    else
    {
        // Create the ToolTip instance.
        var pt:Point = new Point(target.x, target.y);
        pt = target.contentToGlobal(pt);
        var errorTip:ToolTip = ToolTipManager.createToolTip(errorMessages[target.name] + " cannot be empty", pt.x + target.width + 5, pt.y) as ToolTip;
        errorTip.setStyle("styleName", "errorTip");
 
        // Save a reference to the error message ToolTip in a hash for later use.
        errorMessages[target.name] = errorTip;
    }
}
else
{
    // TextInput is valid. Hide the error message if one exists.
    if (toolTipExists)
    {
        (errorMessageToolTips[target.name] as ToolTip).visible = false;
    }
}
 

Where errorMessages is a hash of personalized messages:

errorMessages =
{
    yourName: "Your name",
    yourEmail: "Your email",
    phone: "The phone number"
}

Thus, we no longer need the Label component but there is a catch: we still need the HBox (or a container of some sort) if the TextInput is in a FormItem. Otherwise, contentToGlobal() returns an incorrect value when trying to position the error message.

So the new FormItem looks something like this:

<mx:FormItem label="Your name">
    <mx:HBox>
        <mx:TextInput id="yourName" change="validateNotEmptyTextInput(yourName);" focusOut="validateNotEmptyTextInput(yourName);"/>
    </mx:HBox>
</mx:FormItem>

And the resulting validation errors both look nice and are functional.

Better Flex Validation Errors

(In the above example, I modified the errorTip style to make the message boxes slightly shorter than usual by setting the paddingTop and paddingBottom properties to 2.)

To summarize, I'm not a big fan of the mystery meat validation error tooltips in Flex. Displaying validation errors on the form itself leads to better usability as users do not have to exert additional effort to find out what they did incorrectly.

Update: Someone has filed a bug about this very issue in the public Flex Bug and Issue Management System. I've left a comment on the bug and linked it to this post.

Making captchas less annoying

I personally find captchas annoying. And most of them are completely inaccessible to people with visual problems. But if you find that you must implement a captcha, you can at least try and make it as painless as possible for the user to use.

First off, let's review what the purpose of a captcha is. A captcha aims to differentiate human beings from bots. As such, there is nothing more annoying than proving to a captcha that you are a human being by replying correctly to it only to be asked again and again when form validation fails for some other field.

So here's a pattern for captchas that should improve the usability of systems that employ them:

If the captcha is valid but form validation fails for some other reason, store the fact that the user is a human being as a cookie or on the server and don't present the captcha to the same user next time the same form is submitted. You can even go so far as to not present that user (based on IP/cookie/session) with captchas for other forms. If you're worried about spammers getting through, you can limit this to a specific period of time (ten minutes, an hour, a day, etc.)

Update: I just saw that Google's Blogger implements a similar pattern to what I describe here in their commenting system and doesn't keep presenting you with the captcha once it's reasonably sure that you're human. Good one, Google! :)

Do prescribed secure passwords really result in better security?

buzzword password error

I was excited to hear that Buzzword is in public beta so I tried to sign up this morning only to be greeted with an error message: "A password must be at least 6 characters, with at least one alphabetic and one non-alphabetic character."

It's not as bad a policy as some applications have (my favorite is "Your password must be between 6 and 8 characters long and must contain at least one number and at least one non-number, non-alphabetical character). Or, even worse still, I've actually seen an application that generated a password for me and then didn't give me the option of changing it (thankfully, I've only run into that train-wreck once).

These policies are bad because, whether we like it or not, most people use the same password (or several different ones) for different services. Yes, it's not ideal for security but it is the reality we are faced with. Given this, you can either let people use their existing passwords or dictate that they create a new one for your application. Whenever an application forces me to do this, I guarantee that I will forget this password. And what do most people do when they know they'll forget a password? That's right: they write it down somewhere. And how are most successful hack attacks carried out? You guessed it: through social engineering and by rummaging through offices and/or garbage bags for little pieces of paper with passwords on them.

That little yellow post-it that you just wrote your new eight character super strong Buzzword password on and stuck to your monitor at work is more of a security risk than the six character password you usually use for stuff that you have locked away safely in your head.

Update: I also just noticed that the Buzzword login page is being served over HTTP. Of course, they may be making an HTTPS call in the application but, if they're not, it means that your lovely strong password is open to everyone else on the network to see as it travels in clear text over the Internet.

Memo to the CEO in Edutech NTE Podcast

Pauline McNamara presents a 13 minute edit of my Memo to the CEO talk from last year's Flash on the Beach conference on the latest episode of the Edutech NTE Podcast. Listen to it here.

FOTB slides: Memo to the CEO

I've just put my slides up from my Memo to the CEO session at Flash on the Beach. Download them here (PDF, 3MB).

I thought about exporting QuickTime and Flash versions of the presentation too but, frankly, I couldn't justify it. The QuickTime version has all the bells and whistles of the transitions but it staggeringly large. The Flash version, well, let's just say I'm sure that Apple didn't cripple the Flash export on purpose but in terms of size (it's large) and performance (it doesn't have all the effects), it really doesn't make much sense. Again, I'm sure it's not a case of Apple favoring QuickTime over Flash! At the end of the day, the PDF version seems to be the best bet. It contains the information and is small. There you go, you just read a whole paragraph on why you've got my session slides in PDF format. Truly, could there have been a better way for you to spend the last thirty seconds. Thirty one. Thirty two! :P

While searching around for a picture to include in this post, I also found some reviews of my session. Here are some links:






Bad Behavior has blocked 0 access attempts in the last 7 days.