Created
February 26, 2013 19:35
-
-
Save ivanacostarubio/5041408 to your computer and use it in GitHub Desktop.
When to use exceptions
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| ----------------------------------------------------------------------------------------------------------------------- | |
| 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