Checked exceptions vs Either
Exploring the pros and cons of Java’s checked exceptions and functional programming’s Either type for effective error handling
This post assumes that you have experience with or at least have some knowledge about functional programming concepts.
I will be using an example of Java checked exceptions because I am most familiar with those.
Both, throws
and Either
, are used for error handling and both are trying to force you to handle or at least consider unhappy path. They seem similar in principle but there are many practical and conceptual differences.
We’ve all heard about Java checked exceptions and throws
and how they are bad and should be avoided. Turns out that it was a bad idea and Java discourages it and Kotlin doesn’t have it at all while some new and modern language like Swift reintroduced checked exceptions. Our industry doesn’t seem to learn very quickly.
Why is throws
bad and Either
is good?
Java checked exceptions
Java checked exceptions were introduced in Java 1.0, which was released in 1996. The goal of checked exceptions was to provide a mechanism for handling errors in a more structured and reliable way than was possible with unchecked exceptions or error codes. By requiring methods to declare all of the exceptions that they could throw, Java’s designers hoped to make it easier for developers to write more robust and maintainable code.
However, over time, the use of checked exceptions in Java became controversial. Some developers found that the requirement to declare all possible exceptions in a method signature made code more verbose and harder to read. Others argued that checked exceptions encouraged developers to handle errors in ways that were too generic or to simply ignore errors altogether. Later we will explore real problem with checked exceptions and it had nothing to do with Java.
Either
The Either
type for error handling is a concept from functional programming languages that has been adopted in various forms in other languages. It was first introduced in the functional programming language Haskell in the 1990s as a way to represent a computation that could result in one of two possible outcomes, either a success value or a failure value.
Either
is a sum type that can hold either a value of one type or a value of another type. This allows functions to return a value that can represent success or failure, and makes it easy to handle errors in a more structured and composable way.
Either
provides a more flexible and composable way of handling errors than traditional error handling mechanisms like exceptions or error codes.
History didn’t answer our question: What is the difference? We will compare the two.
Comparison
Checked exceptions and Either are two approaches to error handling in software development. While both have the same purpose of ensuring the safe and correct operation of a program, they differ in their usage and implementation.
Java checked exceptions are enforced by the compiler. If a method is marked with throws
, the callers of that method must either use try/catch
or also use throws
. This ensures that the exceptions are handled in a proper way, but it also adds complexity to the code, as developers must explicitly handle each exception. Checked exceptions are also limited to representing exceptional cases.
Either is a construct that can be used in any programming language that supports algebraic data types. If a function returns Either, the developer must deliberately handle the Either and not just stick throws
onto the method. The Either type can be used to represent any kind of computation that can have multiple possible disjunct outcomes. It is a value that can be stored in a data structure, and it allows for greater flexibility and composition compared to checked exceptions.
The biggest problem with Java checked exceptions, in my opinion
In my opinion the biggest problem with Java checked exceptions is not that it’s not composable but boundary crossing and the abuse.
We, programmers, abused it to a point of use discouragement and languages dropping it altogether. This is ours, programmers, problem.
Checked exceptions also cross boundaries in unassuming ways making higher level policies know about low level details, you have to catch the exception or use throws
.
How I would use checked exceptions
I think that there is right way to use checked exceptions and that is for truly exceptional cases. Even then I would limit it to usages like, for example, Java open file:
public void open (File file) throws IOException
that is: library development. Developers will rely on that library to open the file and their program needs that file opened.
But in the case I am using library that’s using checked exception I would create a wrapper that’s storing errors inside Either
.
Conclusion
Checked exceptions and Either
serve same purpose but are wastly different. Biggest differences being that checked exceptions are:
- Very limited and constraining, focussing only on errors.
- Complexity.
- Boundary crossing.
- Prone to abuse and misuse, this is not problem with checked exceptions but they allow it with their design.
while Either
is:
- Flexible.
- Composable.
- Customisable.
- Requires deliberate handling of errors, you can’t be lazy and just stick
throws
onto the method.
My personal choice will always be Either
.