When You’re Done, You’re Only Halfway Done
You’ve just checked in your code, given it a version number and are about to send it to QA, but wait, are you sure you are done?
Sometimes when I use a new whizbang program, only to find it lacks some things which every useful program should have. It is easy, especially when building a complex program with unique functionality, to focus entirely on the unique offering of the program. While an enormous amount of time should be put into differentiating a program, there are certain features that users now expect in order to get the highest performance out of any program, and if a program is missing these features, they will stop using the program. I’ve built a list of 11 things which I consider essential if a program is to be considered non-trivial.
- Auto Recovery – If your program crashes, or the user shuts down his computer without cleanly exiting, your program should be saving his work at all times in a temporary work file. If an unclean exit happens, when he comes back into the program you should ask him if he’d like to resume where he left off.
- Undo – Changes should be reversible wherever possible.
- Redo – Undos should be undoable!
- Logs – Important information that doesn’t warrant an error message but might help the user out. I run into a lot of need for this with Android applications that just don’t work, but have no error messages. Like an RSS reader that just won’t update, and there’s no reason given why. I chalk this up to programmers not using exceptions and thus having functions fail where they don’t bother checking the error code returned.
- Scriptability – If your program’s functions can be automated it greatly enhances its usefulness. In fact, letting its features be scripted makes automating tests for it easier is worth the effort just for that alone. This means your program, even if it has a graphical interface, should be driven by commands or functions behind the scenes. The graphical interface merely invokes those commands. If you have these commands defined, it is very easy to add a complete scripting capability to your program with a language called “Lua”.
- Export/Import/Serialization – Any data your program uses should be exportable and importable. For example, I have a webcam application on Android and it takes a long time to manually enter the 12 or so webcams I monitor. I used to have to manually do this every time I reset my phone, or tablet. Entering full URLS, usernames, passwords, camera types on an Android device was a real hassle until the programmer added a way to export and import the configuration. Now it’s easy to reload all the cams. Most programs need this anyway just to save work the user has done. As a multiple computer user, there are programs I had to stop using because there was no way to share data and configuration between different copies of the program I was using on different computers. The main reason I use Chrome as my browser is, I’m a multiple computer user and the only way “bookmarks” would work for me is if the various machines I used could all import and export my bookmarks, but Chrome syncs across every machine I use automatically.
- Export/Import Formats – your import and export capabilities should support different formats, at least each of the following 1) Pure text for humans to read directly 2) A self defining format such as JSON or XML to the exported data can be directly consumed by other computers and 3) XML or JSON should be reversible, meaning, the file I export, must be useable later to import all that data back into the program.
- XML and JSON Formatting – There are some music editing programs that don’t save their data as XML or JSON. Because of this, no collaboration is possible. There is no way to “merge” work done on the same song from two different computers. If the song data were saved in line oriented, xml, merge would be possible.
- Fully Implemented Drag and Drop – One of my pet peeves is that Graphical User Interface Drag and Drop is never implemented completely. Developers pick and choose what is going to work with “Drag and Drop” so there is no universal standard and thus, every new program you use doesn’t work the same. Here’s an example, open Windows File Explorer. Drag a drive onto “Open” in the toolbar. A simple and very primitive operation: Nothing, nada, zip. Over the past 20 years people have just learned to accept this half implemented way of doing D&D and doing it right has been completely forgotten.The APIs and operating systems should enforce the programmer adding handlers for every object that is in the same screen (container), like C++ pure virtual functions, the code must not compile until the developer has added a handler for every other type of object that could be dragged and dropped onto this object and inversely every object this object could be dropped upon. Without that discipline, drag and drop can never be the primary interface because it cannot be relied upon to always be there, and thus we will never have “Minority Report” user interfaces.That may sound like an impossible amount of work, but with Object Oriented Programming you could subclass your object from a generic class “Opener” for example that already has Drag and Drop functionality working for anything derived from class “File System” for example. Until someone comes up with a user interface development system that does this, all GUIs are frauds.
- Pluggable User Interface – The backend logic should be separated from the User Interface. This makes your program much more powerful. I’ve worked on several big projects where, in the end, the User Interface the company thought was all cool and flashy, turned out to be meaningless (and obsolete by the time it was finished) and the big customers wanted to interact with the software using their own software via a web services type of interface. “We have our own Software, we just want to access yours from within ours”. That is a common request and if you can do that, suddenly your program becomes more than an App, it becomes an operating system for its operational domain. It’s a way for other developers to interact with your domain, a “Hardware Abstraction Layer” where the “Hardware” is the real world like Process Control, or Accounting, or Cashier Queue Management at Whole Foods. With an operating system like this, crowdsourcing will get you all the User Interfaces you will even want.
- Command Line Options – Every program should have command line options, even if it’s a graphical program. This makes it useable in batch files, i.e., it can do automated tasks. Granted, command line options will probably provide a very limited automation capability (unless you provided a scripting language) but if you put the most commonly needed commands in the command line, it goes a long way.
Next time you build a program, go through this checklist to make sure you are building from the ground up to meet the expectations that users have about the features and interface for a positive user experience.