Exponentially because if each method branches in two different ways then every time you call another method you're squaring the previous number of potential outcomes. By the time you've called five methods you are up to 256 possible outcomes at a minimum.
The code that we imagine might be problematic, the call to Connect(), is now wrapped in a try block. Any exception that occurs in the code inside the catch block will immediately transfer to the code in the catch block, where we can specify what we want to happen if the call fails.
Without a try catch, you run the risk of encountering unhandled exceptions. Try catch statements aren't free in that they come with performance overhead. Like any language feature, try catches can be overused.
Although this is sometimes unavailable, nesting try/catch blocks severely impacts the readability of the source code as it makes it difficult to understand which block will catch which exception.
My basic rule is : Unless you can fix the problem which caused the exception, do not catch it, let it bubble up to a level where it can be dealt with.
In my experience, 95% of all catch blocks either just ignore the exception (catch {}
) or merely log the error and rethrow the exception. The latter might seem like the right thing to do, but in practice, when this is done at every level, you merely end up with your log cluttered with five copies of the same error message. Usually these apps have an "ignore catch" at the top most level (since "we have try/catch at all the lower levels"), resulting in a very slow app with lots of missed exceptions, and an error log that too long for anyone to be willing to look through it.
Extensive use of Try...Catch isn't defensive programming, it's just nailing the corpse in an upright position.
Try...Finally can be used extensively for recovery in the face of unexpected exceptions. Only if you expect an exception and now how to deal with it should you use Try..Catch instead.
Sometimes I see Try..Catch System.Exception, where the catch block just logs the exception and re-throws. There are at least 3 problems with that approach:
No, it's not "defensive programming." Your coworker is trying to rationalize his bad habit by employing a buzzword for a good habit.
What he's doing should be called "sweeping it under the rug." It's like uniformly (void)
-ing the error-status return value from method calls.
The term "defensive programming" stands for writing code in such a way that it can recover from error situations or that it avoid the error situation altogether. For example:
private String name;
public void setName(String name) {
}
How do you handle name == null? Do you throw an exception or do you accept it? If it doesn't make sense to have an object without a name, then you should throw an exception. What about name == ""?
But ... later you write an editor. While you set up the UI, you find that there are situations where a user can decide to take the name away or the name can become empty while the user edits it.
Another example:
public boolean isXXX (String s) {
}
Here, the defensive strategy is often to return false when s == null (avoid NPEs when you can).
Or:
public String getName() {
}
A defensive programmer might return "" if name == null to avoid NPEs in calling code.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With