TrainingConferencesAbout UsContact UsAdvertiseSQE.comRSS Feed

StickyMinds.com: brain food for building better software

Log In
 Clarify Your Search Criteria

Tips on Using Our Search Feature(s)
 
StickyMinds.com Home
ResourcesTopicsCommunityPowerPassBlogs
Home  >  Detail: The Exceptional Exception



A StickyMinds.com Original

The Exceptional Exception

By Tod Golding

Send This Content to a FriendGet a Short Link to This ContentPrint This ContentSee User Comments About This Content

Summary: So much more than a bucket for your errors, exceptions can be a valuable tool that lets you communicate to your clients not only that there is a problem but why and where the code failed.


TechExcel, Inc.
If I were an exception, I might be feeling a bit unappreciated. Don't get me wrong, I think exceptions are mostly a well-understood construct. Developers seem to easily grasp the fundamentals of throwing and catching exceptions, but at the same time—even though the mechanics of exceptions are well understood—their power and value often go untapped.

Time and time again I come across code in which developers are taking a fairly shortsighted view of exceptions. For this group of developers, exceptions end up being little more than a big bucket where they can send all of their errors.

The code in figure 1 provides a good example of what I'm referring to. In this example, I have created a method to update a customer's bank account. This somewhat simplified method accepts a customer ID and an amount that will be used to increment the customer's account balance.

At first glance, this method seems relatively straightforward. So, what's wrong with it? Well, technically speaking, nothing. The method will achieve its purpose and will certainly capture and log errors if they occur.

However, even though this code works, it does little to tap into the power and expressiveness of exceptions. If you're using this approach, you're basically saying, "I have a big block of code I hope executes, and if for some reason it fails, I'll put a try/catch around it to log the error." From my perspective, that is far too narrow a use of exceptions.



Imagine for a moment you are an exception. There you are with your uniform on, pacing the sideline, chomping at the bit to go into the game to catch, process, and forward a wide variety of highly expressive error conditions to clients near and far. You just can't wait for the coach to send you in. Then, when your number is finally called, all you're asked to do is catch the most basic exception, log an error, and throw yourself over the fence. That's got to be humiliating.

I think one reason we end up undervaluing exceptions is because we all have a tendency to take a somewhat self-centered view of our own code. When we write methods, we're not always thinking about what the client might want to do when our code fails. Instead, it's easy to fall into the trap of just assuming clients always expect our code to succeed, and when it doesn't, we'll just log a fatal error.

With this viewpoint, it's easy to see why no one would make much of an effort to throw interesting exceptions. If the error is fatal, why should I care about what the client may or may not want to do after the method exits?

This argument falls apart quickly, however, when you star thinking about unit testing. Imagine you have to write unit tests for the code in figure 1. When you call the UpdateBalance() method in this example, a variety of things could go wrong. For example, you may want to have tests that pass in different user accounts—some with update privileges and some without. How can you differentiate between this security failure and the multitude of other failures that could happen within this method? It's simple—you can't.

To be fair, this isn't exactly news. I think most developers would look at the code in figure 1 and recognize the need for more granular exceptions. In fact, I think most people looking at this code could easily list a number of custom exceptions they might want to throw and end up with something resembling the code shown in figure 2. Unfortunately, there are too many times when we simply don't implement these exceptions.



Making your methods throw more granular errors is the easy part. The more difficult part is figuring out how you want to propagate these errors back to the client. This is especially significant when your exceptions must be propagated throughout a multilayered architecture.

Suppose you have a typical n-tier architecture with client, business logic, and data access layers. With this architecture, you'll want to be sure any layer-specific exceptions are not allowed to cross the boundaries. For example, you don't want the "SQLException: Foreign Key ACCOUNT_ID constraint violation" message that was generated in the data access layer propagated all the way back to the end-user.

So, when you design a system, you'll want to have a clear exception policy that allows you to define how each layer in your architecture will propagate errors to its clients. For example, if you call a method in the data access layer, you should know precisely what family of exceptions can be thrown by any public method in that layer. If any other form of exception comes out of that layer, something went wrong.

The code in figure 2 provides an example of this policy in action. Here, the UpdateAccount() method in my client layer is calling into the service layer of my architecture. So, each exception coming out of that layer should be part of my ServiceException family of exceptions classes.

This approach can simplify the testing of each layer, and it can reduce the complexity of each client's catch block. It also simplifies my logging policy. Whenever you catch one of your custom exceptions, you know it has been logged. However, if you didn't have this custom exception and you were only able to catch a generic Exception object, you'd essentially be in the dark about what might have already been done with this error. Should it get logged? You really have no way of knowing.

This example gets to the real heart of the issue. Exceptions are not meant merely to catch errors—they are supposed to be the tool that lets us establish a clear error-handling protocol between clients and the methods they call. We cannot view each exception condition as if it exists in a vacuum. Every time we catch an error and decide to throw an exception, we have to ask ourselves how that exception fits within the overall exception-processing scheme we have adopted.

My broader concern is that exceptions seem to get rolled into the simplistic domain of "error handling" and, as such, some developers implement their exception strategy with this same granularity and narrowed perspective. Exceptions can tell us much more than "did I succeed or did I fail?" They represent an opportunity for us to tell clients why and where our code has failed.

I guess that's why I'm feeling so bad for the exception these days. He's a great language construct and, given the opportunity, he has a lot to offer—if you can see him as something more than a simple error handler. {end}

How are you currently using exceptions to establish specific error-handling policies within your own systems?

Join the conversation below or start a new one in the Reader Comments section.


About the Author
Tod Golding is the founder of Blue Puma Software, a technical consulting company that provides software training, mentoring, and development services. He has twenty years of experience as a software developer, lead architect, and development manager for organizations engaged in the delivery of large-scale commercial and internal solutions. With an extensive background leveraging .NET, J2EE, and Windows DNA technologies, Tod has become equally skilled with C#, Java, and C++. He has worked and consulted at a variety of companies, including Microsoft and Borland. Tod is the author of Professional .NET 2.0 Generics and a contributing author of the XML Programming Bible.

Back to Top
 
 

Member Comments
Add Your CommentExpand Comments
 
Comment:    
by Wayne Mack 3/20/2007

I would recommend not creating custom exceptions. The key to a useful exception is write a good message when it is thrown. Beyond that, there is no need to catch different types.

As for .Net exceptions, do not waste time catching and rethrowing. The exception already has a very nice stack trace built into it that is exposed throught the ToString() method.

As for unit tests, typically the presense of an exception is sufficient. The test configuration will determine what error condition is present and if the test throws no exceptions in absense of an error condition and throws exceptions in the presense of each...Read On

Author's Response:
3/21/2007    
I'm not sure that I completely agree with the idea that exceptions are focused exclusively on writing good messages. That's certainly *one* of the goals of good exception handling. From my perspective, exceptions also represent an opportunity to express failures to clients in a way that allows them to take specific actions. Different errors may require different actions. Now, I would agree that there's more than one way to convey each of these different error conditions. In my example, I've chosen custom exceptions to convey each of these conditions.

In terms of unit testing, I'm not suggesting that every method in your class should return custom exceptions. I certainly find plenty of cases where a single method will simply succeed or throw an exception. At the same time, there are also plenty of scenarios where more granular exceptions are required. If I'm calling a service to update a business object, I definitely want to distinguish between an inability to connect to the service and the case where there's a data collision. My reactions to each of those scenarios will be very different in the client and I'll want tests that exercise both of these paths independently.





 
 
Comment:    
by Peter O''Reilly 3/20/2007

I agree with Rob, it is a good thought provoking article. Thank you. I also agree with him that the requirements should drive such decision as for the reasons he provided.

When writing .Net code, I take advantage of the innerException property to create a linked list/exception object chain. I will rethrow an exception through each procedure called in the call stack, capturing the state (e.g. local variable values) within each procedure. While it does not address Todd's concern of how you want to propagate these errors back to the client, it does pay big dividends saving time (and money) troubleshooting exceptions that have been...Read On

 
 
Comment:    
by Rob Park 3/13/2007

As much as I would agree that when you throw your own exceptions having your own type (or types) is a good idea. However, I think you should really have your requirements drive this. It may or may not be a priority for the user to handle this and if you're taking the time to catch and rethrow as something else then I'd assume a client class is actually going to use the new type. If not, then I don't see the real value.

catch(Exception e) really should only happen at the highest layers (if at all). Different arguments can be made based on the specific application, but in general I would not recommend to ever catch all. Let the...Read On

Author's Response:
3/21/2007    
In general, I agree with the idea that requirements should drive the creation of custom exceptions. The problem is, in many organizations, developers tend to "discover" un-expressed requirements while they're building their systems. This is especially true in heavily unit tested environments. Still, your point is valid. This really comes down to *how* requirements are captured and how you're applying them. For most projects I've been on, it's very typical for developers to discover new requirements during implementation. Overall, I just want developers to consider the possibilities with each exception block and look for areas where more specific exceptions *may* be required.

 
Back to Top



 
Ads By Google
What's This?
 
 



Home   |   Resources   |   Topics   |   Community   |   PowerPass



© 2010 StickyMinds.com. All rights reserved.
StickyMinds.com is a division of Software Quality Engineering.
Privacy Policy    Terms & Conditions    Link to StickyMinds.com    Feedback


Cloud Connection

Rally Software




STAREAST 


Better Software Conference