Fail Fast
I found this paper about "Failing Fast" while reading Paul Lockwood's blog. It refers to Martin Fowler's wiki about writing code to Fail Fast. This technique has been around for a while; however, I honestly have always been more of a proponent of writing defensive code.
However, after writing defensive code for years and reading this paper I am starting to rethink my approach. I am not saying that I am doing away with defensive coding. I still believe that writing defensive code makes very robust code; however, there are times when the Fail Fast technique makes sense. For example, I wrote a piece of code that stores some common lookup information in a cache on the server. The base code looks like this:
try
{
_leaseDuration = Convert.ToInt32( ConfigurationSettings.AppSettings[ _leaseDurationLookupKey ]);
if(_leaseDuration==0)_leaseDuration = __defaultLeaseDuration; <--( Defensive technique: Add this line of code)
}
catch
{
// an error occurred. this means that the lease property is not
// configured properly in the configuration file. so set it to
// its defalt value.
_leaseDuration = __defaultLeaseDuration; <-- This line of code would rarely get hit.
}
The issue is that Convert.ToInt32() will convert a null value to 0....and it is one of the reasons I typically advocate using Convert.ToXXX() methods over a simple cast. It is much more forgiving; however, it has a side-effect of masking potential issues. Following a Fail Fast technique I should opt to do a straight cast e.g.
_leaseDuration = (int)ConfigurationSettings.AppSettings[ _leaseDurationLookupKey ];
and then in my catch block, I should have thrown an exception as opposed to setting its default value.
In other words:
try
{
_leaseDuration = Convert.ToInt32( ConfigurationSettings.AppSettings[ _leaseDurationLookupKey ]); <--(Fail Fast Technique)
}
catch
{
throw new ConfigurationException ( "Could not lookup Lease Duration!!!" ); <--(Fail Fast Technique)
}
The question then arises, when to use which technique?. Some people would advocate using 1 versus the other always. However, I believe you must always be pragmatic and that being a purist is a form of dogma and doesn't always lead to the best overall solution. If you think about it, Defensive coding and Fail Fast are not mutually exclusive. Defensive coding means that you are evaluating different execution paths and handling accordingly. However, a pure defensive technique might be to force the code down a different execution path if certain situations occur, a Fail Fast technique would be to throw your hands up and state "fix the problem". The question you then ask, when do you fail fast?
- Configuration Data. If you don't get it right, Fail Fast and let everyone know.
- Retrieving data or you come across a condition that if it occurs you really have no idea what to do. In other words, when writing defensive code and you come across a situation that could occur and that if it does occur you are at a complete loss of what to do. The answer...Fail Fast.
- Others, still considering this....
Just a few thoughts,
-Mathew Nolton