The Constant Handler
Posted in Error Handling, Programming, Work on October 27th, 2009 by andrewWe are starting a new project at work. It is always an exciting time because you get to take what you have learned recently and apply it to something fresh. You don’t have to work around the scar tissue from past patches and additions. You don’t have to work with that Frankenproject on which your company relies. Finally, you get to build something from the ground up and do it right this time.
For our new project the one thing we want to be very serious about is error handling. This is something that gets overlooked far too often in the early stages of software development and always creates problems later during testing. Most programmers have had to do battle with the error message that reads “Unexpected fatal error” or “Stack trace unavailable”. They are the worst because they not only don’t tell you where the problem occurred in the sometimes muddy river of references you have, but they also don’t give you a clue as to what failed.So here is what we think will really get the job done and also do a good job of informing us to problems later.
Identify Errors at the Source
So often is development, especially .NET development, it is easy for programmers to handle the errors they receive at the top of the event chain. We click a button that performs actions, so we put a try/catch around the event and inform the user to any errors that may occur during the process. But what does that do for us? We don’t really know where or why the error occurred. We only know that it happened whilst we tried to perform some action. So we tell the user there was an error while trying to do “A” and to try again.
But what if we were to go to the root of each process and handle the error there? we might really be able to do something! Let’s take an SQL command for example. Perhaps we have a button that searches a database for the purchase history of a customer. There are many things that could go wrong, but let’s look at just a few scenarios.
- The customer information you used to search returns no results.
- The information you use returns multiple results (assuming this is not good
- Some other error occurs during the query (timeout or something)
In case one, we can handle the error very easily if we return a defined error code to our client software telling it that no results were found. So now instead of “Error retrieving customer data” we get “No customer data found for these criteria”. Much more explanatory for both the user and the programmer. Case two is the same. In this case, it would tell the programmer that somehow, multiple customers with the same identification are coming up in queries designed to only find one. This would que the DBA to resolve the data conflict and the programmer to find out how it got into the database. In the third case, we have at least eliminated two other things it could have been. As we expand on our error handling, it allows us to better service the user and ourselves. That brings us to our next topic.
Handle Error at the Source
The other problem with handling errors at the top level is that you really don’t get a good chance to try and salvage proper operation without having the user know something is wrong. There are many cases where software could recover from an error without even having to tell the user something happened. For instance, let’s say we have a specialized print system that takes in printing requests for an entire company and distributes them out to printers in a certain manner. If a request comes in and the printer we are targeting is busy, there will be an error. However, if we handle the error at the low level, we can just tell the process to chill out while the printer finishes what it is doing and try again. In this way, we are able to provide a success state for our user without having to tell them that something went wrong. Why should they care that the printer queue was full?
The other way it helps us is to compartmentalize our code. If we can stop errors from propagating upwards through the call stack, we can eliminate the need to handle errors from class libraries to which we may or may not have code access. If I write a static class that will handle user identification, I can build into that class error handling so that it can intelligently depending on the error that is received. In this way, the calling class doesn’t have to worry about handling errors from class that aren’t expected. And, in any case, errors that could be passed out of the class definition should be conveyed in some manner to the programmer. Again I encourage programmers to think long and hard about what could possibly go wrong in their software and to plan for the worst. The more detailed your error messages are, the easier it is for you to fix the problem later.
Mother Tested
Not to be stereotypical, but it is true that most mothers are terrible at using computers. However, we should never underestimate their value at breaking things. If you think your program is iron-clad, let your mother, or other technically-inept acquaintance have a go at it. I guarantee they will find some input for a field that will make your program bed for mercy. Of course, this person doesn’t even need to be someone that is going to use the software. In fact, it is better that way, because they will then have a blank point of view for the situation. They won’t know what to expect or how it works. In this way, they won’t come into testing with an idea of what to do and, consequently, shall make the most grievous of mistakes.
Well, I am very tired, but thank you for reading and leave me a comment if you ever need it.