Saturday, 6 March 2010

Do You Seek Permission or Forgiveness?

I attended a python dojo at dev8D last week and a conversation ensued regarding type checking within a function. As python is loosely typed and dynamic, any object could be passed into pretty much any function. A question was asked about whether a function should check for the type it was going to use prior to actually using it. It was not deemed to be “Pythonic” to check the types but rather to ensure adequate exception handling is in place in case of,well…. an exception!

I thought about this for a while and wondered if this notion could be applied to my own programming. Consider the following method:

   1: public static void DisplayNameAndTitle(Person p) 
   2:        {
   3:          Console.WriteLine("{0} {1} {2}", p.Title, p.GivenName, p.FamilyName);
   4:        }

Obviously, all we’re doing here is writing out to the console the title, first and surname of an imaginary person object. Our method only contains the essence of what we want the method to do and it would be great if that was all it had to contain but we have to think and code a little more defensively than that! So what could possibly go wrong in our little example that means we’ve got to consider adding more code to our method?  Our main concern should be that the person object doesn’t actually equate to anything, so maybe we should check it exists before we try to use it:

   1: public static void DisplayNameAndTitle(Person p) 
   2:       {
   3:           if (p != null)
   4:           {
   5:               Console.WriteLine("{0} {1} {2}", p.Title, p.GivenName, p.FamilyName);
   6:           }          
   7:       }

By carrying out a null check on the person object before using it, we’re almost seeking permission before we use it. We’re certainly placing ceremonial code before the essence. This seems a bit smelly if you ask me. We’re checking for a null value every time the method runs, adding processing overhead to the method even when everything’s “peachy”.

   1: public static void DisplayNameAndTitle(Person p)
   2:    {
   3:        try
   4:        {
   5:            Console.WriteLine("{0} {1} {2}", p.Title, p.GivenName, p.FamilyName);
   6:        }
   7:        catch (NullReferenceException)
   8:        {
   9:            // runs when the Person object, or one of its properties is null
  10:        }
  11:        catch (Exception)
  12:        {
  13:            // runs when any other exception occurs
  14:            throw;
  15:        }
  16:    }

By using a try/catch statement, we can let the essence run with sooner, but seek forgiveness  and run the “ceremonial code” only runs when something goes wrong.

Although the examples in this post have centred around dealing with null references, any scenario could have been used.

I didn’t really have a strong view regarding this matter but having thought it through, I’m going seek forgiveness from now on and hopefully will be able to produce some even more “concise essence”, with an apology always on stand-by…!

9 comments:

  1. Actually, I don’t think it’s quite as simple as this. Making a rule that says “I’ll always do it this way” is not good practice IMHO. This is much more of a case-by-case judgment call.

    In this case, for example, you really need to consider 1) how the method is being used, and 2) how “likely” it is that the Person object you’re passing in will actually be null, and 3) where best to actually handle the exception.

    If the Person object comes from client code in which the programmer must pass it in explicitly, then the possibility that the programmer will forget to check null on his end might be quite high. In that case, doing the null check is better. This is because the process of handling an exception is rather costly in terms of performance. Therefore, in this case, null checking is actually much more performant overall, because no exceptions are being thrown.

    On the other hand, if the Person object comes from, say, a configuration setting, database, a static property, or whatever, where there is very low probability that p will be null, then it is better to catch the NullReferenceException. That is because in nearly all cases, the null check would be superfluous; therefore, bypassing it will be more performant overall.

    Finally, let’s consider the case where this method is part of a reusable framework. In that case, you wouldn’t want to handle the exception at all, but rather do a null check and throw a new ArgumentNullException back to the caller if p == null.

    So, you see, this topic is much more “fuzzy” than it may appear at first glance.

    I explain a lot of this in my blog post from last year:

    http://leedumond.com/blog/defensive-programming-or-why-exception-handling-is-like-car-insurance/

    I won’t even get into this issues raised by the last catch(Exception) block you included, except to point out this:

    http://leedumond.com/blog/friends-dont-let-friends-catch-exception/

    ReplyDelete
  2. Thanks for taking the time to feedback to me on this Lee.

    You're right that there are going to be edge cases to this strategy but I think there's a lack of trust in the client code if you've got to check for nulls every step of the way. This suggests to me a more serious problem.

    Lets look again at the DisplayNameAndTitle method in the post.
    What if the Person object was a valid object but it's GivenName property was null? Does this mean that to concatenate three fields in a class together, we need to null check each of these fields?

    If an object is passed into a method I want to assume that the object is fit for use and any problems that occur, ARE exceptions. When the method is called I don't want to have to check for any possible exceptions - that just increases the ceremony/essence ratio in the method.

    At the end of the day, if an object passed into a method, fails a null check, it's pretty serious and the apps has probably got more more issues than the resources used by throwing a null reference exception.

    ReplyDelete
  3. The context is important. After all, if this API was given to a developer who wasn't familiar with it, they could feasibly pass an invalid argument to it.

    To me, catching exceptions this way actually leaves the developer guessing a little as to what the pre-conditions for successfully using the code are. It would also lead to a lot of catch blocks to handle every possible failing scenario.

    I recommend reading up on Design-By-Contract http://tinyurl.com/yjqgcpx as a possible alternative.

    ReplyDelete
  4. Design-by-contract looks like its found its way into .net 4.0.

    http://www.iridescence.no/post/Design-by-Contract-with-NET-40.aspx

    It is also a prominent feature of S#arp Architecture.

    http://wiki.sharparchitecture.net/ClassLibraries.ashx

    ReplyDelete
  5. Thanks Jon, I'll take a look at the book.

    What are your thoughts regarding the essence/ceremony ratio idea. Does this sit well with you?

    I haven't got the answers here just lots of questions...!

    ReplyDelete
  6. Just looking into Code Contracts a bit more and it's definitely interesting.

    http://mariusbancila.ro/blog/2009/05/31/code-contracts-in-visual-studio-2010/

    That article points out that with Contract.Requires and Contract.Ensures in your code you'll get compile time warnings to tell you if any calls to the functions containing the contracts violates them.

    Regarding the essence/ceremony question, I think this...

    http://gist.github.com/326517

    Is a lot clearer in it's intent than your example.

    Where you mention about any properties of Person being null, well in domain-driven-design terms you would always ensure that any given Person class is valid, by making it impossible for the Person class to be instantiated without the bare minimum required properties (perhaps by having no parameterless constructor).

    For anything else it could return an empty string rather than a null reference.

    ReplyDelete
  7. Cheers Jon!

    I was having a look at Marius post', when you suggested it. It certainly adds a little more structure regarding how you check for values coming into a method, and will have a play with it in VS2010.

    I'd still like to live in a perfect world where the method gets on with "essence" and sorts out any potential mess later but maybe I'm just being to idealist!

    ReplyDelete
  8. I don't think I can agree with this. In perfect world, as I vision it, I should be following Design by Contract (DbC) in order to build robust solutions. In DbC, first, I'll check that my method caller fulfilled the contract between us before I waste my time to process his request. And by this I'm targeting the essence immediately; when applicable.

    Regarding, your sample you didn't mention the ELSE part of the IF statement. If you wrote it down, you'll see that you have replaced the IF statement with a TRY-CATCH statement. Do u think this can reduce the cost, I doubt that.

    ReplyDelete
  9. Hi Waheed,

    In real life, there could be an awful lot of things in the IF statement to check than just the one value in the example.

    I'm certainly interested in the DbC notion but like I mentioned to Jon in a telecon regarding this earlier, although the idea sounds attractive, I'm unsure of the overhead in using such a framework.

    Thanks for your comment :-)

    ReplyDelete