The principle is that since exceptions are essentially non-local gotos, it's preferable to avoid using them as far as practially possible. If you can test for failure first, do that. If you can return a null object that satisifies the caller's expectations, do so. If the caller passes in invalid parameters, write a test and correct the calling code or make your function handle the incorrect parameters. Use exceptions only when you cannot find out whether an operation will succeed without trying it. Using exceptions for flow control is especially evil.