views:

858

answers:

12

Hi,

I have been programming for last 3 years. When I program, I used to handle all known exceptions and alert the user gracefully. I have seen some code recently which has almost all methods wrapped inside try/catch blocks. The author says it is part of defensive programming. I wonder is this really the defensive programming? Do you recommend putting all your code in try blocks?

Any thoughts?

+29  A: 

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.

James Curran
Exactly. Putting everything in a try/catch statement is usually a sign of an inexperienced developer who doesn't know much about exceptions IME.
Jon Skeet
We should be allowed to mod+2 if we spend rep points like downmodding. But I'll just do it here.
I think that sometimes, particularly when crossing the boundary of a module or library, it is good practice to catch the exception, wrap it in a different type of exception (like Java's cause-chaining facilities), and rethrow.
rmeador
That would be "partial handling" which does allow a rethrow, potentially with a different exception. Exception translation is partial handling, in my book.
MadKeithV
+2  A: 

There is such a thing as "too much" processing, and catching all exceptions kindof defeats the point. Specifically for C++, the catch(...) statement does catch all exceptions but you can't process the contents of that exception because you don't know the type of the exception (and it could be anything).

You should catch the exceptions you can handle fully or partially, rethrowing the partial exceptions. You should not catch any exceptions that you can't handle, because that will just obfuscate errors that may (or rather, will) bite you later on.

MadKeithV
A: 

I guess the real answer is "It depends". If try-catch blocks are catching very generic exceptions then I would say it is defensive programming in the same way that never driving out of your neighborhood is defensive driving. A try-catch (imo) should be tailored to specific exceptions.

Again, this is just my opinion, but my concept of defensive programming is that you need fewer/smaller try-catch blocks not more/larger ones. Your code should be doing everything it can to make sure an exception condition can never exist in the first place.

EBGreen
+1  A: 

I would recommend against this practice. Putting code into try-catch blocks when you know the types of exceptions that can be thrown is one thing. It allows you, as you stated, to gracefully recover and/or alert the user as to the error. However, putting all your code inside such blocks where you don't know what the error is that may occur is using exceptions to control program flow, which is a big no-no.

If you are writing well-structured code, you will know about every exception that can occur, and can catch those specifically. If you don't know how a particular exception can be thrown, then don't catch it, just-in-case. When it happens, you can then figure out the exception, what caused it, and then catch it.

Elie
+3  A: 

Catching random exceptions is bad. What then?

  • Ignore them? Excellent. Let me know how that works for them.
  • Log them and keep running? I think not.
  • Throw a different exception as part of crashing? Good luck debugging that.

Catching exceptions for which you can actually do something meaningful is good. These cases are easy to identify and maintain.

S.Lott
+6  A: 

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.

Aaron Digulla
+3  A: 

Can I just say as an aside here that every time one of my co-workers writes a method signature with "throws Exception" instead of listing the types of exceptions the method really throws, I want to go over and shoot them in the head? The problem is that after a while you've got 14 levels of calls all of which say "throws Exception", so refactoring to make them declare what they really throw is a major exercise.

Paul Tomblin
Agree wholeheartedly! Metaphorically, of course. Not actually advocating shooting anyone in any part of their person.
Bill Karwin
Just write a method called shootProgrammer(Programmer p) throws OutOfAmmoException
Elie
@Bill - is it ok if I smack them with a rolled up newspaper then?
Paul Tomblin
How about making them wash all the coffee cups festering in the break-room sink?
Bill Karwin
+4  A: 

If you're going to handle random exceptions, handle them in only one place - the very top of the application, for the purposes of:

  • presenting a friendly message to the user, and
  • saving the diagnostics.

For everything else, you want the most immediate, location-specific crash possible, so that you catch these things as early as possible - otherwise exception handling becomes a way of hiding sloppy design and code.

In most cases where the exception is predictable, it's possible to test ahead of time, for the condition that the exception handler will catch.

In general, If...Else is much better than Try...Catch.

ChrisA
I disagree. There are exceptions that you handle that way, but there are exceptions you handle down deep - for instance, some of my code throws a "ScheduleConflictException", and a few levels higher up there is code to make changes to the schedule and try again.
Paul Tomblin
@Paul, "In most cases," and I think personal exceptions are an exception. In this case you are creating an exception to handle higher up, and I don't see this as what cris5gd was considering as a general case.
he_the_great
@Paul And this one sounds like that shouldn't be an exception at all...
Stephan Eggermont
@Stephan, the code that says "add this to the schedule" is quite a few layers above the code that evaluates if the current schedule will work, and an exception is the best way to get that information up through all the layers.
Paul Tomblin
+6  A: 

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.

Bill Karwin
Am I showing my age by saying I'm immediately reminded of printf printing "not a typewriter" no matter what errno was?
Paul Tomblin
+2  A: 

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.

RoadWarrior
+1 for 'nailing the corpse' analogy
ChrisA
A: 

I've found "try" "catch" blocks to be very useful, especially if anything realtime (such as accessing a database) is used.

Too many? Eye of the beholder.

I've found that copying a log to Word, and searching with "find" -- if the log reader does not have "find" or "search" as part of its included tools -- is a simple but excellent way to slog through verbose logs.

It certainly seems "defensive" in the ordinary sense of the word.

I've found, through experience, to follow whatever your manager, team-leader, or co-worker does. If you're just programming for yourself, use them until the code is "stable" or in debug builds, and then remove them when done (or if done only in debug mode, this happens automatically in release mode).

A: 

In C++ the one reason to write lots of try/catch blocks is to get a stack trace of where the exception was thrown. What you do is write a try/catch everywhere, and (assuming you aren't at the right spot to deal with the exception) have the catch log some trace info then re-throw the exception. In this way, if an exception bubbles all the way up and causes the program to terminate, you'll have a full stack trace of where it all started to go wrong (if you don't do this, then an unhandled C++ exception will have helpfully unwound the stack and eradicated any possibility of you figuring out where it came from).

I would imagine that in any language with better exception handling (i.e. uncaught exceptions tell you where they came from) you'd want to only catch exceptions if you could do something about them. Otherwise, you're just making your program hard to read.

Michael Kohne