Saturday, 16 January 2010

Failsafe application development: everyone can do it


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?

2 reacties:

Lee Provoost said...

Good points. Espcially the basics around errors/exceptions seem to be not fully understood by all devs I have noticed.

I'm not completely sure whether the one parameter per function makes sense all the times. In functional programming for instance, it's a very powerful construct where you have as a parameter that is a functional call, which return results is used as the other parameter for that function.

Also it needs to make sense to wrap all the parameters in 1 object. If you have to pass student details, then it makes sense to put it all in a student object to pass it around. However, if thre is other non-student data involved, one might end up with several monster objects that contains the whole world. Although you could argue that this is a bad function design in the first place :)

Martijn Linssen said...

Thank you Lee! We've indeed come to the point that not even the basics are understood by all...

In what you call functional programing, what do you do when the first function fails, thus returning unpredictable results? Shouldn't you handle errors at the very moment they occur? Otherwise, you'll get the "a friend of my sister's boyfriend's mother..." situation where you have a result in hand, and have no clue of the circumstances that led to it

I agree on the "motherload object", but you can also assign other objects to The Object. I just want to keep it generic: walk through the object, and if there's a sub-object that's fine. Just don't go to deep

I'm ATM writing another post on the rest, to work out my rationale

Post a Comment

Thank you for sharing your thoughts! Copy your comment before signing in...