exception

Exceptions are Confusing. Here’s When to Use Them.

In my days as a junior developer, I didn’t understand exceptions. One of my standard questions to more experienced colleagues was 

“When should you use exceptions?”

 

Which elicited the standard response: 

“Use exceptions in exceptional situations.” 

 

I found this glib reply unsatisfactory, yet I did not know why. This answer sounded deep and meaningful, yet it contained little actual explanation. The follow-up question was obvious: 

“What then makes for an exceptional situation?” 

 

Here the answers given were even less clear-cut: 

“Well, when the situation is unexpected.” 

 

Or something similarly ambiguous.

 

Why ambiguous? Because at the end of the day, with sufficient forethought, almost all circumstances are foreseeable and consequently expected. 

  • A 100-year flood? We should expect one of those about once every 100 years. Expected 1% in any given year.
  • What about an error saving to the database? Yes, we know that can happen. Also expected from time to time.
  • A user typed incorrect credentials when logging in. That happens all the time, and thus also very much expected.

 

No, the condition being ‘unexpected‘ won’t do as a rule. Any foggy notion of ‘unexpectedness’ that depends on the observer is not workable as a programming principle for invoking exceptions. We’d like a more robust explanation; thank you.

 

Let’s consider an example.

Below is the listing for adding a quantity of a product into an instance of a ShoppingCart:

  public void Add(Product product, int quantity)
  {
     var item = GetItem(product.Name);
     if (item != null)
        item.Quantity += quantity;
     else
        Items.Add(new ShoppingCartItem(product, quantity));
  }

Can you spot the problem with this method?

 

If we pass a null value as the product parameter at runtime, the result will be a NullReferenceException since the code is trying to read product.Name on a null. We have a bug. That’s what NullReferenceExceptions are. We should never have NullReferenceExceptions (Java: NullPointerExceptions) in our code. 

Anyway, receiving a null for product is an invalid value and a showstopper for the continued processing of Add(). 

What should we do? There is no point carrying on with Add(). 

Given that Add() cannot continue, it should inform the calling code that there was a problem with product’s argument value.

When such an exceptional situation occurs, we can bounce the problem condition to a higher level of control in the hope it can be handled there.

 

Therefore:

Exceptions are a type of program control flow mechanism.

 

Exceptions are handy when the program encounters circumstances the local logic is ill-equipped to handle. Their purpose is to escalate problems to the caller, or even further up the call stack, until some code is prepared to handle the problem situation raised by the exception—the exception handler.  

 

As a real-world analogy, consider the case where you face a problem you cannot (or don’t know how to) handle at work. What should you do?

 

One reason we have managers in our modern organisations is so that we can escalate problems to them. Management exists to remove roadblocks and impediments holding us back from doing our jobs. It’s now their problem to resolve.

 

In code, exceptions act as escalation messages to the calling code that may be able to respond to the problem and resolve it or otherwise manage or handle it.  

So, how should ShoppingCart.Add() manage null values for Product?

Given it cannot continue with a null Product, it should inform the caller as such by throwing an exception:

  public void Add(Product product, int quantity)
  {
     if (product == null)
        throw new MissingProduct();
     var item = GetItem(product.Name);
     if (item != null)
        item.Quantity += quantity;
     else
        Items.Add(new ShoppingCartItem(product, quantity));
  }

When the incoming product is missing (i.e. a null) the local code is not equipped to handle this exceptional circumstance. Consequently, Add() throws an exception and escalates the problem to a higher-level. 

Conclusion

Most of my confusion regarding exceptions instantly evaporated when I discovered that exceptions were merely mechanisms for escalating problems to calling code.

So, throw exceptions whenever you encounter circumstances that, given the local context, you cannot resolve.

0 replies

Leave a Reply

Want to join the discussion?
Feel free to contribute!

Leave a Reply