Exceptional Ruby was written in 2011 but the content was valuable when I first read it circa 2017 and coming back to it for this review, I’m still finding new things useful.

Most of the book is good for people new to Ruby, covering Ruby syntax for error handling (raise, rescue, ensure, $! etc), the exception hierarchy, the different parts of an error object (error.message, error.backtrace), and so on. I imagine this is most useful to people new to Ruby, but even a few years into using the language there are features here that I had misunderstood or not even heard of (raise has a synonym in fail? Who knew?).

The also contains some worthwhile advice on when to use what features. For experienced programmers some of these things might be realisations that have already dawn naturally: for instance rescuing broad errors may cover up a multitude of other errors that are not intended to be handled by your error logic.

At the same time I often find that seeing things I know written down helps me in a few ways: giving me new terminology with which to discuss with others, or triggering some new insight on a related topic. And I suspect that if I had the Java equivalent of this book when I first started my career, I would have avoided many pitfalls. The “5 questions to ask before raising” section gives a method to a decision that I must admit is quite haphazard even now.

There is some advice on alternatives to exceptions that was really eye-opening. There is a whole world of error handling outside the standard Ruby raise/rescue paradigm. This is hidden in broad daylight in front of most Ruby programmers, because so many of us use Rails which intentionally swallows validation errors and shepherds programmers towards giving the user a chance to recover from bad data entry. This is a classsic example of an error that isn’t unexpected and therefore doesn’t match the idea of “force the caller to handle this, or make the entire app crash”.

In a similar vein, the discussion of Ruby error-handling strategies helped give context to the patterns in Ruby’s standard library. I’m thinking here of caller supplied fallback strategy, as in hash.fetch(key) { # my error handling logic here } where the caller supplies a block that executes if the key is not found, or hiding expected error cases from calling code, as in File.read { # my file handling code} where there is no need to explicitly call file.close.

It’s a short book (86 pages), and very accessible. Anyone new to the language, and anyone new to programming will find almost all of it valuable. In my 2020 re-read, I’m finding the value that I get now comes from bringing a bit more experience to the reflection that the book prompts. I’m also getting some ideas on where else in the programming world to look for interesting concepts: for instance I now need to go read more about the Circuit Breaker pattern.

You can buy the book here, go make Avdi Grimm’s day by buying something that he wrote 9 years ago :).