Developers enjoy writing code but few developers enjoy writing exception handling code and even fewer do it right. A new book titled Exceptional Ruby by Avdi Grimm attacks the subject and helps developers take the right approach to solid exception handling code.
Exceptional Ruby is a new guide to exceptions and error-handling that includes over 100 pages of content and working examples. The book includes details on how exceptions work to designing for failures in your application.
InfoQ caught up with Avdi Grimm, the book's author, to discuss the book and topic of exception handling.
Most books today covering a programming language or framework, don't go into intricate detail of a subject. Avdi explains what the difference is between most books and his:
Exceptional Ruby is a book about the art of handling failure in Ruby. Where other books spend a chapter or two on the topic of exceptions and dealing with errors, Exceptional Ruby devotes over 100 pages to detailed explanations of how exceptions work, how to tweak Ruby's exception system to work for you, alternatives to exceptions, how to verify that your code is exception-safe, and how to structure a clean and robust failure-management architecture.
Developers are made aware of exceptions early on but to make best use of them it takes a thorough understanding. This book is intended for bit more experienced developers:
I wrote the book for intermediate to advanced Ruby programmers. Anyone familiar with the basics of Ruby will be able to get something from it, and even veteran Rubyists will learn some new tricks; I can pretty much guarantee that unless your name is Matz you'll learn something new about the Ruby language and failure handling.
A book of this size on a single subject such as Ruby exception handling makes us wonder what we could expect to learn from the book:
First of all, you should come away with a deep, practical understanding of how Ruby's exception system works--and be able to use that knowledge to write better programs. You'll also have a lot more tools in your toolbox for dealing with exceptional situations: you'll be able to identify cases where raising an exception may not be the best solution, and where an alternative, such as a caller-supplied fallback strategy, is preferable.
You'll learn about some time-tested patterns for structuring resilient programs and avoiding failure cascades. You'll understand the concept of "exception safety", and learn how to verify that your most critical methods are robust in the face of unexpected failures. You'll come away with a better understanding of how to write applications and libraries with failure firmly in mind, rather than as an afterthought.
In general, exception handling in any language is an afterthought by many and then not always done with best practices in mind. On the subject of what Avdi has seen from other developers approach to exception handling:
I think developers suffer from a paucity of guidance on how best to approach failures. One of the reasons I wrote this book (and the talk that preceded it) was that I felt like I needed to get a better handle on the subject for my own projects. I can't tell you how many times, for instance, I've struggled with the question of how to best structure an exception class hierarchy. These are areas where there's a lack of solid guidelines; even the best programming books rarely devote more than a brief section to failure cases.
In addition, I think the Ruby community has suffered to some degree from a lack of exposure to some of the classic literature on this topic. For instance, the exception safety testing technique that I demonstrate is something I first came across years ago in the C++ community. It's actually a much easier exercise in Ruby, but I've never seen it documented in Ruby books or articles.
I think what I see most often is simply that the failure case has been left as an afterthought. I see this in code that is littered with begin/rescue/end blocks that were clearly patched in as a result of some unexpected exception that cropped up in production.
I also see a lot of code that hasn't really taken into account the fact that in Ruby, an exception might be raised literally at *any* point. That's one of the reasons I included a section on exception safety and verifying that methods are exception-safe.
A lot of APIs raise exceptions unnecessarily. When a method raises an exception it is stating "I know for a fact that this event is unexpected". But one programmer's "unexpected" is another's daily reality. A great example is HTTP libraries that raise an exception for "404 Not Found". When client code has to wrap API calls in "rescue" blocks in order to handle predictable events, that says there's something lacking in the API design. In many cases APIs can be improved by delegating the decision about what constitutes a truly exceptional case back to the client code.
Finally, I've seen quite a few subtle bugs crop up as a result of over-broad "rescue" clauses causing failures to be silently ignored. I spend a fair amount of time in the book on techniques for tightening up your "rescue" clauses to be specific about what they are intended to catch, even when 3rd-party libraries raise over-generic exception types.
Having a deep knowledge on any single software development topic takes experience and to acquire the knowledge demonstrated in such an unpopular topic such as error handling requires discipline. When asked about how this knowledge was attained:
I've been working with Ruby for ten years now, so a lot of it came from personal experience. I've spent a lot of time reflecting on the common patterns and anti-patterns I've seen in all the projects I've worked on. I also solicited thoughts on Ruby exceptions from other longtime Rubyists; so for instance I've included convention for choosing between the "raise" and "fail" synonyms that I learned from Jim Weirich.
I also wanted very much for the book to be grounded in the established programming literature. So dusted off my library and re-read sections on dealing with failure in classics like "Code Complete", "The Practice of Programming", and "The Pragmatic Programmer". In order to establish definitions, as well as a solid framework for thinking about exceptions and failures, I went back to Bertrand Meyer's "Object-Oriented Software Construction". Meyer's programming language, Eiffel, strongly influenced Ruby's exception system, and his work on the idea of a method having a "contract" with its caller really helps clarify what we mean when we talk about terms like "error", "failure", and "exception".
Developers love to learn about best practices. We wanted to know if the topics discussed in Exceptional Ruby could be considered best practices or obscure methods that would be hard for developers to implement themselves:
I've tried to strike a balance between showing how to implement established, time-tested patterns and idioms in Ruby; and introducing lesser-known techniques to a wider audience. So you'll see things like the Bulkhead pattern--as documented by Steve McConnell and (more recently) Michael Nygard--demonstrated. On the other hand you'll find techniques like using Tag Modules to namespace exceptions, which as far as I know has never been documented before.
Avdi Grimm has been hacking on Ruby code for 10 years, and is still loving it. He's spoken at numerous Ruby conferences and user groups, and he writes about Ruby gotchas, guidelines, and style (among other things) at his blog, Virtuous Code. He is Chief Aeronaut at ShipRise, a consultancy specializing in sustainable software development and facilitating geographically dispersed agile teams. Avdi lives in York County, Pennsylvania with his wife and four children.
Avdi will be speaking at RailsConf being held this week, May 17-19, 2011 in Baltimore, MD in the event readers would like to meet him.