Programming Error Exceptions – Is the Approach Sound?

cexceptionsjava

I am currently trying to improve my use of exceptions, and found the important distinction between exceptions that signify programming errors (e.g. someone passed null as argument, or called a method on an object after it was disposed) and those that signify a failure in the operation that is not the caller's fault (e.g. an I/O exception).

How should these two kinds of exceptions be treated differently? Do you think that error exceptions need to be explicitly documented, or is it enough to document the relevant preconditions? And can you leave out the documentation of a precondition or error exception if it should be obvious (for example, ObjectDisposedException when calling a method on a disposed object)

Best Answer

I think you are on the right track. Neither throwing, catching, nor documenting all potentially throwable exceptions makes much sense. There are times where the product stringency requires a higher degree of exception employment and documentation (e.g. certain safety critical aspects of a systems).

The strategy of being more defensive, using contract concepts to identify preconditions (and postconditions) on especially downstream callers (e.g. anything that resembles a public or protected member) will often be more effective and more flexible. This applies not only to the implementation, but to the documentation. If developers know what is expected, they are more likely to follow the rules and less likely to be confused or misuse the code you have written.

Some of the common things that should be documented include the case of null parameters. Often there is a consequence for their use that drives the result to something that wouldn't normally be expected, but are allowed and used for a variety of reasons, sometimes for flexibility. As a consumer of a member that has parameters that allow null, or other special, non rational values (like negative time, or negative quantities), I expect to see them identified and explained.

For non null parameters, as a consumer of a public or protected member, I want to know that null is not allowed. I want to know what the valid range of values in the given context is. I want to know the consequences of using values that are outside the normal range, but are otherwise valid in a different calling context (eg the value of the type is generally valid for any operation, but not here -- like a boolean parameter that doesn't expect false as a valid value.

As far as platform, or otherwise well known interfaces, I don't think you have to go to extremes in documenting it. However, because you have an opportunity as a developer to vary the implementation from whatever platform guidance, making note of how it follows that guidance may be of value.

Specific to IDisposable, often implementations of this interface offers an alternative method that is preferred over the explicit disposal process. In these cases, highlight the preferred method, and note that the explicit disposal is not preferred.

Related Topic