views:

1154

answers:

10

I've heard this on the Internet. For instance, Google's Go language has no exceptions as a design choice, and Linus of Linux fame has called exceptions crap. I am just wondering why?

+18  A: 

Exceptions are not bad per se, but if you know they are going to happen a lot, they can be expensive in terms of performance.

The rule of thumb is that exceptions should flag exceptional conditions, and that you should not use them for control of program flow.

Robert Harvey
@Robert: "you should not use them for control of program flow", I've not thought about it this way, new perspective for me :P +1
o.k.w
It also really depends on the language. It's difficult to avoid exceptions if you're programming in Java for example.
Charles Salvia
@Charles: I think the point is that exceptions are appropriate in situations that indicate a bug, misconfigured system, or unreasonable inputs. Most Java library exceptions can be avoided in "normal workflow" code.
Artelius
they don't have to cost much. for example, you can implement a "try" that costs zero execution time, and have "throw" look up exception handlers in a table based on the caller addresses it sees on the stack... I would say that the biggest reasons not to use exceptions are not at all related to performance.
asveikau
+6  A: 

Typical arguments are that there's no way to tell what exceptions will come out of a particular piece of code (depending on language) and that they are too much like gotos, making it difficult to mentally trace execution.

http://www.joelonsoftware.com/items/2003/10/13.html

There is definitely no consensus on this issue. I would say that from the point of view of a hard-core C programmer like Linus, exceptions are definitely a bad idea. A typical Java programmer is in a vastly different situation, though.

Tim Sylvester
C code has exceptions sort of, just in a different way. You need to wrap every call to a non trivial function in ifs which makes using that language a headache!
RCIX
There's also the `setjmp`/`longjmp` stuff, which is pretty bad.
Tim Sylvester
Do you really want to take the advice of a man who values Duct Tape programmers and who does not believe that unit tests are necessary? http://www.joelonsoftware.com/items/2009/09/23.html
TrueWill
+3  A: 

Exceptions aren't bad. They fit in well with C++'s RAII model, which is the most elegant thing about C++. If you have a bunch of code already that's not exception safe, then they're bad in that context. If you're writing really low level software, like the linux OS, then they're bad. If you like littering your code with a bunch of error return checks, then they not helpful. If you don't have a plan for resource control when an exception is thrown (that C++ destructors provides) then they're bad.

paul
RAII is useful even without exceptions.
Mark Ransom
however, exceptions aren't useful without RAII (or some other automatic resource management).
Greg Rogers
A: 
  • Exception not being handled is generally bad.
  • Exception handled badly is bad (of course).
  • The 'goodness/badness' of exception handling depends on the context/scope and the appropriateness, and not for the sake of doing it.
o.k.w
+7  A: 

From the perspective of golang, I guess not having exception handling keeps the compiling process simple and safe.

From the perspective of Linus, I understand that kernel code is ALL about corner cases. So it makes sense to refuse exceptions.

Exceptions make sense in code were it's okay to drop the current task on the floor, and where common case code has more importance than error handling. But they require code generation from the compiler.

For example, they are fine in most high-level, user-facing code, such as web and desktop application code.

ddaa
+2  A: 

Theoretically they are really bad. In perfect mathematical world you cannot get exception situations. Look at the functional languages, they have no side effects, so they virtually do not have source for unexceptional situations.

But, reality is another story. We always have situations that are "unexpected". This is why we need exceptions.

I think we can think of exceptions as of syntax sugar for ExceptionSituationObserver. You just get notifications of exceptions. Nothing more.

With Go, I think they will introduce something that will deal with "unexpected" situations. I can guess that they will try to make it sound less destructive as exceptions and more as application logic. But this is just my guess.

Mike Chaliy
"Look at the functional languages, they have no side effects, so they virtually do not have source for unexceptional situations." That is a gross overstatement.
Stephen C
Could you please elaborate on this?
Mike Chaliy
What's 5/0 in math? Arcsin(200)? Sqrt(-1)? Math has loads of exceptional situations.
Robert Fraser
This is not execptional situatuations... they just have no meaning... and because of that could be implemented as exceptions... but also could be implemented as vialations of preconditions.. so its depends on technical implementation.
Mike Chaliy
+15  A: 

Exceptions make it really easy to write code where an exception being thrown will break invariants and leave objects in an inconsistent state. They essentially force you to remember that most every statement you make can potentially throw, and handle that correctly. Doing so can be tricky and counter-intuitive.

Consider something like this as a simple example:

class Frobber
{
private:
    int m_NumberOfFrobs;
    FrobManager m_FrobManager;

public:

    void Frob()
    {
        m_NumberOfFrobs++;

        m_FrobManager.HandleFrob(new FrobObject());
    }
};

Assuming the FrobManager will delete the FrobObject, this looks OK, right? Or maybe not... Imagine then if either FrobManager::HandleFrob() or operator new throws an exception. In this example, the increment of m_NumberOfFrobs does not get rolled back. Thus, anyone using this instance of Frobber is going to have a possibly corrupted object.

This example may seem stupid (ok, I had to stretch myself a bit to construct one :-)), but, the takeaway is that if a programmer isn't constantly thinking of exceptions, and making sure that every permutation of state gets rolled back whenever there are throws, you get into trouble this way.

As an example, you can think of it like you think of mutexes. Inside a critical section, you rely on several statements to make sure that data structures are not corrupted and that other threads can't see your intermediate values. If any one of those statements just randomly doesn't run, you end up in a world of pain. Now take away locks and concurrency, and think about each method like that. Think of each method as a transaction of permutations on object state, if you will. At the start of your method call, the object should be clean state, and at the end there should also be a clean state. In between, variable foo may be inconsistent with bar, but your code will eventually rectify that. What exceptions mean is that any one of your statements can interrupt you at any time. The onus is on you in each individual method to get it right and roll back when that happens, or order your operations so throws don't effect object state. If you get it wrong (and it's easy to make this kind of mistake), then the caller ends up seeing your intermediate values.

Methods like RAII, which C++ programmers love to mention as the ultimate solution to this problem, go a long way to protect against this. But they aren't a silver bullet. It will make sure you release resources on a throw, but doesn't free you from having to think about corruption of object state and callers seeing intermediate values. So, for a lot of people, it's easier to say, by fiat of coding style, no exceptions. If you restrict the kind of code you write, it's harder to introduce these bugs. If you don't, it's fairly easy to make a mistake.

Entire books have been written about exception safe coding in C++. Lots of experts have gotten it wrong. If it's really that complex and has so many nuances, maybe that's a good sign that you need to ignore that feature. :-)

asveikau
Interesting answer, however it does not reflect anything in my programming experience. So I guess it's either culture-specific (maybe more of a problem in Java or C++ than, say, Python) or domain-specific.
ddaa
Exceptions written in a managed language using a try-catch-finally pattern should never leave invalid state if they are written properly; since the finally block is guaranteed to be executed, objects can be deallocated there. The rest should be taken care of by variables going out of scope and garbage collection.
Robert Harvey
@ddaa The issue is definitely possible in Python. The result is typically a difficult to reproduce bug. Perhaps you've been especially meticulous, or lucky. But then, you are right that it's more of an issue in C++, where the most common bug from poor EH is a memory leak. I tried to emphasize that leaks aren't the most serious problem. @Robert GC will mitigate memory leaks, but I'm not sure managed code will free you from programmer error. In particular if someone is not paying attention to exception safety because they don't think it's a problem in their language, that's not a great sign.
asveikau
IMO, we could handle errors by return values, sometimes we have to use exceptions because the 3rd parties will throw exceptions --- Is there any advantages of exception over return value?
lz_prgmr
+3  A: 

Exceptions in and of themselves are not "bad", it's the way that exceptions are sometimes handled that tends to be bad. There are several guidelines that can be applied when handling exceptions to help alleviate some of these issues. Some of these include (but are surely not limited to):

  1. Do not use exceptions to control program flow - i.e. do not rely on "catch" statements to change the flow of logic. Not only does this tend to hide various details around the logic, it can lead to poor performance.
  2. Do not throw exceptions from within a function when a returned "status" would make more sense - only throw exceptions in an exceptional situation. Creating exceptions is an expensive, performance-intensive operation. For example, if you call a method to open a file and that file does not exist, throw a "FileNotFound" exception. If you call a method that determines whether a customer account exists, return a boolean value, do not return a "CustomerNotFound" exception.
  3. When determining whether or not to handle an exception, do not use a "try...catch" clause unless you can do something useful with the exception. If you are not able to handle the exception, you should just let it bubble up the call stack. Otherwise, exceptions may get "swallowed" by the handler and the details will get lost (unless you rethrow the exception).
Jeff Bramwell
Returning status is a tricky thing. I've seen far too much code that has a GetCustomer method returning a Customer entity on success or null on failure. In multiple cases the calling code never checked the result, but immediately accessed the Customer. This worked most of the time...
TrueWill
But if GetCustomer throws an exception instead of returning null, the client code still needs to handle the exception. Whether it's by checking for null or by handling exceptions, the responsibility lies with the client code - if it doesn't do what things properly, then either way sooner or later something will explode.
Chris
+10  A: 

The reason for Go not having exceptions is explained in the Go language design FAQ:

Exceptions are a similar story. A number of designs for exceptions have been proposed but each adds significant complexity to the language and run-time. By their very nature, exceptions span functions and perhaps even goroutines; they have wide-ranging implications. There is also concern about the effect they would have on the libraries. They are, by definition, exceptional yet experience with other languages that support them show they have profound effect on library and interface specification. It would be nice to find a design that allows them to be truly exceptional without encouraging common errors to turn into special control flow that requires every programmer to compensate.

Like generics, exceptions remain an open issue.

In other words, they haven't yet figured out how to support exceptions in Go in a way that they think is satisfactory. They are not saying that Exceptions are bad per se;

Stephen C
I hate it when they hide information by putting it in the FAQ. :)
brian d foy
+3  A: 

I disagree with "only throw exceptions in an exceptional situation." While generally true, it's misleading. Exceptions are for error conditions (execution failures).

Regardless of the language you use, pick up a copy of Framework Design Guidelines: Conventions, Idioms, and Patterns for Reusable .NET Libraries (2nd Edition). The chapter on exception throwing is without peer. Some quotes from the first edition (the 2nd's at my work):

  • DO NOT return error codes.
  • Error codes can be easily ignored, and often are.
  • Exceptions are the primary means of reporting errors in frameworks.
  • A good rule of thumb is that if a method does not do what its name suggests, it should be considered a method-level failure, resulting in an exception.
  • DO NOT use exceptions for the normal flow of control, if possible.

There are pages of notes on the benefits of exceptions (API consistency, choice of location of error handling code, improved robustness, etc.) There's a section on performance that includes several patterns (Tester-Doer, Try-Parse).

Exceptions and exception handling are not bad. Like any other feature, they can be misused.

TrueWill