Exceptions are like non-local goto statements.
Also, I mostly agree with these two statements from Joel Spolsky's article on exceptions. I think there are situations where raising exceptions on your own makes sense thought.
- Never throw an exception of my own.
- Always catch any possible exception that might be thrown by a library I'm using on the same line as it is thrown and deal with it immediately.
In The Pragmatic Programmer, Dave Thomas and Andy Hunt suggest:
Ask yourself, "Will this code still run if I remove all the exception handlers?" If the answer is "no", then maybe exceptions are being used in non-exceptional circumstances.
User input is not something unexpected or exceptional. I often see that abused by using exceptions in validations. Sometimes as an alternative I see using multiple return values but that does not improve the situation because it's easy to forget the order or mix the values so best to avoid that too.
What leads to better design is replacing exceptions with notification in validations. Martin Fowler has an article on the subject with some Java code samples. In Ruby/Rails, you get the same thing using ActiveModel validations.
class Person include ActiveModel::Model attr_accessor :name validates_presence_of :name end person = Person.new person.valid? # false
I would often use
ActiveModel::Validations in combination with
Virtus model for handling attributes when dealing with custom multiple models persistence or table-less models.
The first step in the process of switching from exceptions to notification in validations is figuring out the missing domain object to represent that logical entity in the system.