Encapsulate Exception Messages
Encapsulate Exception Messages
While writing an article on adding exception messages with TDD, I noticed a fine point regarding custom exceptions.
(BTW, custom exceptions are almost always the only type of exceptions one should ever throw.)
So, let’s come back to the custom exception from the TDD write-up, the ZeroQuantity
exception. Here is the definition:
public class ZeroQuantity : Exception { public ZeroQuantity() : base("Must have a quantity greater than 0.") { } }
We then throw ZeroQuantity like this:
throw new ZeroQuantity();
Did you notice how the error message “Must have a quantity greater than 0.” is encapsulated inside ZeroQuantity
?
Isn’t that interesting?
Why not define ZeroQuantity
exception so that we can pass in a message?
public class ZeroQuantity : Exception { public ZeroQuantity(string message) : base(message) { } }
Here is how we would then raise the exception:
throw new ZeroQuantity("Must have a quantity greater than 0.");
If we had other places where having a 0 quantity was problematic, we could throw ZeroQuantity
there also—and with different messages:
throw new ZeroQuantity("Quantity is not allowed to be 0.");
throw new ZeroQuantity("A zero quantity is nvalid!");
throw new ZeroQuantity("The quantity is not valid.");
Hmm, the first example of ZeroException
is fine. However, the second instance contains a typo; specifying the message each time can introduce subtle errors. The last example is the most troubling. Here, the error message is much wider, i.e. the quantity not being valid, than what the ZeroQuantity
exception implies: Namely having exactly zero quantity is disallowed.
OK, what is going on here?
A custom exception, like ZeroQuantity
, represents a precise error condition. Therefore it can, and should, hold the message that describes the error condition internally. If we don’t, we may well end up with the problems enumerated above: Multiple messages describing the same error condition—with or without typos, or even incorrect descriptions. We are much more likely to sidestep these issues if we encapsulate the error message inside the custom exception type.
Sometimes, additional information must be part of the exception message. No problem. Here is how we manage that with placeholders:
public class InvalidQuantity : Exception { public InvalidQuantity(int quantity) : base ($"{quantity} is not a valid quantity.") { } }
Now,
throw new InvalidQuantity(-7);
will produce the error message “-7 is not a valid quantity. “
To wrap up, all this amounts to is another example of the usefulness of Encapsulation.
Encapsulation is a critical idea in Object-Oriented (OO) programming. It’s worth wrapping one’s head around it.
Leave a Reply
Want to join the discussion?Feel free to contribute!