|
First, if you write an exception for it, it's not "unexpected".
Second, exceptions should only be used for stuff you can't control via code (access to resources, ie network, files, services, etc). User input errors, on the other hand, should be handled with UI messages to the user, and only after being verified as being correct (or as correct as you can verify) should the application be permitted to use said data.
".45 ACP - because shooting twice is just silly" - JSOP, 2010 ----- You can never have too much ammo - unless you're swimming, or on fire. - JSOP, 2010 ----- When you pry the gun from my cold dead hands, be careful - the barrel will be very hot. - JSOP, 2013
|
|
|
|
|
John Simmons / outlaw programmer wrote: First, if you write an exception for it, it's not "unexpected".
Counterexample:
{
try
{
}
catch(...)
{
}
}
I'm retired. There's a nap for that...
- Harvey
|
|
|
|
|
For desktop, or similar, applications, exceptions are mostly used to handle really unexpected behavior. Corrupted data, missing resources and other errors that prevent the application from running. Errors that can be caused by a user, should be handled differently.
On the other hand we have api/framework, i.e. backend oriented, development, where specific exceptions can help to identify the problem. Here everything what is not in the specification should throw an exception, with a clear identification and error message, to prevent confusion.
At least for PHP and C# it's the way i do things. Some may prefer another method, but i think that's the best way to point out an error. Even if it's a small one.
|
|
|
|
|
Usual errors should be catched programmatically
|
|
|
|
|
Need a better reason??
Life is too shor
|
|
|
|
|
...but they have a crucial role to play.
Exceptions are best used to handle decisions that are outside the scope of the current context. One of the main sources of such problems is external resource constraints.
To put this in others words, the normal control flow should define "this is how the logic of this algorithm works, assuming all external resources are available. If not, punt to the higher level context manager to handle the situation gracefully."
So exceptions help maintain the simplicity of the code and guard against violations of the SRP (single responsibility principle).
|
|
|
|
|
|
I don't think it was said anywhere here, but it also depends on the language. In C++, it is well known (see Scott Meyer's Essential C++ series) that exception handling causes all sorts of extra code and inefficient behavior by the compiler. This is mainly to prevent resource leaks on the 2 control paths when exceptions are and are not thrown. On the other hand, in garbage collected languages such as java and C#, the resource leaks don't happen and programming with exceptions is much more accepted and in fact the norm. Many of the builtin classes use and expect a large amount of exception handling to use properly.
In any case, I (and I know a lot of others) consider exception handling to be misused and overused and generally poor style, even with garbage collection taking place. Use of exceptions adds a second flow of control in a program, with the result that structured programming principles are violated; the smallest demon in the pack is the fact that debugging is harder on an exception control path.
I'm retired. There's a nap for that...
- Harvey
|
|
|
|
|
|
I had to select at least one item from the list to satisfy the "Vote" button... but in fact, none of the choices qualifies.
I'm retired. There's a nap for that...
- Harvey
|
|
|
|
|
I agree and I reported it in Bugs&Sugs. The only other valid option is to select them all.
|
|
|
|
|
data suplied by the user
This is not the exception, it is the rule
M.D.V.
If something has a solution... Why do we have to worry about?. If it has no solution... For what reason do we have to worry about?
Help me to understand what I'm saying, and I'll explain it better to you
Rating helpful answers is nice, but saying thanks can be even nicer.
|
|
|
|
|
Raymond Chen quoting from memory: an exception is truly exceptional.
I voted bad code; while not being an exception, it is better to catch (not consume !) and terminate.
The others are *not* exceptions, but conditions any software should handle:
- failed network connection: expected condition. Program should implement this and be prepared to re-open network (or restart itself, if that's an option). I don't see Starcraft crashing because network is down. Eventually gives up and you lose, that's all. Or browsers, for that matter.
- external resource unavailable: this can happen even more than no network. Simply retry.
- backend server fails: if we're talking about server software, maybe, but even in this case, a reload/restart should be devised. Qualifies as an exceptional condition.
- local resource: this is a programming error, not exception. The single documented example I remember is when In-page IO exception may occur with memory mapped files. This is documented in MSDN (I remember I fixed a VERY long scanning procedure which exhausted paging file).
- timeout: hardly exceptional. Happens all the time. That's what the nice spinning bitmaps are for.
- invalid parameter values: let's say depends, but any function should define at the beginning what it can process and what not. The single exception I can see is when input parameters *modifies* while function is executing, but that's what pure functions are for: copy the input parameters and work on them. Only if those parameters are externals (i.e. a file HANDLE passed is closed while function is attempted to read, but this falls back to "local resource access fails").
- invalid data supplied by user is not exceptional. They do it all the time.
-
|
|
|
|
|
|
I must disagree with you (and Raymond Chen) regarding the rationale for exceptions. An exception should be thrown at any point where:
1. An error (or other fault) has occurred, AND
2. There are a number of equally valid responses to this error (or fault), AND
3. The current module does not possess the information necessary to distinguish between them
Logic and parameter errors (e.g. passing null to a function that expects a valid pointer) are not exceptional in the sense meant here, and neither are most user input errors. However, all other cases could be exceptional.
If you have an important point to make, don't try to be subtle or clever. Use a pile driver. Hit the point once. Then come back and hit it again. Then hit it a third time - a tremendous whack.
--Winston Churchill
|
|
|
|
|
3 - If the current module does not know what to do, it can either return an error code to caller (and log an error), or pass local error info along with error to upper call. If nobody knows what to do with the data, we don't crash the program, but finish with error.
1 (An error (or other fault)) is too generic.
Errors can occur at any time, suppose you read a JSON (last of my examples) but the file is not ANSI, but UTF-8. This (Jansson's json_loadf, for clarity) is not an exception, it simply means "we do not know how to read BOM marker".
Fault - depends what do you mean. If fault means program flow disruption or program starting affecting other unrelated data, it is an exception (that's why KeBugCheckEx exists).
2 - Equally valid responses can exists. Suppose you need to do two allocations and either can fail with ENOMEM. The result is indeed ENOMEM, but we don't know which one failed. And we do not need to know - ENOMEM is enough. (Not sure if this was a good example, though).
|
|
|
|
|
Well, using of Exceptions in the code does not mean the crush of the program itself.
Its a valid and quite commonly used method of informing the calling code about... you know... exceptional situation.
All Microsoft .NET libraries throw exceptions, lots of others do the same.
IMHO, the only invalid cases of throwing Exception are: hiding of the bad code (it must be fixed) and user input errors (they must be handled gracefully).
|
|
|
|
|
True for .NET. But we're not talking specifically about .NET.
What do you do in C? RaiseException just because you encountered ERROR_FILE_NOT_FOUND?
No. This is just a legit error returned by a system call; what do you do next depends on program logic. It can be a stopper - meaning, for example, a critical configuration file is missing, usually equal with an installation error - or can be a check for "is the user profile created?", and, if not found, create it now. In any case, trying to read from a non-existing file is not an exception.
As I am not in love with .NET approach - if I'm formatting a date/time from an invalid string, this is not an exception, is it just invalid data. Exception would be to have a *valid* string and the conversion call bonk, and even in this case, it can be anything else from assumed culture being not the expected one etc.
Imagine this sequence in an imaginary language:
assert(get_user_locale() == "en-us");
...
datetime = convert(
get_user_locale(),
enUSString)
Is this an exception? No. It is just my program not handling WM_SETTINGCHANGE.
|
|
|
|
|
Well, as you mentioned, it all "depends on program logic". Or, more precise, on System Design Documentation.
I just wanted to point out that exceptions is one of programming language features and they are perfectly valid to use appropriately in any programming language allowing exceptions.
|
|
|
|
|
Bad code and invalid parameters should be caught using an assert() statement or equivalent. The idea here is that if these bugs occur, you have a serious logic error in your code, and the program should terminate immediately - even if recovery is possible, it is no longer safe.
User input, sensor input, etc. should be validated. A user input validation error may be fixed by asking the user to correct the error.
Bad sensor input cannot be fixed, but some sort of low-level handling policy should be in place - filtering of extreme values, smoothing, etc. Only if the data are verifiably erroneous (e.g. because of a bad sensor) should an exception be thrown - this is similar to the case of a bad network connection, where no data are available. Note that if a verified reading exceeds the "safe" range, this is not exceptional; it should be handled in the normal code, just like any other reading.
A network error etc. cannot be handled at the low level - the network I/O module has no way to know whether it should retry the operation, fall back to an backup link, etc., and therefore throwing an exception is the appropriate way to handle this.
If you have an important point to make, don't try to be subtle or clever. Use a pile driver. Hit the point once. Then come back and hit it again. Then hit it a third time - a tremendous whack.
--Winston Churchill
|
|
|
|
|
When network is not available, you still have data: the error code (WSAENOTAVAIL or whatever subsystem reported is down).
|
|
|
|
|
Cristian Amarie wrote: When network is not available, you still have data: the error code (WSAENOTAVAIL or whatever subsystem reported is
down).
The issue here is that the O/S network API reported an error; how should this error be handled by our program?
We may, for example:
1. Retry the operation on the same network link
2. Attempt the operation on a backup link
3. Abort the transaction
4. Queue the transaction for later attempts
5. ...
The module that called the O/S network API has no idea how to proceed, and therefore an exception that transfers control to a higher level is appropriate.
This is not true, for example, for bad user input. In that case, the correct action is usually to ask the user to enter the correct data.
If you have an important point to make, don't try to be subtle or clever. Use a pile driver. Hit the point once. Then come back and hit it again. Then hit it a third time - a tremendous whack.
--Winston Churchill
|
|
|
|
|
So you're using exceptions in this case as a control flow. Not sure if this is the exceptions role, when a simple
SetLastErrorSuperEx(__FILE__, __LINE__, GetLastError(), L"Johnny Bravo was here.");
return false; would do the job. (SetLastErrorSuperEx left as exercise for the user).
|
|
|
|
|
No, I am not using exceptions in order to control flow. I am using them in order to:
1. Pass the error up to a layer that has the context to handle the error.
2. Ensure that the error is handled. (An unhandled exception crashes the program.)
This, IMO, is a more robust way of ensuring that errors get handled appropriately.
[Note that your SetLLastErrorSuperEx() API is often part of the exception handling mechanism. The missing parts are the stack unrolling, calling of destructors, etc. It is these (missing) parts of exception processing that make it more robust than simply returning an error code.]
If you have an important point to make, don't try to be subtle or clever. Use a pile driver. Hit the point once. Then come back and hit it again. Then hit it a third time - a tremendous whack.
--Winston Churchill
|
|
|
|
|
|