Skip to content

Instantly share code, notes, and snippets.

@ivanacostarubio
Created February 26, 2013 19:35
Show Gist options
  • Select an option

  • Save ivanacostarubio/5041408 to your computer and use it in GitHub Desktop.

Select an option

Save ivanacostarubio/5041408 to your computer and use it in GitHub Desktop.
When to use exceptions
-----------------------------------------------------------------------------------------------------------------------
Michael Feathers wrote on Ruby Parley:
I still like Bertrand Meyer's advice on exceptions: use them when you
can't tell before a call whether it will succeed or not.
That said, there are alternatives. You can pass two actions to a
method, one of which is called when it succeeds and the other when it
fails. Or, degenerate case: use a null object (null objects assume
that one of those cases is a no-op), and (like most other things) it
is better in the 'tell' case than in the 'ask.'
View the urge to use exceptions as a design challenge and try to come
up with a better design.
Jim Weirich expanded:
My approach is a refinement of things I learned from Bertrand Meyer.
First you have to understand that all methods have a contract (implicitly or explicitly). The contract is merely the things that must be true before the method is called (preconditions) and the things that must be true after the method is called (postconditions).
If the preconditions are met, and the method is unable to meet the postconditions, then you must throw an exception [1].
This moves the decisions about throwing exceptions into the realm of thinking about what the contracts for our methods really are, which a more fruitful discussion IMHO.
For example, for the save and save! methods in active record, the contracts are something like this:
Method: save
Preconditions:
* none
Postconditions:
* The object is saved OR it has errors [2]
* Return result is true if the object was saved
Method: save!
Preconditions:
* none
Postconditions:
* the object is saved
By understanding the contracts, we understand when it is useful to use one or the other. For example, I use "save" in controllers where I want a different action if the object wasn't saved. I'll use "save!" in seed data files where I fully expect the seeded object values to be valid.
FYI: Thinking about pre/postconditions is good when you are writing your tests too.
Footnotes:
[1] Or signal an error in another manner, e.g. returning error codes or something.
[2] I guess technically that should be an exclusive or. English is such an imprecise specification language. "
-----------------------------------------------------------------------------------------------------------------------
For more delights like this, join the mailing list at: http://rubyrogues.com/parley/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment