Guard Methods

In defensive programming, guard clauses are used to protect your methods from invalid parameters. In design by contract, guard clauses are known as preconditions, and in domain driven design, we use them to protect invariants — unbreakable rules that form assumptions about our model:

public class BankAccount
{
    private int balance;

    public void WithDraw(int amount)
    {
        if (amount < 0)
            throw new InvalidAmountException(
                "Amount to be withdrawn must be positive.");
        
        if ((balance - amount) < 0)
        {
            string message = String.Format(
                "Cannot withdraw ${0}, balance is only ${1}.",
                amount, balance);

            throw new InsufficientFundsException(message);
        }

       balance -= amount;
    }
}

Unfortunately, in examples like this, the true intention of the method – actually withdrawing money – is now lost in a forest of error-checking guard clauses and exception messages. In fact, the successful path — representing 99% of executions (when there is enough money) — only accounts for 1 line in this method. So let’s refactor:

public class BankAccount
{
    private int balance;

    public void WithDraw(int amount)
    {
        ErrorIfInvalidAmount(amount);
        ErrorIfInsufficientFunds(amount);

       balance -= amount;
    }

    ...
}

By extracting these guard clauses into separate guard methods, the intention of the method becomes much clearer, and the explicit method names give a clear indication of what is being checked inside (regardless of how those checks are implemented). And we can concentrate on the main success path again.

April 8, 2010

4 Comments

Klaus Hebsgaard on April 8, 2010 at 2:36 pm.

The problem with this approach is that when you get a stack trace in your exception, it is not starting at the withdraw method, but the ErrorIfInvalidAmount method

Richard on April 8, 2010 at 2:43 pm.

Klaus: and that is a bad thing? I think a stack trace starting at ErrorIfInvalidAmount() is pretty descriptive…

Klaus Hebsgaard on April 8, 2010 at 3:17 pm.

Actually I agree with you, I was stating a co-developers point of view in order to provoke him.
We had a good discussion and we mostly agree on this…

Sorry for using your blog for that :-)

MinnowNoir on April 10, 2010 at 4:17 pm.

If your schema doesn’t preclude you from exposing balance as a public property, you might be able to delegate the invariant checking to contracts or method attributes, which have a strong declarative value for those calling your method. You could also have the class pass itself to a BankAcountValidator class, thereby siloing the validation for easier maintenance.

OTOH, you could also delegate this behavior to aspects and use reflection to get at the balance value. You lose the visibility, but still clean up the method code.

Same arguments mostly hold for logging, which also tends to clog up method code.

Leave a Reply