This is based on working in the software world for quite some time, ranging from technical support to consulting to quality assurance to software engineering. And from observing people at every chance I get. While some things improve in software, some pesky things stay the same and repeat themselves whenever a new application is created.
Here’s my list of things that I think most software needs to get better at doing. Most of the examples will involve tapping on a touchscreen device, but are often applicable to clicking with a mouse or trackpad. They are in no particular order.
You may be uncoordinated, elderly, or an a train when you tap on your screen. Your finger may shift a bit when you tap just because that’s how your body works. There is typically a threshold of movement after which the tap is registered as gesture rather than a tap. Next time you tap on a button and it fails or you tap in a view and it scrolls instead of recognizing the tap, you may be hitting a tap tolerance issues. To test it, try the same action again but be very careful not to move your finger. One particularly common case is tapping on a row in a list, like you would to dive into a setting. If your finger tap starts and ends in a row, but you move your finger a tiny bit, it scrolls. Probably not what you wanted.
Tap target size
Imagine an interface where there are a number of buttons with ample space between them. Try tapping just outside the button itself and note that in many cases, nothing happens. Especially in interfaces that don’t have strongly delineated buttons, there should be some affordance for people that are tapping slightly off target. A good example of this is in a web browser. If there’s one link on a screenful of small text and I tap a link, but I’m off by enough that the browser thinks I’m tapping on the previous line, why not register that as a tap on a URL rather than doing nothing? Another example is an interface with one critical button like Play/Pause and nothing is around it. The target size should be as large as possible without intersecting with other interface elements.
Confusing responsiveness and performance
Everyone says they want better performance out of their devices. But raw speed is not necessarily what people actually want although speed helps. When a user taps or clicks or scrolls or swipes or pinches or zooms, it needs to be immediately clear that the device recognizes what the user did and is working on executing it. Often this comes out of the assumption that overall device perfomance will always be fast and get faster every year. But there could be network issues, resource issues on the device, or throttling to save battery life to name a few. Making something execute faster often doesn’t make it feel faster. The user likely paid good money for their device and it should react immediately. If an app launches in 2 seconds instead of 3, it feels slower if the tap on the icon produces no immediate visual response.
A special case of responsiveness is progress indication. If you tap a button and the interface immedatiely display the result of your tap, that’s great. But what if it leaves you staring blankly at your screen wondering what’s going to happen next? You don’t always know for certain how long an action is going to take, so inform the user that the device is working on it and it knows you asked it to do something. Immediately bring up a progress indicator or otherwise show that the . Even if the action ends up taking a short time, quickly fade the indicator out and display the result of the tap. Even though it could slightly slow down the action in some cases, the user will feel the device is more responsive. We’re talking about milliseconds here, so users likely won’t notice. Anecdotally, a quarter to a third of a second is about the limit of something that the user will perceive as responsive.
Obvious progress indication
Progress indication is great, but a little tiny spinner in the corner on a large display isn’t going to be noticed. If the button tapped on is going to bring a user to an entirely new screen, create an overlay with a large progress indicator in the middle and a Cancel button. If you can’t interact with the interface anymore, don’t make it look like you still can. Alternatively, put the progress indication near where the user initated it so they notice it. Or dim the screen and show a giant indicator in the middle. Also, don’t forget a cancel button (see next item). This is tied very closely to responsiveness. You don’t want a user to click a button and wonder if the device noticed it or not.
There really are very few cases where you’d want to prevent users from canceling any operation at any time. State should be kept track of for reverting easily. Don’t trap users in an interface they can’t get out of with a potentially indefinite end time. A determinate progress indicator can help, but it can also stall at 99% and leave the user stranded, potentially have to force quit your app.
Prominent tap indication
When you tap an interface element, the indication that you tapped on it shouldn’t just be a progress indicator. The tapped element should prominently indicate the tap was recognized. Again, this is a responsiveness issue.
Disabled interface elements
Sometimes user interface elements or an entire view will be disabled in some way and it will show as greyed out. Don’t make the user have to figure out why the interface is disabled and how to make it enabled again if that’s possible. For example, a disabled interface with a lock button somewhere else in the view is not obvious enough. Why not have clicking on the disabled element be the same as clicking on the lock icon? Even a tooltip to explain why something is disabled will help.
Interruption of active interaction
This is probably universally despised. Say you’re actively typing an email or moving the cursor and clicking on items on a desktop device. The current application or the system decides it wants to pop up an alert or another application jumps into the foreground. Suddenly your input is going where you didn’t want to go. There has to be some sort of heuristic that could be developed that would defer changing context until the user pauses their activity. If an alert pops up with a text field, part of the text you’re typing ends up in the alert! If it’s an informative alert, the device starts beeping at you. Only the user should be changing context. Logging into a desktop device that is launching lots of apps will often push windows from other apps on top of one you are actively using.Important information like passwords could be revealed to shoulder surfers as well.
Animations blocking input
If you want to tap on something before an animation has fully completed, the tap is typically ignored (although this has improved of late). Especially in the case of animations that fade out very slowly, it may ignore the tap even though, to the user, the animation is finished. Either the animation should change or some way to process or at least defer these taps until the interface is ready to receive them would be an improvement.
Buffering of keystrokes
When bringing up a new interface within an application or by launching an application, sometimes you are ready to type or press a keyboard shortcut before it is ready. The keystrokes typed before the interface is ready are lost. A simple example would be hitting Command-N to open a new document window and then typing. If the window is slow to appear, anything typed until it is ready is lost. This should be buffered and inserted when the interface is ready.
Making assumptions about networking
It sounds obvious to say, but not everyone has high-speed, low-latency networks to connect them to the internet. Whether it be cellular, Wi-fi, cable, or DSL, each network type is subject to local conditions, outages, upstream providers, and the server you are connecting to. Applications should never block a user interface while networking takes place unless it is absolutely required for the program to proceed. For example, if an app checks for an update on launch and that holds up launch or using the program, that’s something that should be done in the background. If eventually it is discovered that an update exists, then you can inform the user.
Appearance of data loss
When a user is creating, moving, and deleting data, it’s often unclear what stage you are in the process. Especially with critical data, you don’t want to be left wondering. For example, if you move files in an interface and they disappear from the source location but haven’t yet appeared in the destination, they will appear to be gone. This is not a comfortable feeling. Another example with email is sending a message. A sent message should go to the Outbox and then to the Sent folder. If at any point, the message is not in either, there is implied data loss. Inform the user where in the process their data is and always make sure it is visible somewhere.
Inform users of new features
Instead of forcing users to figure out how to turn off a new feature they don’t like, inform the user of the new feature and how it might be useful to them. And tell them how to turn it off if they don’t like it. Especially with critical productivity apps, you don’t want people to update an application and mess up their workflow with a new feature. Sell them on the new feature rather than force it on them.
When a new interface appears, such as a new window or alert, keyboard focus should be in a text field or equivalent. Don’t make users have to click or tap into a field to get started. Also, make your applications keyboard navigable!
Draw focus to critical blocking alerts
When there is a system-modal or application-modal alert, it can be very easy to miss, especially on a large screen. This leaves the user trying to type or click in the application they are using and getting beeps in return. Just like controls are disabled when they cannot be used, unusable areas of the screen should also take on a disabled look. If you simply cannot use anything on the system or anything in an application until you deal with an alert or sheet, guide the user’s focus to it.
Moving views unexpectedly
In some cases, views or item(s) within a view will move based on a user action that wasn’t supposed to cause this move to happen. For example, you may change the name of an item in a manually ordered list and it moves to the top or bottom of the list. Or you resize a window and the view that has focus moves out of view. Or a list you’ve manually scrolled changes position because new items are added or removed. Or you go to a new view and then go back, the previous view should not scroll to a different position or be different in any way.
Quitting with active alerts
When quitting an application where there is an active alert or sheet present typically requires you to deal with the alert before the quit is initiated. Unless it’s time sensitive or could lead to data loss, defer the alert until the next launch. Don’t ask whether to save a document, just save it. It’ll appear on next launch anyways. This last one has become less of a problem. In general, if someone quits an app, they want to be done with it immediately.
When deleting data, it should disappear from the user interface instantaneously. Deal with the actual deletion behind the scenes and if there is a failure, inform the user. Otherwise, the app feels sluggish and if the progress indication is weak or non-existent, showing the action happening quickly shows responsiveness to user actions. You also avoid users trying to delete something that’s already deleted, which could be a source of bugs or crashes.
Sometimes clever tricks are used to fake responsiveness and some are great, but some can lead to problems. The most common is to save a snapshot of an interface and then display that when the user returns to the application. This makes the app seem quick to return to its previous state. There are two significant problems with this. One, if the user tries to tap anywhere on the snapshot before it becomes live data, the tap is probably ignored. Secondly, for apps that have frequently updating data, you risk showing a user stale data that may not get refreshed until they have moved on to something else. Imagine checking a weather forecast quickly and seeing the old forecast and then you look away before it updates. This second case could be improved by clearly showing progress indication that the data is updating.
Sometimes a user will do something like create tags and end up with tags that have a space at the beginning or end. This can cause false duplicates to appear. In most cases, trimming whitespace at the beginning and end of strings is what you want to do when a user is naming things.
Never subject a user to case sensitivity in an application environment unless it is absolutely necessary. If a user tags something and uses a different case than was used before, now they’ve got two tags if case sensitivity is enforced. Searching data in nearly all cases should be case insensitive.
A plague on many users is having duplicate data. Whether it be songs or photos or documents or contacts, no one wants to waste their time pouring over duplicates. In some cases, they are close duplicates but not exact, which can lead to seeing the wrong version of a user’s data item. It’s a difficult problem, but allowing duplicates to even get created in an application in the first place is where the problem needs to be solved. If it’s not completely obvious it’s a duplicate, the user can also be prompted. Far better than them having to manually fix the mess later.
Wrap around interface
In a misguided attempt to make navigating a data set easier, some applications allow navigation to wrap around to the beginning when the end is reached. When reviewing a set of data from the beginning and navigating through it, this can lead you right back to the beginning without you even realizing it, especially in a large dataset. You may forget items near the beginning and think they are new. Collections of photos and documents and contacts have a beginning and an end and users can be confused by the appearance of data they already reviewed. The convenience of wrapping around doesn’t justify confusion. Imagine having a photo slideshow that always wrapped from the end to the beginning. Sure, it’s easier to tap Next on the last photo to go to the beginning, but is it worth not realizing you’ve already shown your whole slideshow?
Enabling buttons inappropriately
One example of this is in an interface where you are creating or editing an item. Typically you’ll see a Save or a Done button to tap. However, sometimes that button is already enabled and remains enabled after changing something and changing it back to what it was initially. This is the user’s indication that they have made a change and showing this in the incorrect state is misleading.
There’s been an explosion of new gestures over the years. But if you watch people use desktop and mobile devices, you’ll often see them inadvertently end up in modes that they don’t wish to be in or have no idea what they mean. They may not know how to get out of it and may never figure out how to disable them. Gestures should be added sparingly and heavily promoted to educate people on how to use them. Other gestures should be advanced features that are off by default. Surprises are nice when they are cool surprises. Discoverablility and stumbling upon something accidentally that you didn’t want aren’t the same thing.
Respect the basics
Every application can define a set of core functions that are critical to the app and used by nearly everyone. A bug in this core functionality should be treated as a Level 1 emergency even if no way is discovered to reproduce it. If you have a messaging client and on even rare occasions, messages that claim to be sent are lost, that should be treated with the utmost urgency. New features are great and it’s acceptable to have bugs in non-essential features, but there’s no excuse for bugs to be there in core features or for them not to be treated seriously. When working on an application, make a list of features that you must never break or that are taken seriously even if there is only one report.
While I’m sure some of these opinions aren’t shared by some people, I feel many of them will resonate by those that have thought about these things before. I hope that ten years from now, we’re not still deferring dealing with them at the expense of new features.