Properly Building Persistent Programs, Page 2
What Should You Persist?
I've already mentioned user preferences as a category of information that lends itself to persistence. Here are some other things that you should think about persisting in your next application:
- Transparent preferences. Sometimes user actions result in a change to the internal state of an application that it makes sense to persist. For example, if you allow the user to customize the toolbars in your application, they probably do so via drag-and-drop rather than through an Options dialog box. But even though they don't think of this as something to be saved, you should be smart enough to save the changes behind the scenes. The size and location of your application's main window is another example of a transparent preference that you might decide to persist.
- User history. Sometimes it makes sense to give the program some memory of what a user was doing when they last left the application. A weak form of this sort of persistence is the most recently used (MRU) list of documents you'll find in many document-centric applications. A stronger form is to simply open the last document that the user was working with automatically when they launch the application in the future.
- Logging with playback. Ordinarily, I don't consider logging or tracing of a program's actions to be a part of its persistence layer. That's because the log is normally not meant to be read, only written to. But there's a special case when you can consider logging as a form of persistence: when you offer playback. Imagine a complex graphics program that let you decide to suspend an editing session in progress without saving the changes to the image. You might log all keystrokes up to that point so that the user could return to where they left off.
- User limits. This is a case where permanent storage, even if the application is uninstalled and reinstalled, can make sense. The classic example is limits on shareware: if your application is designed to be used for thirty days without payment, you don't want the user to get another thirty days just by reinstalling it. In this case, you'll want to persist (and probably encrypt) the starting date somewhere. Note, though, that not removing your information from the computer at uninstallation time may violate the guidelines for various logo programs.
The Problems of Programming Persistence
After you've determined the information that your application will persist, there are two main implementation details to consider: where to persist information, and how to structure the persistence layer in the application.
- Is your application used by multiple users? Do you need to keep them from "stepping on each other" by overwriting persisted information?
- Is the information sensitive? Does it need to be encrypted to protect the user's privacy or security?
- Is your application already using a data store (such as a database) for other data storage? Can you leverage this to persist user information with minimal code?
- Is your application used by non-administrative users? Can these users open the store you've chosen?
- Is your application used by roaming users? Does your chosen data store roam with these users so that they get their preferences wherever they log on?
Whatever you choose, I urge you to make use of any persistence features built in to your operating system and coding environment. Don't reinvent the wheel if there are good facilities available. If you're working with Microsoft .NET, for example, take a look at the Isolated Storage feature, which automatically handles security and roaming issues for you across all of the supported Windows operating systems.
Finally, some advice on structuring your persistence layer:
- First, whatever you do, do create a persistence layer that presents an abstract view of persistence to your application, and hides the implementation details. This will allow you the freedom to change the underlying storage medium without rewriting the rest of the application.
- You'll usually want to read the persistent information at startup and write it out at shutdown. Be sure you take into account all code paths out of the application; if something goes wrong, and the application needs to exit abnormally, you should still persist information if possible.
- Always assume that the data isn't actually persisted when you're reading it in. That is, if the call to read the data fails for any reason, you should supply good defaults to the application.
- When you're running in debug mode, add checks to make sure that persisted information has reasonable values. This will help shake out bugs where you're saving the wrong information.
The Benefits of Proper Persistence
Why go through all this bother when you're designing a new application? The answer is simple: users expect applications to be intelligently persistent. Properly implementing persistence translates into an easier to use application with happier users. Ultimately that translates to either sales or job security (or both!) for the developer. Look at it this way: having an application without persistence is like going out to sleep every night at a hotel. The furniture is always in the same place when you get there, whether you like it or not. Wouldn't you rather sleep at home, where you've moved the couch and the bed to just the right spots, and they stay there when you're away? That's what persistence can do for your applications: make the user feel right at home.
About the Author
Mike Gunderloy is the author of over 20 books and numerous articles on development topics, and the lead developer for Larkware. Check out his MCAD 70-305, MCAD 70-306, and MCAD 70-310 Training Guides from Que Publishing. When he's not writing code, Mike putters in the garden on his farm in eastern Washington state.