SoftwareEngineering
DesignByContract
ConditionSystems
SpaghettiCode
- Exceptions: signal -> handle/recover ==> Stack unwinds
- Conditions (Lisp): signal -> recover -> select strategy for recovery (restart) ==> Stack not necessarily unwinds
- Signals move up the call-stack until someone is interested in them.
- http://www.joelonsoftware.com/items/2003/10/13.html --Exceptions, rant by JoelSpolsky
- Policy:
- Never throw an exception of my own.
- Always catch any possible exception that might be thrown by a library I'm using on the same line as it is thrown and deal with it immediately.
- Why?
- They are invisible in the source code.
- They create too many possible exit points.
- Solution
- A better alternative is to have your functions return error values when things go wrong, and to deal with these explicitly, no matter how verbose it might be.
- http://discuss.fogcreek.com/joelonsoftware/default.asp?cmd=show&ixPost=77575 interesting discussion
- Contrary to your comment about having to sprinkle catch clauses all ove the place, the crucial thing to understand about exceptions is that you should never catch an exception that you don't know how to handle, and most of the time, the current function cannot do anything about it.
It all boils down to allmost only catching exceptions in a central place (like main i c++). Once you realize that, life becomes so much simpler.
- The best example I can think of is when we cede control to a listener in an observer pattern, we try / catch runtime exception because we don't trust observers. I don't think there is an elegant way to do that with errors & return codes. (although there are always ways) We leaving catching Exception to a higher level, and then throwable in the main method.
I don't think so. Return-values (RV)? Better not. Handling RV has to be adapted all the time new RV enter. While that has to be done with Exceptions, too. You'll notice if you forget this with exceptions. You won't notice when using RV. Will you?
In exception-based code one must be prepared that any method-call (constructor, etc.) may fail!
General design principle: Don't commit data until they are ready.
- http://blogs.msdn.com/oldnewthing/archive/2005/01/14/352949.aspx --Cleaner, more elegant, and harder to recognize
- Consequently, when I write code that is exception-based, I do not have the luxury of writing bad code first and then making it not-bad later. If I did that, I wouldn't be able to find the bad code again, since it looks almost identical to not-bad code.
Be careful with side-effects!
Write exception-based code good the first time.
- Some tips on Exception Handling
- Instead of being embarrassed about exceptions occurring in your code, let the exceptions bubble up through the call-hierarchy to a place where you have enough contextual information to handle the exception.
- Avoiding flow-control through exceptions has numerous benefits, apart from increased performance; you’re code turns out to be more readable.
- Instead of catching exceptions: TryParse?, DoesFileExist?...
- Error and Exception Handling
- When should I use exceptions?
- simple: whenever the semantic and performance characteristics of exceptions are appropriate
- wrong: is this an exceptional (or unexpected) situation? -> The problem is that one person's ``exceptional is another's ``expected [...] After all, if you check for an error condition, then in some sense you expect it to happen, or the check is wasted code.
- do we want stack unwinding here?, Can I afford stack unwinding here?
- in time critical code, throwing an exception should be the exception, not the rule.
- Avoid catch(...) when possible
- Exception handling@Wikipedia
- However, there are some problems where the use of exceptions can dramatically simplify the algorithm used and some people regard exceptions as just another coding construct that can be applied to help solve a problem.
- Exception Handling
- Problems
- Hides Unrelated Errors
- suddenly program flow jumps several levels up the call stack and resumes somewhere else
- An exception handler which was added to deal with a particular event (say, a divide by zero), sometimes ends up suppressing all similar events within a large area.
- No Thought
- Remove bugs by catching resulting exceptions.
- Hanging Resources
- CPU Time
- Sometimes a program will call a function which does a lot of work and has a high probability of failing. In these cases it would be more efficient to check your inputs for obvious signs of failure first. There is no point in letting the poor computer thrash away on a problem which is doomed to failure.
- Advantages
- Reliability
- In certain situations: sure there may be memory leaks and data corruption, but that is probably better than an application crash.
- Such a handler should log the error and alert the user that now would be a really good time to save any data and restart.
- Rare Events
- Checking each possible error condition in advance of every file operation would be ludicrous.
- This is exactly what exception handling is designed for.
- Risky Calls
- Exception handlers are reasonably good at providing isolation between an application and 3rd party code.
- Quick Hacks
- I find it helpful to think of an exception handler as an ejection seat: use it to save yourself in an emergency, but do not use it for routine issues. Think twice before using an exception handler.
- Best Practices for Exception Handling
- Never use exceptions for flow control
- In a flow-control situation, the stack trace would be ignored, since the client just wants to know how to proceed.
- Why exceptions shouldn't be used for flow control
- What you want is not a normal return, it's an _ab_normal return. Something like returning (int)-1 when the function's only expected to return char, or (in Python) returning None. The problem? These things are SO easy to ignore!!!! C is famous for noiselessly casting the -1 to a char (look at the old Bash security bug), and Python is even worse -- any return you can possibly make will almost certainly fit in noiselessly with anything you do with it. This is Python's ease of use.
- You ought to feel lucky. Some respected programming gurus recommend calling abort() on any odd results, to make misuse of their API as blatantly obvious as possible.
- In DesignByContract terms, a service may throw exceptions for two reasons:
- The caller violated the precondition of the contract (passing an invalid parameter, for instance). Note that ALL such exceptions are supposed to be avoidable, given enough diligence on the caller's part.
- The service was unable to fulfill the contract due to the moral equivalent of force majeure (out of disk space, etc.). No action the caller could possibly take beforehand would obviate the need to catch/propagate these exceptions.
- Exception handling, DesignByContract BertrandMeyer, Eiffel?
- The failure of an operation is an exception for the routine that needed the operation.
Exceptions are escape Continuations [1]
in .NET, the stack trace is created at the time you throw the exception. In Java, it's created at the time you create the exception;
use
throw;
instead of
throw excInstance;
The Question
Better use Exceptions or Return Values? Should one write exceptions-based code or error-based code?
Checked vs. Unchecked
The trick, you see, is that RuntimeExceptions don't need to be declared, and all of the code you were thinking of writing just got a whole lot cleaner-looking. [2]
Resource Acquisition Is Initialization (RAII)
The technique combines acquisition and release of resources with initialization and uninitialization of variables.