Problem: Progress bars never seem to accurately reflect progress
Solution: “Am I done yet” custom form control for developers. Just tell the control how far you are through the operation (e.g. step 5 of 20), and the control will tell you what proportion of the way through the entire operation you are time-wise (e.g. 50%). You can then use this to update a progress bar which really does show chronological progress.
I know what you’re thinking. How does it work? Well, you’ll be glad to know that I’ve already worked all that out. The control knows how far you are through the operation because it sends all your data to our web service, which has a huge database of previous results for that same operation and can therefore tell how long there is left based upon data from previous instances of the same operation. When the first guy goes through your install routine the control has no idea how long each of the stages take but, when the ten thousandth guy goes through it, the control can tell him with reasonable certainty that he’s got another three minutes left, because that’s what it took the other ten thousand people.
Examples always make things easier, so let’s say the application we’re going to create a progress bar for does three things:
- Copy three zip files from the current folder to a temp folder on your C drive
- Unpack those zip files into a program folder on your C drive
- Create 100 registry entries
While it’s doing this, the application shows a userform on the screen with a progress bar on it. We’ll use this nifty new “Am I done yet” control to make that progress bar show accurate percentage numbers.
First, the developer needs to get an ID for his application. Let’s imagine he gets that from our web site or something.
Secondly, the developer needs to think of what the various steps are in his task. It might be her, I suppose. But, let’s be honest, it’s probably his. In the task above, I’d say the steps are:
1. Copy file 1
2. Copy file 2
3. Copy file 3
4. Unpack file 1
5. Unpack file 2
6. Unpack file 3
7. Create registry entry 1
8. Create registry entry 2
…
105. Create registry entry 99
106. Create registry entry 100
These steps obviously don’t take the same amount of time. That’s fine. If they did, the developer wouldn’t really need this nice new thing.
Finally, the developer needs to add an instance of our AmIDoneYet control onto his form and call it when necessary. This control has one method:
void AnnounceProgress(int id, int stepnumber)
id is the ID he got from our web site. stepnumber is, well, the step number. I think these argument names are well-chosen. The developer must call AnnounceProgress whenever he hits one of these steps. The control has one single event:
UpdateStatus(double proportionthrough)
Inside this event, the developer will update his percentage bar.
Hopefully you can see what happens here – when the developer calls AnnounceProgress the id, the step number and the current time will be sent to our web service. That web service will look at previous data from the same task and establish how far the user is through time-wise, and return that as a proportion. When that data comes back, the UpdateStatus event will fire and the developer can update his percentage bar. Of course, the UpdateStatus event doesn’t only have to fire when the developer calls AnnounceProgress. Let’s say that file 2 in our example is much larger than the others – our control knows from the historical data that step 2 takes a long time, so it will fire the UpdateStatus event a few times during that file copy just to update the progress bar and show the user that something’s still going on.
I know what you’re thinking now. Why not just fire one AnnounceProgres at the beginning of the entire operation, and one at the end? The web service will know how long the entire operation normally takes anyway, so the progress bar will steadily update all through your install. Well, as a developer you certainly could do that but you’d miss out on the nattiest feature of our service.
[Drum roll]
In our case study above, certain things are likely to take the same amount of time on all computers. Creating the registry entries, for example, is going to be pretty much the same. But there could be a huge difference in the time that the first stage (copying the files to a local drive) takes – perhaps they’re already on a local drive, or perhaps they’re on a network. Perhaps they’re on a wireless network.
Our web service will be able to deal with this by splitting clients down into profiles. As more and more data gets collected, similar patterns will develop in certain situations. The people on a wireless network will take ages over steps 1-3, but will be just the same speed as everyone else for steps 4-106. Once you’ve taken a while for step 1, the web service can determine that you’re probably one of those wireless guys, and give you the appropriate time estimates for the rest of the progress based on the experiences of other users who took a long time on step 1. Steps 4-6 probably use a lot of memory – if those slow to a crawl, you’re probably one of those guys who are running low on memory, so your expected completion time will be profiled accordingly. Perhaps you’re running on remote desktop and the animations the developer chose to show during install are slowing the whole thing down – after a few steps, the control can realise that for some reason a bunch of people ended up on this super-slow install path and, because your profile matches those, show an appropriate time estimate.
Of course, the web service doesn’t actually know that you’re on wireless or you’re out of memory or that the developer choose poor animation – it just knows from the data that a bunch of people went slow on this particular step and you’re probably one of them.
To get all of this wonderful data, all the developer needs to do is pepper his code with step updates. The more steps he puts in and the more times a user installs his app, the more accurate the estimates will turn out. Eventually there will be enough data to profile every eventuality, and the progress bar will show perfect time estimates even if you’re connected to the internet with a modem, are running out of memory and have a hard disk that writes ten times faster than it reads.
Of course, there’s a lot of work that has to be done. The profiling of use cases is by no means simple. There would also have to be some sort of offline story, where the app came with a bundle of standard profiling data which would suffice on most occasions. And the web service has to be smart enough to discard the data from the guy who put his laptop to sleep halfway through and resumed it again the following day.
This all may look like too much thought dedicated to something that’s not really of much importance – do we really care that the “sending/recieving mail” bar in Outlook doesn’t exactly scroll linearly? Does anyone really sit and wait for their World of Warcraft to be patched? Well, one of the ways that computing is headed is towards “happier” user experiences and higher levels of trustworthiness in interaction. The iPhone is a great example of this – Apple opted for a slightly reduced feature set and a lower level of customisation but they concentrated their efforts on nailing those features perfectly and building a feel-good environment around those features and making the way in which the user interacts with them feel intuitive. This is just one of many areas in which we should strive to make the user believe what the computer is telling them. We don’t wait outside to the “one hour drycleaning” store wondering whether our drycleaning is going to take three minutes or four hours. We don’t stand anxiously next to the door of the train all through a 40-minute train ride, just in case it finishes in ten. We accept what we were told, and go and do something useful instead.
Installing this is going to take twenty minutes. Honestly. There’s no point in you sitting here waiting for it. Why not tidy the spare room?