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

4 Comments

  • I agree on the configuration data. The last thing you want is a misconfigured system that you discover long after the system has been up and running that it's using say a default userid because someone mistyped it in a config file. But then I wonder about any data in the system. I mean, if a Domain Object is only valid if it has context (say a Customer object) then loading data from a store should also be written using a Fail Fast approach.



    If a Customer isn't valid without a name then it shouldn't default to any value. Reading a Customer from a database say, the only default values should be when you create a new one but then that would be in the UI where your users are entering the information.



    So is there a condition where would you not use this techique? I guess the drawback is now you've got assertions all over the place which bothers me.



    I guess the question would be that it depends on the situation but there could be a few situations where you do want default values rather than ignoring a problem and moving on. For a defensive approach maybe it makes sense to consider Fail Fast First (FFF programming, now there's a new one) and fallback if your condition doesn't meet a set of criteria.

  • The config file example is a great example of when defaulting or leaving values as null can be a royal PITA trying to track down unexpected behavior. I saw a good deal of this on my last project.



    Live Real time systems are be obvious example of when we should always use defaults. Doing a moon landing? Fail fast would tell us what the problem was, but taxpayers may have wish we had least tried to land their multi-million dollar craft :) While testing such systems I would still be tempted to ignore defaults and fail fast instead (via a compiler directive).



    Assertions are another related technique, but used by too few coders. Yesterday was the first day on my new project I was delighted to see them being used... not sure about the GUIDs as surrogate PKs (clustered too!), but that is another blog post.

  • Guids....i have used them in the past; however, they only make sense when the record you are maintaining must be unique across more than 1 system....but even then...using them as a primary key is suspect at best.



    -Mathew

  • Fail Fast and Defensive codes are all resonable in certain case.

Comments have been disabled for this content.