Exception Factory Methods

Victor Todoran
3 min readApr 27, 2022

--

A picture of smoky factory chimneys  in black and white
Photo by Dominik Dancs on Unsplash

There is lots to talk about Exceptions: what are they, when should you throw them, when not to catch them and so on and so forth. You won’t find any info about these topics in this post, we’ll leave that for another day.

What you are going to find in this post is an opinion about how you should create exceptions in your code and a few arguments to support it.

When I stumble across throws statements most times they look something like this:

Or maybe something like this:

I find it that this is quite a poor way of creating Exceptions for a couple of reasons:

  • Long messages, often built by mixing constants and variables, make the code clunky and hard to read. Sometimes it takes a minute to understand why a given Exception is thrown and that’s because the messages are optimized for the end user or logging and not the developer.
  • One Exception might be thrown for more than one reason, in our examples the CantCollectTotalsException is once thrown because of an empty cart and once because of an non sellable cart item.
    By directly calling new whenever we want to throw an exception there is no quick way to semantically categorize all the reasons and places for which an Exception is thrown.
  • Mind you that an Exception can also be thrown in multiple places because of the same reason and with the same message.
    Just consider the following example:

Let us imagine that the app works heavily with start dates and end dates, then it won’t be a stretch to think that maybe this exception, with this message, is thrown in more than one place.
Say that the message needs to change for whatever reason or you would need to replace all the usages of InvalidPeriodException, that are thrown because of start date being bigger than the end date, with another Exception.

Sure, you can search by the string and replace each message or usage individually. But if the usages are high this is prone to error and if the message is sometimes dynamically built then things get even messier.

The alternative is static factory methods inside Exception classes:

And the callers of these exceptions will look like this:

The advantages of this approach are as follows:

  • IMO it makes the code more readable. I don’t need to mentally parse the exception message every time I encounter a throws statement. Also the variables used to build the exception message seem to pop out and be more visible.
  • The usages of a given Exception class are also more visible. Just by looking at the class I can deduce all the places or at least all the reasons for which it is used.
  • If this approach is a coding guideline in your project it will force people to create their own Exception classes and not abuse the global \Exception which should be reserved only for exceptions that are not meant to be caught.
  • If the message needs to change, for a specific use case of the Exception, then you need to change it in only one place.
  • If you need to replace all the usages of a specific use case then the Find Usages feature in your IDE is a much more comfortable method of search than by looking up an exception message.
    Also when removing one of the factory methods, for the purposes of using a different Exception for that use case, static analysis will tell you if you forgot to adjust some parts of your code. (assuming you use static analysis, which you should)

That’s it! Thanks for reading!

Disclaimer: Consider this to be a living document, which means it’s subject to undocumented changes and it might even die in the future.

--

--

Victor Todoran

I write, read and think about software and its users for a living