To Err Is Human (So Program Accordingly) (Harry's Code Class Newsletter)22 Apr, 2008
In Part 1 of a series, Harry offers some basic advice about error handling for Visual LISP and VBA programming.
Mastering the craft of programming is a path of interesting diversions. For example, as your programming evolves and you tackle increasingly complex tasks, you'll eventually face what many believe is the dark side of programming: error handling. This part of coding accomplishes nothing more than preventing your program from stopping unintentionally. In the worst case, your programming glitch might bring AutoCAD itself to a halt, but most of the time it will be your customization routine that stumbles and falls. This month and next, I'll introduce some programming concepts and tools for dealing with the unexpected in your code.
Prevention Is the Best Medicine
The best approach to error handling is to minimize the chance that errors will occur in the first place. My years of programming experience come in handy at this point. I have seen many errors and have observed how many programs are used. Let's start by taking a look at several of the most common sources of errors -- and how to prevent them.
User error. Most errors are the result of user input. When testing your code, you probably don't even read the prompts you created because, as the programmer, you know that you need to enter something that makes sense. Other users of your code might not be so careful. I've been amazed many times by a user who is confronted with a prompt, only to enter something completely off base. When asked why, the response is often something like, "Just to see what happens." That is just the user's nature. So, I advise you to set up your prompts with other users in mind. Anticipate wrong input, catch it at the source, and ask the user to try again or exit the program. In some cases I'll mix things up, perhaps allowing the user to enter stupid information for a few tries before exiting my program or putting it on hold until cleared by some authority.
System-related errors. The second big source of errors in routines is the system environment. Files might get moved and your program can't find them. Or a network outage occurs. Regardless, you can't assume your program will always locate a particular file or other needed resource. You must build in a checkpoint to verify that what you need exists, then proceed or exit gracefully.
Bad data. Another common source of program errors is bad data. Your routine might locate a needed file and start to read it without a problem, only to encounter a file format that has changed or has been corrupted outside your program control. (For example, your program might be set up to read a spreadsheet, but at some point that file was changed by a user and no longer contains the needed data.) In such cases, you probably need to exit with some sort of message that lets the user know things are not right in Program Land.
Unexpected circumstances. Finally, we have those strange and wonderful errors that result from the very chaos of complexity. You may have tested every possible permutation you could imagine, but once you release your program to the user community, you'd be quite surprised by what materializes. Odd cases not considered or special cases requiring special handling can result when dealing with anything that's complex or sports an open architecture. It's almost impossible to anticipate where these errors will occur, so you should always build in a general-purpose error handler to exit your program as gracefully as possible in the event of the unexpected.
The Graceful Exit
Just what is a graceful exit? As a rule of thumb, I recommend that any program encountering an error that halts processing should report the error to the operator quickly and clearly, undo any graphic manipulations, and clean up the program space. In other words, avoid annoying the user and leave the system the way you found it.
Report the error. Reporting the error is pretty easy using the existing tools of the Visual LISP and VBA programming interfaces. If your programming endeavors have led you to the point where error processing is of interest, you likely know how to issue a prompt. Some programmers use error code numbers that require either a decoder book or contact back to the programmer for correction. Others use cryptic error messages -- no different from a code number in my mind. Still others tell the life story of the program to date -- scaring the user by letting them know you are watching!
Because most users only report the last thing seen on the Command line or in a dialog box, I prefer to keep error messages brief and to the point. If the program is very complex, a simple message citing a code number, such as ?Error 09,? is easy for the user to remember and can point me right to the problem area. Whatever approach you take, you should always be consistent.
Offer the option to undo. When you're customizing AutoCAD, your applications normally carry out activities that modify graphics, which you might have to undo in the event of a program error. This is easy using the Undo marker feature available at the command level at the start of the programmatic manipulations. (If you have not used the Undo command in AutoCAD, the online help explains how to set and use markers.)
All you need to do is issue the Undo back to your designated Undo marker when cleaning up. I recommend placing the Undo marker at the point in the program code where you begin to change or add data, but not actually undo that work without user approval. Give the user that control by indicating in your error message that any work can be reversed by typing Undo if desired. That way, if the program prematurely exits but has created a lot of useful graphics, the user can preserve the work.
Clean up after yourself. The last step in the graceful exit is to clean up the program space. If you have defined a large number of global variables, then here is where they need to be reinitialized. The same holds true with AutoCAD system variables that may have been changed during the course of your program. Reinitializing the data and variables will allow the user to try again with a clean slate. Plus, users don't like it if you change the system variables they have meticulously set. Resetting object snaps, grids, pick box size, and so on will save your users a lot of time and frustration.
Next month, I'll dive into more specifics about error handling in Visual LISP and VBA programming. In the meantime, keep in mind that the best error handling is error prevention. Present clear prompts and dialog boxes to ensure the quality of input data and tighten up your input system with data checks for accuracy and validity, and you'll prevent the majority of errors.
Until next time, may your errors be few and caught quickly too! Keep on programmin'.