Unchecked vs checked exception (with FP glasses)
Tags: java, oop, functional, exceptions
Published: 2020-06-29 16:37:35

Hi all,
for my first post/article/whatever here, I have decided to talk about an old argument in the Java community: the dreaded **Checked vs Unchecked exceptions**.

For those of you who have never heard of this, here is a brief recap:

- **Checked Exceptions**: when calling a method that throws a checked exception the compiler will force you to either handle it with a try-catch block or add it to the signature of your method
- **Unchecked Exception**: they extend the RuntimeException class and if not handled simply bubble up in your calls stack.

The dispute on their usage has been controversial, with checked exceptions usually regarded as the black sheep.

Arguments against checked exception that you could have heard are:

> Checked exceptions can be ignored by swallowing them, so what's the point of having them?

```java
	try {
		// do stuff
	} catch (AnnoyingCheckedException e) {
		// do nothing
	}
```

> Checked exceptions are easy to ignore by re-throwing them as RuntimeException instances, so what's the point of having them?

```java
	try {
		// do stuff
	} catch (AnnoyingcheckedException e) {
		throw new RuntimeException(e);
	}
```

> Checked exceptions result in multiple throws clause declarations.
>
> > The problem with checked exceptions is they encourage people to swallow important details (namely, the exception class). If you choose not to swallow that detail, then you have to keep adding throws declarations across your whole app.

As far as I can tell, in the Java world the following best practice has been established:

- use checked exception for public API
- use `RuntimeExceptions` for your internal modules.

The reason being that checked exceptions clutter your code (so avoid them inside your module) but document the external behaviour of your API.

The point I want to make here is that: 

> `RuntimeExceptions` are **evil** 

If you feel offended by this argument you're free to stop reading and go out for a walk, they say it's really good for your health!

Why are they **evil**? 

Well because whenever you're throwing a `RuntimeException` from one method you're telling a **lie**. 

Which lie?

Say you have a method like:

```java
	public Money from(BigDecimal amount, String currency) {
		if (amount.signum() < 0) {
			throw new ValidationException("whatever");
		}
		return new Money(amount, currency);
	}
```

This method is lying! It is telling its user it will return an instance of `Money` given a `BigDecimal` and a `String`, but it is not, or at least not always.

You may say: I can always document this behaviour with a test, but still that is a loose end.

Another example might be:

```java
	interface Repository<T> {
		T save(T elem);
	}
```

You know from your experience that the `save` method might throw an exception, but you have been told not to use checked exceptions, so you are failing to document it. 

Another couple of considerations:

- given their ability to bubble up in the calls stack, `RuntimeExceptions` are nothing else than glorified GOTOs
- methods that throw `RuntimeExceptions` are more difficult to reason about because you have to keep that information in the back of your mind
- it is too easy not to acknowledge a `RuntimeException` has been thrown

Checked exceptions, on the other hand, by forcing you to handle them are more _honest_ and they are actually telling you that the method you are calling returns 2 possible values:

1. a value of its return type
2. or a value of the checked exception type it throws

By now I guess you might be wondering where I left the FP glasses I mentioned in the title: here they come.

In the FP world (disclaimer: I am just at the beginning of my journey in this world) there is a type meant to be used to express exactly the choice between two types: `Either<E, A>` where:

- A is the right type (got the hint?), i.e. the type you would have ideally returned
- E is the type of the possible error that may occur

Aside from being exactly what you might have been looking for to explicitly state what your method returns, Either is also a **monadic** data type.
Without going into the rabbit hole of talking about Monads, let's say a monadic data type exposes 2 functions that make it easy to work with the **right** value once you get an Either into your hands.

The 2 methods are:

1. **map** that takes a function `f: A -> B` and will turn your `Either<E, A>` into an `Either<E, B>`
2. **flatmap** that takes a function `f: A -> Either<E, B>` and will still turn your `Either<E, A>` into an `Either<E, B>`

You might be familiar with this 2 new functions because the new Stream API (since java 8) or Optional (again starting from Java 8) support those 2 functions.

And you may appreciate how they promote a more declarative way of programming.

`Either` instead is not in the Java JDK but you can find it in (not an exhaustive list):

- VAVR, a functional extension library for Java (https://www.vavr.io/)
- Arrow, a functional companion library for Kotlin, but you can use it also in your Java code if you wish (https://arrow-kt.io/)
- the Scala lang itself (https://www.scala-lang.org/).

# Conclusion
The FP way of thinking about functions as mapping between inputs and outputs (and nothing more) brought me to the conclusion that you should always 

> Return a value from your function or not return it (maybe the parallel does not work here). There is no try!

Or, to put it not in Yoda's terms, 

> A function should be total and always return a value!

Well that's all folks.

Hope you have enjoyed it!