I read the blog post JRuby Performance: Exceptions are not flow control which advocated avoiding using Exceptions except for exceptional circumstances.
I realized that I'm guilty of using rescue to handle LoadErrors on a regular basis.
Is there an alternative to require
that tries to load a file if it exists, but doesn't throw an exception if it doesn't?
Background: If you're wondering "why have you got requires that you don't absolutely require?", here's my story:
require "rdoc/usage"
so that I could give usage information if I didn't enter the correct number of parameters in my command-line application. This throws an exception on out-of-the-box 1.9.Computer programs spend almost all their time in loops. If you are repeatedly raising and rescuing exceptions in an inner loop, which is executed millions of times during an execution of your program, you may genuinely have performance problems. But loading files is something which is usually done only during program initialization. If you raise and rescue a few exceptions during program startup, the impact on performance will be too close to zero for anybody to ever notice.
By the way, if you have a method which is truly performance-sensitive (ie. executed many times), but you do want a "goto" which allows you to jump out of multiple blocks and even up the call stack (like an exception), use throw
and catch
. They're similar to raise
and rescue
, but much faster. Most of the performance cost of raising an exception comes from filling in the stack trace, and throw
doesn't do that.
IMHO, begin; require "..."; rescue LoadError
is idiomatic Ruby and is not to be considered a bad practice in any way, regardless of what people say about "using exceptions for flow control". If your script is normally executed on Windows, running on Linux could rightly be considered an "exceptional condition", and worthy of using exceptions. In general, if a file which you want to load is not there, that's an "exceptional condition" -- which is why require
raises exceptions in the first place!
Hold your head up high, man! Don't let the haters make you feel guilty for using simple, common-sense code!
Using an exception for your first case is probably fine and a lot less messy than trying to figure out if require
would fail before calling it. If all you're doing is trying to load something optional (or, similarly, you need to support several different libraries that do the same thing), then trying to load it and handling the exception is fine, good, and morally upstanding behavior.
In your second case, it might make more sense to check RUBY_PLATFORM
or sys-uname before trying to do platform specific things like OLE. Sometimes the yak does need shaving. In this, if you're on Windows then you really do want to have the require fail whereas if you're on Linux, you don't want to require at all; you're using side effects of the exception rather than the exception itself.
Sometimes people try to use exceptions as a trappable goto of sorts. Exceptions are intended for non-recoverable error conditions, not as a general event notification system. Using exceptions as a goto (i.e. flow control) is an abuse of the exception handling system and people that build systems that use exceptions for flow control usually end up in the hospital (for "falling", into a box of hammers, ten times in a row).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With