Saturday, October 4, 2008
She had good things to say about this map (it's aesthetically pleasing, it's easy to use). But her biggest complaint was that she could not tell that a certain destination was going to be twice as far as the last one.
Not being one to take a challenge lying down, I thought about it. The map crams a lot of information into a fairly small space (the image above is reduced a lot). It is fairly information rich. What could be added to that map that would still preserve its aesthetics and simplicity?
How about we give up our preconception that every map has only one scale? (A scale is a ratio of say map miles to real inches of map distance.) What if a map had multiple scales? What if it had a variable scale? Could we present a solution that would service both users who want to get real distances and those who want relative?
Here is what I came up with. Suppose that we put tick marks on the tracks. Each tick mark would represent a distance (say 2 km). This would be true for the whole map. This would allow users to quickly eyeball a source and a destination and either visually compare or actually count the distance. Notice that the actual map inches for each tick is variable. Check out a small section that I blew up and modified.
I think the idea is ready for usability testing! ;-)
Friday, August 15, 2008
Maybe this works for your company, but it is a flawed process. By focusing on your existing product and thinking additively, you effectively warp your process into being tool-centric. The Next Great Release is only a few new features away. Developers think this way, product managers think this way, and existing customers think this way (potential customers may not).
So what exactly is wrong with this picture? Everyone is focused on the tool. It is a distraction from what is important, namely solving the user's problem. If you could really see how your tool is used by end users, you might notice that there is a lot of interaction between the user, the tool, and other things.
I'll call this workflow. It is the sequence of steps that the user is following in going from nothing to solution. It might involve using your tool multiple times in different ways. It might involve generating intermediate workproducts. It might involve interacting with others at certain points. Ultimately, it might be all this activity around your tool that determines its success, rat more than its feature set.
Workflow may not be prominent in all problem domains, but the more complex the domain, the more likely that workflow is significant. Consider my company's domain for example. We provide tools to allow technical people to work with network and server data, to build a models of their system, and to predict the behavior of the system under various loads.
One day one of our consultants passed by and proudly flopped a meaty document on my desk and informed me that he had finally codified a methodology to solve one of our users' most common modeling problems. It was a masterpiece at 90 pages, was well organized, was valuable to our users, and made an impressive sound hitting my desk.
In a later meeting, while developers and product managers argued about getting SAN support into our tools, I was still thinking about that sound. If the problem domain was that complex, surely we should be selling guidance to our users, right? And we couldn't ship a consultant in every box, could we?
In a sense, the methodology was a recipe, and arguably was as valuable as the tool. If we could productize it, users would see real value in a productivity boost. The analogy to a cooking recipe is apt. It has ingredients (preconditions), a step by step description of what to do (a process), and a view of the expected result. Users might choose different recipes, depending on what they are trying to do.
One of the most valuable things a recipe can do is to establish context. By knowing context, any support you give the user can be made more relevant. Maybe your user has filtered a network traffic report and it is empty. Is that an error condition? Maybe. Is there sage advice to offer them - only if you know what they are trying to do. If you build tools without context, in a way, you can only offer abstract options and abstract advice. It becomes much harder to embed domain knowledge in your tool.
Steps are the building blocks of recipes. Our product is composed of more than one application, and some steps control these other applications, launching them with the appropriate inputs and outputs when appropriate. Some kinds of steps generate workproducts. Some steps encompass critique of data or state, sometimes encompassing expert advice. Some steps allow declaration of data (like a list of server names). A lot of steps have fixed or parameterized functionality, but one type of step is very highly customizable in terms of both its behavior and its designable user interface.
Flow and Dependency
There is a concept of information flow involved in recipes. Since recipes have multiple steps and steps might have inputs and outputs, there is a flow among the steps. The inputs and outputs of each step are typed and the flow matches up by type. This brings up one of the strengths of this approach, namely the managing of dependencies. If a user makes a change farther up in the recipe, all downstream steps that share that flow are now out-of-date, meaning that the steps need to be executed again to bring their outputs up-to-date. As long as this out-of-date state is visible to users, it is a simple matter of making sure that required changes propagate correctly.
In our problem domain, users are making business decisions on modeling results, involving potentially millions of dollars. Confidence in the results is paramount, requiring an understanding of how those results were arrived at. If the results are unexpected, they need to work backwards in the flow to figure out where their expectations diverge from the results. Users might work backwards examining not only intermediate workproducts, but also look at assumptions along the way.
Consider this requirement in the context of a loop. Whether in a conventional programming language or a flow chart, a loop has a conditional, a loop body, and a loop terminator. There are undesirable characteristics of this representation. First, it assumes that the logic associated with the loop body is the same for each pass through the loop. When you consider that each pass might represent the analysis of a different set of data, and that the user might want to tweak each pass, the flow chart style logic is not flexible enough.
A way to represent this is to unroll the loop. That is, represent the loop body explicitly for each iteration of the loop. It takes more space to do this certainly, but it meets the traceability requirement and allows the user to modify each pass independently. There is also a dynamic reconfiguration aspect here. Maybe the loop is a pass for each test case in the collected data. So if the user adds a test case, a new series of steps might dynamically come into existence representing the new pass through the loop.
A final benefit in explicitly representing all steps required in a recipe, is that the user has a roadmap that tells them how far they need to go. They can tell how far they have come by a "done flag" that each step displays.
An easily overlooked issue with introducing workflow into your products involves business politics. You might have to champion a fairly sizable change to how you are going to spend your development dollars. If introducing workflow competes for the same resources that would be used to develop new features, you might meet resistance.
In my company, I started the sales pitch at the customer advisory council level. Being composed entirely of our biggest customers, the council readily bought into the concept. This should be expected, as users are the ones who ultimately pay the price for lack of workflow support through lost productivity.
Next up was an internal presentation that included developers, consultants, and product managers. The development staff was positive towards the idea. The product managers were uncertain about this; the workflow solution came out of some creative thinking in development, which is backwards from what they expected. The really interesting responses came from the consulting staff, who are effectively very advanced users. Most were favorable to the idea, but consultants have a history of being mavericks. As subject matter experts, each might have their own way of solving problems.
One consultant stood up in this meeting and gave the most negative response, saying something like "Tell me why I would ever use something like this. Why would we build this application?" I'm happy to say that the same consultant caught me in the hall about a year after the product was released and told me, "I don't know how I got along without this!"
I'd like to close this with an admission. To this day, I never have read every page of that original methodology. Just don't tell that consultant.
Thursday, August 7, 2008
Screen real estate is at a premium. The balance between being efficient and being rich without being cluttered is very narrow, and they have done a good job at the user interface.
One of the fun user interfaces involves scrolling through lists (think of artist/album lists). As a user, you think of pressing your finger on the list and flicking it in a direction. This sends the list rolling in the direction your finger directed. The fun thing is that the faster you flick, the faster the list scrolls. And the list has friction! Its velocity decays over time. And if you hit the end of the list, it kind of compresses a bit then rebounds, kind of like its made of rubber. I’m ashamed to admit that even after having the Touch a week, I still sometimes play around with flick-scrolling.
One thing that I ran into was the lack of tool tips. With a mouse-based interface, you can linger over items to get a hint to pop up as to the function of the widget. But with touch screens, there is no lingering. You press on a button with a finger. That’s it. I missed the ability to browse the functionality that tool tips provide. A possible compromise might be to have a tool tip pop up while the press down occurs. A user might move off a widget without releasing, hence restoring the viewing of tool tips without activating the widget.
Another slight surprise was how much your finger actually obscures. Apple did a good job of averaging a hotspot to represent the center point of your finger, so I rarely missed items, even as a newbie user. But your finger tip is quite large. When you click say on a small keyboard, or a small control, its nice to know what you hit. This happens with several forms of feedback. If you hit a lone control and pick your finger up, you often see the control glow for a couple of seconds, indicating that is was hit. This is a “nice touch” (sorry, I couldn’t resist). When clicking on a virtual keyboard, when you click the letter, a larger representation of that letter jumps up above your finger while it is pressed, allowing visual confirmation of your choice.
One of the really glitzy user interface features is controlling zooming. The Touch uses the Safari web browser. When you navigate to a page, you see the whole page (usually as you’d see it rendered on your computer screen) only shrunk down to fit the mobile screen. This makes actually using this sized page dubious. Most users will zoom in and then move around by dragging the screen with their finger tip. The zooming is what’s interesting. If you want to blow up a screen, you put two fingers on the screen and spread them out. The screen zooms bigger in real time in proportion to how much you spread your fingers. Zooming back out is the opposite; use two fingers and squeeze them together. Very, very slick. The obvious usability defect I ran into was that the zooming factor was not preserved when jumping to a new page. This means you keep having to zoom in every time you follow a link.
The Touch also has real orientation sensor. (Please pardon my printer jargon to follow.) If you are viewing a web page in portrait mode, and you rotate the Touch to landscape mode, the screen will reorient itself so you are no longer looking at it sideways! That one is a real crowd pleaser. Some applications take advantage of this; for example, the drawing programs allow you to erase a screen by shaking the Touch. Ah, that takes me back to the old Etch-a-sketch days. I ran into an interesting usability issue with this feature. I took the Touch to the gym, where I primarily listen to music (you know, to keep the old forty-something body going). The Touch would not deactivate the screen (to save power) because I was doing sit-ups, causing the screen to switch between portrait and landscape mode with each grunt of effort. Thankfully once it went into screen deactivate, no amount of sit-ups would reactivate the screen (there is a separate gesture to wake it up).
I guess the moral of the story is that even a multi-billion dollar company that thrives on slick user interfaces makes usability mistakes. The second moral of the story is that touch-based interfaces are a new challenge to those of us who create mouse-based applications. The final moral of the story is to go out and get an iPod Touch – now.
Friday, August 1, 2008
This pipeline can work well. But it is not perfect. As a pipeline, it is only as good as the information that is feeding it. In particular, missing information often results in software which may not meet the originally envisioned requirements. (Anyone who has had a brush with dealing with an outsourced team can appreciate this in spades.) One often neglected area concerns performance, particularly in user interfaces. Those who are developing web applications are less likely to suffer from this lack than those who are working on desktop client applications.
What might performance specification look like? This can take the form of a maximum time for a certain action, a minimum throughput specification (events per second), or a specification of expected volumes. These are typically lacking in most projects, or are injected very late in the development cycle, where the workable responses available to the development team are going to be limited. If you are unlucky, there are no performance requirements, and this lack causes you to choose an architecture that does not scale well.
To avoid this, you should try whenever possible to specify performance requirements in your SRS. It is unlikely that you’ll be able to find hard numbers in terms of time constraints. This is partly due to the cost of determining these (think of the time and expense of canvassing your customer base), but also human tolerance of delay is vague. If a dialog takes 500 milliseconds to come up, versus 200 milliseconds, is anyone really going to complain?
One easy specification to include should be the average and expected maximum sizes of things. Image your user interface includes a dialog that shows a list of items. The average and maximum length of that list should be specified; even a guess is better than nothing, but take care to get several considered opinions. In a product that I worked on, when I asked our subject matter expert what an average and maximum value for our list would be, I was told 7 and 12 (these were big abstract things in the list). Knowing that, we never saw any problematic performance during development. We knew that the implementation was probably n^2, but were unconcerned. Our QA stress test case was 30 items. Image our chagrin when handling a customer call where said customer had 600 items in their list. Trust me when I say that you do not want customers going in your product where your QA team has not.
Another easy specification is concerns response time and cancelling long operations. First, make sure that you never do real work in your event dispatch thread; this is the main thread that runs your user interface. Doing real work there means that your application becomes unresponsive. So your SRS should specify places that progress indicators should be used (a wait cursor, a status bar message, or a full blown progress dialog). This has the implication that at least one extra thread should be doing the real work in the background. If your user interface operation is expected to take more than a certain amount of time (say a handful of seconds), you should specify that it be cancellable by the user.
These sound like common sense, and for many practitioners they are. But in the press to get product out the door, try hard to avoid performance concerns from getting pushed back into the next release.
Tuesday, July 29, 2008
At this point in the riddle, you hear “what am I?” Yep, you guessed it – error messages. (This diatribe can be applied to warnings and informational messages too)
Error messages are a legitimate and primary facet to a user interface. We as product designers conceive of a products to solve a problem or perform a service to users. We strive to make our product feel intuitive and natural. We always end up asking our users to assume a manner of interaction with our program. But no matter how well we do, we designers never get a perfect score, for we do not live in the user’s world.
Expectations that our users have of our product may not be met, and the reasons may be numerous. Maybe we weren’t as good at conceptualizing as we thought. Maybe what we wanted to build was too expensive in effort or time. Maybe someone in the decision chain is deciding things they ought to delegate. Whatever the reason, when the user deviates enough from the Chosen Path, an error message is likely to ensue.
The primary down side of error messages is that they interrupt the flow of work that the user is orchestrating. The user’s momentum is broken and they are reminded that the product they are working with cannot read their mind, and that it may not fit very well into their problem space. The user’s focus moves from the getting real work done to focusing on the error. This often results in annoyance or even anxiety.
To help convey the user’s anxiety level to developers, I describe an informal Angst Temperature Scale. In this scale, the lowest, cooler end represents a user’s lack of anxiety when they are moving along smoothly through your product. If any warning message shows up, the scale goes to pale yellow. If any error message shows up, the scale shows intense yellow. If the user sees a sloppy, unhelpful, or confusing error, the scale temperature is orange. The first intrusion into red occurs when a product has a silent error, which often is accompanied by puzzling application behavior. The anxiety scale tops out at a sizzling red when a product has a crash, usually accompanied by loss of data.
So what is going on in a user’s head when they see an error message? The answer is captured in two simple questions: “what just happened to me” and “what can be done about this by me.” I like to call this Me-centricity. It is a concept that developers either fail to recognize or under-appreciate. After all, developers historically write the error messages for self-consumption, right? So how do we correct this sorry state?
Recognize that error messages play to many consumers. Each has its own needs, own expectations, and own world view. These players are developers, technical writers, technical support, training, and everyone else! (You’ve got to love the irony in this taxonomy.) Each needs something different from an error message.
Before we get much farther into how to correct things, let me digress into some real-world, commercial examples of message (with a commentary in parenthesis):
- Changes are not saved! (It would be really nice to know why)
- You changes have been saved! (A misspelling and why put this message up at all?)
- Your project name has been saved! (Hmmm, I wonder what happened to the rest of the project?)
- 16 >= 16 (I’m not making this up – this is a real error message)
- Confirm to cancel, continue? (This is my all time favorite)
That last one is a real winner. I think it really is a diabolical way to paralyze your user into a permanent state of indecision.
So let’s take a look at critiquing this error message from an application called Navigator. This message is so typical of what a developer might produce without careful consideration.
The following Navigator file had an unexpected version: myproject.npj
This error message is marginal at best. It raises more questions than it answers. A user might be asking these questions:
- What does a file represent in Navigator?
- What was the found version? Expected version?
- Why would I hit this problem?
- How do I get past this problem?
A totally cool, enlightened developer might produce instead the following error message. Note that the underlined items represent hyperlinks to more information for the user.
The Navigator project below cannot be opened because it is incompatible with the current version of Navigator.
Details – the project was created by Navigator 2.4 (with project version 1.1) while the current version of Navigator is 3.0 (with project version 1.2). A list of Navigator releases and corresponding project versions can be found here.
If you need more information, contact technical support at email@example.com or send this file as an attachment.
This version of the error message is far superior to the original by almost any measure you choose, except the effort to create it. But what rules do we follow in creating better error messages?
Let me introduce you to the Jedi Master’s Guide to Error Messages. This is mostly a common sense set of rules to follow:
- Watch out for typos – it looks really sloppy. You don’t want your user thinking that they were the first ones to ever see this message on display.
- Use clear language. There is nothing worse than a confusing error message. Well, I guess there are worse things, but not many.
- Avoid slang. Nuff said.
- Do not mix languages.
- Do not introduce new concepts. Do not refer to concepts in your messages that are not supported in the user interface.
- Do not introduce new terminology. This one is frequently violated. Use the same terminology that is used in your user interface. This needs to be consistent with help too. There is nothing worse than multiple names for the same thing.
- All messages must have a unique identifier. This helps users quickly look up an explanation in the help.
- Easy access to support information. This might take the form of hyperlinks.
- Support “sendability”. Screen dumps can work after a fashion, but it’d be more convenient if users can copy the text of an error message as text and forward it in email.
- Let users drill down to details. In other words, the first part of the error message should be clear and simple. It is targeted at the end user. Let more sophisticated users read more or actually expand more detail if they actually need to.
So what is actually impeding the creation of more usable error messages? There are two things to consider. The first is a lack of technical support. The second is a development process issue. On the technical side of things:
- Developers typically use simple functions to show simple strings.
- The use of property files (a common technique for handling internationalization issues) favors simple string messages.
- There is very little if any support for hyperlinks in error messages. Some of this could be addressed by moving to a richer expression, such as HTML.
- There is no email support. So users are rarely presented with options like directly contacting technical support.
On the process side of things, there usually is none. That is, there is rarely anything in the development process to support better usability of messages. Often the other stakeholders (other developers, technical support, training, etc.) do not even review the messages or do so in an ad hoc fashion.
I’d like to close with one final thought. When was the last time you saw a usability study that focused on error messages?
Monday, July 28, 2008
Actually it doesn't - I need one. This is my therapy for living in software development. Besides letting me vent, this will hopefully show things from unconventional angles. If you are not in software development yourself, you will likely get little from this blog. If you are a developer or a manager, help yourself to seconds.
I have been in the software business as a developer for over 20 years now, so I have my share of bumps, bruises, and most importantly, scars. From the mid to late nineties, I ran the C++ Tips website, which can still be found here. That site is mostly archival in purpose, but one of these days, I'll write some Perl and clean it up.