Notes from Code Complete
- Use error-handling code for conditions you expect to occur; use assertions for conditions that should never occur
- Use assertions to document and verify preconditions and postconditions
- Throw exceptions at the right level of abstraction; include all information that led to the exception
- Always have a mechanism to log application errors and a way to read that log.