It is good practice to check for every possible errors - especially, the unexpected ones. This can push us to write code that is hard to read. The logic of your program can end up being totally obscured by error handling, particularly, if you subscribe to,
"a function must have a single return statement" school of thought.
Let's examine the code snippet below:
Personally, I am not aware of any limitation to if-else nesting but, deep nestings could be an indication of terrible design. They could negatively impact readability which will make the job of the future maintainer a little bit more difficult.
With most modern programming languages, we can, easily, refactor the above code snippet using exception handling to increase readability:
The code is clearer with the main logic on one side and all the error handling moved to a single place.
But, my personal dilemma is the deciding factor of when wrapping a piece of code around a try and catch block is the right approach and when it isn't.
What is Exceptional?
If your code tries to load a record from the database for some operations, and that record does not exist, should an exception be raised?
That depends on the expected behaviour.
Always assume that an uncaught exception will terminate your program and then ask yourself, "Will the code still run if I removed the exception handler?". If "no", then, maybe, exceptions are being used in non-exceptional circumstances.
If the record should have been in the database, then an exception can be raised. This is because something unexpected happenend - a record that your program expected to find in the database was not found.
On the other hand, if you are unsure whether the record should exist or not, then not finding it in the database is not exceptional - not an unexpected behaviour, and an error return is appropriate.