Back To The Exceptions
By Adrian Sutton
Benjamin finally got back to our discussion about exceptions. The summary there is a pretty accurate picture of my viewpoint and the history of the debate.
It seems Benjamin doesn’t like the fact that python throws exceptions when stuff goes wrong:
Fine. An exception is thrown. I don’t catch it. I get a stack trace on the command-line, and everyone’s happy right?
No. The pygtk main loop catches it, reports it, and keeps running.
While all of Benjamin’s experience says that at this point the application should die in case the state is invalid, all my experience is telling me the opposite. The fact is that in most GUI-based applications, each operation is fairly atomic and starts with the user doing something in the GUI. So when a user wants to insert a list into a document, they click the list button and the software performs the operation. If something goes wrong in that process and an exception is thrown all the way out of the application (up to pygtk in this case), the application shouldn’t exit because the error can easily be recovered from by performing an undo (if that’s even necessary). My experience is that about 90% of errors can be recovered from in that manner. That is the software totally fails to deal with the exception, but because the undo code is well built, it maintains a snapshot of a known good state from before the operation and can restore it easily at any time without significant fear of things going wrong.
Undo in this case is a faster version of killing off the process and starting a new one from the last save state – assuming you save after each operation. Which leads to the next interesting part of the discussion – why doesn’t software save everything automatically, all the time?
Well, there are a couple of reasons I can think of:
- It’s not the way users expect to interact with software.
- It requires the application to build in persistent version control (OSs should provide this support to applications but none do).
- Not all data is saved, a lot of data is just processed.
- Not all applications have a place to save.
Reason 1 doesn’t really stack up too well because I’m pretty certain would get used to it and eventually really like it. HyperCard works like this – it constantly saves and it’s a really nice feature but it does cause confusion and a fair bit of grief from time to time. The grief comes in when the user does something stupid and it’s automatically saved. To avoid this we also have to have perfect, unlimited and persistent undo/redo operations which are all too often lacking in applications (when was the last time you undid a command in bash? Adding a friend in MSN? When have you ever undone a software install?).
This is obviously leading into reason 2. Version control is hard. Making sure absolutely every operation in your application can be undone is also hard in a lot of cases (fortunately it’s pretty simple for HTML editors). Currently the user is left to manage the version control because the computer isn’t smart enough to get it right reliably. That can probably be changed now but in most cases it will require OS support to get it right. For instance, if I have a HTML document, the undo/redo information can’t be persisted in the document and there’s no way to clearly identify the document other than it’s file path. So at the moment you could persist the undo/redo state only if the file path remained constant and if the user moved or copied the file the undo/redo would be lost. Worse than that, what happens if the user edits the file in a different application?
Reason 3 seems non-obvious but it’s more common than you think. This web form I’m typing into is a good example. I create the entry in my editor and click submit – the data goes off to the server and is manipulated according to a set of rules and templates and finally the result of that manipulation is stored. The document I’m working on now will cease to exist when I submit.
Another example is the "scratch pad" I keep open a lot. It’s a plain text file that I paste stuff into so I have a place to store it temporarily. If my text editor automatically saved everything I put into it, I’d have millions of crappy, useless text files cluttering up my system. I’d never be able to find the one I wanted if I had to go through them anyway and they’d make searching my file system much more difficult.
Reason 4 is one that’s close to home. I write a software component. It gets used in a huge range of places – many that I couldn’t have imagined when the component was being designed and written. In this particular case, my HTML editor component is sitting in a web page. So where should it save it’s data to after every operation? It could round-trip to the server and store the content there but that would require our customers to implement complex code to handle the version control and recover the data when required (how does the server know when the data needs to be recovered?). In this particular applet I could save the file to disk but how do I know when it’s safe to delete that file to clear out the disk space again? Last time our applet accidently left files lying around I wound up with hundreds of thousands of files in my temp directory and it took nearly an hour to delete them all. How does the applet know when to recover the data? In some situations there are answers to these problems but not always and they certainly make the problem much more difficult than it seems on the surface.
Having said all of that – automatic saving and data recovery needs to be implemented in a lot more places. The other AJ points out a number of cases that would probably be easy to implement and very effective for the user. Browsers saving the list of open tabs and history for those tabs is the best example there – you can’t screw up the users data by saving at a bad time and it’s exceptionally convenient for the user to have things restore correctly. I’m not so worried about the OS remembering which applications I had open but it certainly wouldn’t hurt.