Saturday, 16 January 2010
Error handling and solving has become a lost art. Over the last years the focus has shifted to delivering functionality rather than preventing errors. Hacks, hoaxes and viruses are some of the results, low-quality applications and user-unfriendly error messages are another
The reasons for this are simple. Increased business dynamics demanding quicker results, easier to understand programming languages lowering the threshold for programmers to code, ready-made reusable components available in increasing quantities and at decreasing cost are among the most important
It isn't that hard to write programs that never fail. Of course exceptions and errors will occur every now and then, but there's no reason to not catch them - which I describe as failing. I devised a simple, twofold mechanism that works in almost any programming language. I'm saying almost because I want to be careful, not because I've encountered a language in which it doesn't work
First, every function can only contain one parameter: The Object. That can be a real object, or an array, as long as it's passed by reference it doesn't matter. I'm just calling it The Object as it contains and does anything, and I will explain that.The Object will enable a function's return value to drive your transaction management and error handling, and retrieve new values returned by the function from The Object itself.
Also, this will make for very easy function reuse: if you add or remove a parameter, or make one optional or mandatory, you won't have to go through all function calls to change them all. This is really great if you have a lot of reusable functions in your application (which I hope is the case)
Second, thou shalt be pessimistic: reverse the conditions. This is not a new trick, but cetrtainly one that has completely disappeared as good practice. In fact, a functional design should tell what should happen in case a pre-condition isn't met, giving the more or less exact error message that should result from it.
In coding, this simply means that every if-statement should have an else-clause. To enhance legibility and prevent if-statement and else-clause from being pages apart, it is easier to say: if this condition is not met, then show this error message and quit
Third, there are errors and exceptions. Errors are exceptions you expect to happen, exceptions are unexpected exceptions. You know they will occur at some point between now and eternity, but have no clue which they will be. So, errors have to be handled, and exceptions trapped. When the functional designer does his job well he'll have predefined errors so these can just be coded. The programmer's job is then to trap exceptions, and collect as much information as possible about them. This can easily be achieved by storing the function's local variables at the moment an exception occurs. This can be done by assigning them to The Object used so they're still available once the function's exited
Of course the real power of The Object is that it contains all transaction information at any given point. It is one big container for all changes made by previously called functions, and it is almost as if you're running along with the business functionality, rules and exceptions while these are executed and met
The real beauty comes when an exception occurs, because the run-time value of each variable will be stored in it as well
Make sure to log all values of The Object when an error or exception occurs, and the need for error reproduction will vanish. There have been actually quite a few bugs caught in this way, proving without a doubt -code and log file in hand- that the behaviour encountered was not "as designed"
Sounds almost too easy, doesn't it? Any objections?