Do not be alarmed – Or do!

This morning I watched a video on Rusts Error-Handling that Larry Garfield posted on Mastodon.

The essence – at least to me – is that Exceptions throw one out of the normal flow of execution just like GOTO does. And we all know that GOTO is bad. SO how does Rust handle Errors, when Exceptions are bad and we always want to return a defined type?

Rust uses Result “enums” instead of a dedicated type that a function returns instead of throwing an exception or returning null. They contain either the expected return value or an Error.

I am not a mathematician. So I might be getting things wrong from a logical point of view. But as a developer I do have a slightly different view on the topic of Error and Exception handling.

But first of all: What’s the difference between an Error and an Exception?

One of the images that stuck with me from the video was the image of a train-track with a switch that diverts the train from the happy path onto the unhappy path.

And in the end all our code – the assembly of all the classes and functions and methods that our application uses – creates a track system where some parts are happy paths and others are failure paths.

To organize that a bit and also to delegate some of the logic we are no longer – hopefully – using one single bowl of spaghetti but functions or classes and methods. So each method contains it’s own logic with an entry point an internal happy path that will return the expected return type and an unhappy path that will … do something else.

And this “do something else” is what this is all about and where the difference between an Error and an Exception for me comes into effect.

What is an Error?

Errors happen. We all agree upon that. You don’t? Perhaps this is not the post you should be reading right now!

Errors are things that we expect. And most important. Errors are things we can handle!

Putting salt instead of sugar into the cake? We can handle that! Either by throwing away the dough or by making that a savoury cake instead of a sweet one.

Accidentally setting some paper on fire? We can handle that! Put some water over it and then mop away the puddle. Or use a fire extinguisher and be happy.

Feeling a bit dizzy and having a mild cough? We can handle that! Have a good nights sleep and sweat away the upcoming cold.

Receiving a 0 as a denominator for a division? We can handle that! Tell the user that we can not handle that and that they should give us a different number.

These are all errors that can be handled. They divert us from the happy path. But by handling them we can metaphorically get “back on track”.

But then:

What is an Exception?

That’s when you admit that you can not handle that on your own! That’s when you call in the fire brigade. That’s when you call 112 (or 911 or whatever else is applicable).

You (or your function/method) can not handle the error by yourself. There is no way to get back onto the happy path by yourself, you have to tell the outside that you weren’t able to handle what you got. This is an exceptional situation.

And for exceptional situations there are (hopefully) emergency plans.

Emergency plans do not follow the normal flow of execution!

They delegate handling the exceptional situation to someone else.

Which is exactly what an Exception in programming does. It tells the outside world that a function was not able to do their work because something happened that they could not handle internally. We have lost track, please help!

To stay in the picture of the train track: An exception is a situation where we are not on the happy track (we hopefully all agree on that) but we are also no longer on the unhappy track. We have gone off track. And now we need someones else to set things right!

In programming that means that whenever we can not handle a situation within our code, we throw an exception and let some other part of the function decide how to handle that. But we are for sure not pretending that everything is fine!

We are not returning anything because the firebrigade is here and the flames are licking the sky.

We delegate handling the exception to someone else.

We are alarmed

So the code that is calling our function can now do two things. They can just ignore that the called function might throw an exception (and therefore further delegate the exception handling).

Or they can for themselves see whether that is – in their context – something that they can handle to still stay or get back onto the happy track somehow.

And the best thing is: The return-type of the function is always the advertised one. When I get something from the function back, I do not need to check whether something went south internally- When I call a function, I get something valid back. I do not need to check, whether what I got back is actually valid or not. The called function will tell me when they have a problem in the execution that needs to be handled differently. They will call 112/911.

And I can decide whether I can handle Emergency calls. Or only specific subsets of those emergency calls. Or not at all.

So for me diverting from the normal flow is not bad.

Being alarmed is not bad

It makes sure that exceptional situations are handled appropriately. That emergency plans can kick in. But that also requires that emergency plans are in place.

That a calling function does not have to check whether an Emergency happened on every call. Because that is not what I am interested in.

Thinking about it, for me the main difference is probably the question of who is responsible for raising the red flag. Is it the function that experiences an unrecoverable problem ( by throwing an Exception) or is it the calling function (by deciding how to handle a Response that contains some indication that something happened).

So for me creating code that accepts Exceptions and makes it clear how to get back on track with them will – at least for now – be much easier to understand and more logical to follow than code that returns a wrapped (value or null/false) where I have to add logic to every time decide which path to use depending on what I get back.