Rescuing exceptions in normal flow is actually fine

This is part of the Semicolon&Sons Code Diary - consisting of lessons learned on the job. You're in the architecture category.

Last Updated: 2024-04-26

Say you have this function:

def open_config
  if File.exist?(CONFIG_FILE)
    File.read(CONFIG_FILE)
  else
    false
  end
end

Is this right? Well, not really. The problem is that there are many other reasons - aside from the file not existing - why IO can fail, e.g. the file has the wrong permissions. These reasons are not handled here. A better solution would be this to handle them all, with the following:

def open_config
   File.read(CONFIG_FILE)
rescue IOError
  false
end

This solution goes against the (poor in this case) advice not to use exceptions to control flow. Clearly it is a simpler design to rescue a single exception class than to carry out (e.g.) 10 different (slow) tests on the file within the logic.