Motivation for resultr
motivation.Rmd
Doesen’t R already have exceptions and try-catch
mechanics?
Yes!
R already has a very flexible and useful condition signalling system that is the basis for emitting messages, warnings, and errors - exceptions that bubble up and either crash the executing program / function, or are caught and handled by a matching exception handling function.
This base system was much improved by functionality implemented in
the rlang
package, such as call-stack trimming and making
it trivial to make rich error messages and custom error/warning
classes.
It is beyond the scope of this short article to go into the details of these systems. I encourage you to read the documentation, these tools have helped me immensely, they’re very good, and I can’t recommend them enough. I’ve collected some of the topics below!
Ok, so why should I use a result object pattern instead of exceptions then?
My motivation for this package is not that people should use result objects instead of exceptions, and I’ll make no grand assertions as to the absolute unquestioned superiority of one way of dealing with errors over another. I’m a “right tool for the right moment” kind of person.
People cite all kinds of pro’s and con’s for using a Result object pattern vs. exception patterns, and I won’t litigate all of them here, suffice to say that both patterns have been around for a long time, but a measured take tends to emerge from such discussions which vibes with my “right tools for the right job” attitude:
There are exceptions, and then there are predictable failures.
In my current industry job, a lot of processes, tools and dashboards are being written in R, by people of varying degrees of experience. There are people like me with over a decade experience in writing scientific software - (in many languages including ones more geared towards systems programming like C/C++) and then there are people who are only just beginning with R or who have only ever used R.
In this job, I’ve noticed a lot of coders on a team only ever consider the happy path when writing code. Which can lead to a lot of exceptions and a lot of crashes.
And that’s ok! Exceptions are by definition, exceptional - occurrences that are difficult to predict or anticipate. Our software crashing indicates our software needs to change - that we need to get good and improve the code base.
However, there are lots of places in our code where exceptions keep happening, because they are not exceptional, but predictable failures:
- A user provided incorrect credentials for a database.
- A database or service happens to be down for maintenance.
- The user is asking for a combination of parameters that results in a bad query.
- The user is trying to run a calculation that isn’t applicable to an area of business - a subset of the data.
All of these and more are predictable occurrences that should become gracefully handled by our code base as we improve its quality.
Indeed you can actually simply handle these cases using the exception catching and condition mechanisms that R already has-
“So what’s the problem, ’Brina?”
- yes ok, you can just catch the common predictable exceptions, AND the exceptional ones… but… well… in my own experience it just doesn’t happen. People in my team don’t do it consistently, I don’t do it consistently. And whilst yes, this might be a skill issue to a certain extent, this feels like an uphill battle in many ways. It’s not always obvious from a function’s definition or docs if it could throw or where and why it might throw.