Beta
×

Welcome to the Slashdot Beta site -- learn more here. Use the link in the footer or click here to return to the Classic version of Slashdot.

Thank you!

Before you choose to head back to the Classic look of the site, we'd appreciate it if you share your thoughts on the Beta; your feedback is what drives our ongoing development.

Beta is different and we value you taking the time to try it out. Please take a look at the changes we've made in Beta and  learn more about it. Thanks for reading, and for making the site better!

The Scourge of Error Handling

Soulskill posted about a year and a half ago | from the a-user-did-what? dept.

Programming 536

CowboyRobot writes "Dr. Dobb's has an editorial on the problem of using return values and exceptions to handle errors. Quoting: 'But return values, even in the refined form found in Go, have a drawback that we've become so used to we tend to see past it: Code is cluttered with error-checking routines. Exceptions here provide greater readability: Within a single try block, I can see the various steps clearly, and skip over the various exception remedies in the catch statements. The error-handling clutter is in part moved to the end of the code thread. But even in exception-based languages there is still a lot of code that tests returned values to determine whether to carry on or go down some error-handling path. In this regard, I have long felt that language designers have been remarkably unimaginative. How can it be that after 60+ years of language development, errors are handled by only two comparatively verbose and crude options, return values or exceptions? I've long felt we needed a third option.'"

cancel ×

536 comments

Sorry! There are no comments related to the filter you selected.

The third option (5, Funny)

Anonymous Coward | about a year and a half ago | (#42225567)

Ignoring the error completely, data integrity or planned functioning be damned.

Re:The third option (2)

MacDork (560499) | about a year and a half ago | (#42225619)

That's still catch blocks:

try { throw VeryImportantException(); } catch (VeryImportantException e) { throw UnimportantException(); };

You'd never do this on purpose, but its rather easy to accomplish in practice.

Re:The third option (1)

MacDork (560499) | about a year and a half ago | (#42225649)

Also: try { throw ImportantException(); } finally { throw UnimportantException(); }; The unimportant exception wins again.

Re:The third option (0)

Anonymous Coward | about a year and a half ago | (#42225707)

No, terminate() wins because the ImportantException was still active when the UnimportantException was thrown. Goodbye, app.

Miine is better: increases revenue (0)

Anonymous Coward | about a year and a half ago | (#42225809)

Also: try { throw ImportantException(); } finally { throw UnimportantException(); }; The unimportant exception wins again.

try { throw HolyFuckTheWorldsComingToAnEnd(); } finally { throw PayMeMegaBucksToFix(); };

Re:The third option (4, Insightful)

pla (258480) | about a year and a half ago | (#42225779)

You'd never do this on purpose, but its rather easy to accomplish in practice.

You have too much faith in humanity, friend!

I hate hate hate the exception-handling model of dealing with errors, because in practice, I've seen very, very little code that actually handles the error. People either:
1) Use far too coarse grained a "try" (as in, on the entire function), giving almost no possibility of knowing what actually happened or how to recover,
2) Use the "catch" just to tell the user "golly, it broke, try again later" rather than accidentally revealing the ugly (but meaningful) exception text,
3) Assume nothing in the "try" could actually fail and only do it to satisfy their company's code auditors, so the catch does... nothing, or
4) (My "favorite") - copy the entire body of the "try" into the "catch" and blindly do it again!

When used correctly, exception handling doesn't make your code cleaner, it reduces to a slightly more verbose way of checking return values. You should, if you want any hope of really dealing with the error, wrap every call in its own try/catch. I have not ever seen that done (and honestly, I can't claim I do it as religiously as I should either - I tend to trust my own code (big mistake), and only do that for external calls).


Then again, how do you handle the system volume suddenly vanishing out from under you? So, perhaps the coarse-grained "golly, it broke, try again later" folks have the right idea. ;)

Re:The third option (5, Informative)

Anonymous Coward | about a year and a half ago | (#42225875)

Sounds to me like you actually hate abusive exception handling. Exceptions that are in relevant places and handle the errors in meaningful ways are good. I've seen lots of code that actually handles the error, but then I work with competent people (and yes, that is a lovely thing).

Exception handling can make code cleaner. I'd much rather see a nice exception than return value checking as I can instantly see what kind of error is expected and what should happen if it occurs.

Please don't dismiss a step forward from return value checking just because you're unfortunate enough to have never worked with anyone who uses it properly.

With Teutonic Sharpness (-1)

Anonymous Coward | about a year and a half ago | (#42225899)

"if you want any hope of really dealing with the error, wrap every call in its own try/catch" ..I conclude that you are advocating return values as the sole mechanism of procedure/method error handling. Because that is equivalent to using try/catch for single calls.

Thinking about that I guess you are right. Exceptions are crap and we can see it every day in some Java Crapola that farts stack traces as if it had eaten beans. Hmm Java Beans ?

Proper return value checking and handling is a core part of every proper program and the whole premise of "handling errors is sooooo laborious" is at fault. Stop being a pussy, handle your errors in the POSIX API fashion. The result will be a reliable, nice to work-with piece of software. And if you are an amateur, please quit writing software.

Re:The third option (4, Insightful)

Simply Curious (1002051) | about a year and a half ago | (#42225903)

I would say that it is much less verbose in the case where errors need to be propagated upward. This is exactly why not every function call has a try/catch around it. Suppose I am writing a function that accepts a filename, interprets the text in the file, and then returns some modified version of the text. With error codes, I would need to explicitly check that open_file has returned a valid file handler. I can't do anything without a valid file, so I then need to propagate the error upward. On the other hand, with exceptions, I could simply not catch that exception from open_file. I can't do anything to recover, so I should let the exception propagate upward to wherever called me, and then let them deal with it.

Re:The third option (5, Insightful)

mrvan (973822) | about a year and a half ago | (#42226027)

I think you are focussing too much on java-style compiler-forced error handling. To me, the essence of try/catch error handling is that you only catch errors if you can deal with them. If you can't (the majority of cases), let is escalate, all the way up to the user (or a log file) if needed. I think there are three sane ways of using a try/catch: (1) to actually deal with the error (this is by far the rarest), (2) mainly in loops of more-or-less independeny actions: to log the error, reset state, and continue working, and (3) at the top level, to log the error and display something less meaningful but less scary to the end user.

I think it is a bad design decision to impose static checking on declared 'throws' statements, because that forces routines to catch stuff that they can't handle, or declare a meaningless list of everything every called routine could ever throw. In essence, it couples the signalling and handling again that exceptions were supposed to decouple.

Another nicety of exceptions compared to return values is that the semanitcs of "something went wrong" is clear. This makes it possible to e.g. have a wrapper function that begins a transaction and commits or rollbacks it depending on the outcome (e.g. https://docs.djangoproject.com/en/dev/topics/db/transactions/?from=olddocs#django.db.transaction.commit_on_success [djangoproject.com] )

Re:The third option (1)

MurukeshM (1901690) | about a year and a half ago | (#42225807)

What? Why? It should be:
try
{
blahBlah = blah(); //throws exception
} catch (Exception e)
{ //Do whatever War is good for.
}

Re:The third option (4, Interesting)

Yetihehe (971185) | about a year and a half ago | (#42225723)

That's the philosophy of erlang, "Let it crash". Apparently this leads to some of the most reliable systems. http://www.erlang.org/download/armstrong_thesis_2003.pdf [erlang.org]
Apparently OP didn't heard about it, because this is the third way.

Re:The third option (1)

Anonymous Coward | about a year and a half ago | (#42225831)

Erlang can get away with that because Erlang is built to handle crashes for you. If my non-erlang system crashes then it doesn't restart. It just stops running. This is unacceptable.

Erlang restarts end up being very much like exception handling. The difference being that the coder doesn't have to explicitly handle them. This is not always a good thing.

Re:The third option (1)

Yetihehe (971185) | about a year and a half ago | (#42225981)

It's only philosophy. In erlang you CAN catch errors (there is even try ... catch and throw). But typically you are encouraged to write programs so that when something fails, you just restart it. I've recently written a server in java which had errors and null pointer exceptions, but it survived, just logged the errors and restarted connection, so you CAN write something like this in other languages. Erlang just gives you some tools to make this even easier.

Re:The third option (5, Interesting)

Nerdfest (867930) | about a year and a half ago | (#42225869)

I've gotten to prefer using runtime exceptions with a general policy of "Throw as early as possible, catch as late as possible". Only catch if you can do something about it. It works very well, and keeps the code very clean.

Re:The third option (1)

White Flame (1074973) | about a year and a half ago | (#42225893)

That is only because most of telephony can get away with being stateless.

Re:The third option (1)

Yetihehe (971185) | about a year and a half ago | (#42225999)

Not only telephony. Also in erlang you can make stateful servers, you just don't have shared state. Instead you send messages about data changes between processes. It's like many people talking and updating their knowledge of some situation.

Re:The third option (1)

jythie (914043) | about a year and a half ago | (#42225805)

Over the years I have seen people try to push some kind of sci-fi ready 'graceful failure' where somehow programs simply survive errors without programmers actually needing to do anything... so in that model one doesn't need error handling. As one can imagine, such magical no-work systems have not panned out well in real life.

Re:The third option (2)

PRMan (959735) | about a year and a half ago | (#42225871)

Ignoring the error completely, data integrity or planned functioning be damned.

This is the option chosen by most developers...

Re:The third option (0)

Anonymous Coward | about a year and a half ago | (#42225911)

You see this a lot in example code, where error handling is often "left out for clarity".
Unfortunately the code is then copied as-is by inexperienced programmers.

This shows off a difference between the approaches - in the exception camp, if I write a quick-and-dirty Python script, it will fail noisily, with a user-unfriendly stack trace.
If I write a C or Go program ignoring any errors, it will swallow them silently.
I also see this more in Java due to the checked exceptions -- who hasn't seen something like
try {...} catch (Exception e) {} // Make the compiler shut up

Re:The third option (0)

Anonymous Coward | about a year and a half ago | (#42226025)

Another CPAN contributor heard from!!!! If I see *one more* case statement or value handling that doesn't do anything if all the planned cases aren't handled, I swear I'm going to write a CPAN module called "Verify::Security" that does nothing but randomize the bytes of all the other perl module files. I swear, it'll be decades before anyone notices!!!

here come the category theory nerds (0, Troll)

Anonymous Coward | about a year and a half ago | (#42225575)

Monadian beef bbq.

Yes Monads! (4, Interesting)

Weezul (52464) | about a year and a half ago | (#42225837)

Monads are fun for error handling. :)

I donno if they present exactly what the author might consider a third option though, well certainly they can present other options, like with the Either monad, but that's no simpler really.

Third option. (5, Funny)

Andy Prough (2730467) | about a year and a half ago | (#42225581)

I think MS already tried the blue screen.

ON ERROR GOSUB 30000 (3, Funny)

bunratty (545641) | about a year and a half ago | (#42225591)

BASIC has had it all along!

On Error Resume next (4, Informative)

xaxa (988988) | about a year and a half ago | (#42225661)

Visual Basic had:
On Error Resume Next

I last typed that when I was about 13...

The documentation [microsoft.com] shows a couple of valid uses for it.

Re:ON ERROR GOSUB 30000 (1)

TheGratefulNet (143330) | about a year and a half ago | (#42226021)

iirc, trs-80 BASIC allowed stuff like:

10 if a<0 then 100 else if a>0 then 200 else if a=0 then 300 else 400

the old if-then-else-else trick.

brings back memories, it does.

Errors (0)

Anonymous Coward | about a year and a half ago | (#42225625)

if (errno) goto error_handler;

error_handler:
if (errno == ENOMEM) enomem_handler();

void (enomem_handler) (void) {
  char *error_msg = "No more memory, aborting.\n";
  write(STDERR_FILENO, error_msg, strlen(error_msg));
  _exit(1);
}:

Re:Errors (1)

Smallpond (221300) | about a year and a half ago | (#42225763)

Yup. Errno has been around as long as UNIX system calls, so there are really 3 common mechanisms, not 2 as the article says.

Re:Errors (2)

interval1066 (668936) | about a year and a half ago | (#42225823)

errno is just a return code in other clothing.

Re:Errors (1, Insightful)

Smallpond (221300) | about a year and a half ago | (#42225975)

All code is just assembly language in other clothing.

People just doesn't get it (3, Insightful)

Anonymous Coward | about a year and a half ago | (#42225631)

Exceptions should NOT be used for 'normal' errors. They should be used for events that are, well, exceptional. A healthy program should NEVER raise an exception, but may deal with a lot of error conditions.

Re:People just doesn't get it (-1)

Anonymous Coward | about a year and a half ago | (#42225657)

Trying to select a language that makes up for poorly written code is a fool's game. A well written program doesn't NEED an error handler. This is nothing but poor programmers whining because they can't write good code. It's kind of like unemployed people whining because the jobless benefits aren't long enough.

Re:People just doesn't get it (0)

Anonymous Coward | about a year and a half ago | (#42225795)

Are you daft? No matter how "good" your code is there are plenty of error conditions to check for starting with the runtime environment, system permissions, etc, etc. If you're going to handle any form of input you'd better be checking that shit too.

Error checking is a PITA, but producing code that doesn't check for them and assumes everything is always sunny creates customers and/or users who are a PITA.

Re:People just doesn't get it (4, Interesting)

joe_frisch (1366229) | about a year and a half ago | (#42225829)

Software that interacts with the real world needs some way to handle errors. We have a distributed control system (MATLAB / EPICS based) that runs our accelerator (SLAC). The code needs to deal with a hardware device that is broken and has returned a nonsensical value, or does not return anything. This needs to be dealt with in some way - whether it is by throwing an exception or by checking the return from the routine that made the call. The error handling can be fairly complex, some devices are vital to operation and an error requires that the machine be stopped, others are at least partially redundant and you can continue to operate, though possibly with reduced capacity.

BTW: personnel safety and hardware protection are handled separately.

Re:People just doesn't get it (4, Insightful)

pla (258480) | about a year and a half ago | (#42225861)

A well written program doesn't NEED an error handler.

Okay, tough-guy... "The specified network name is no longer available". Explain how you avoid needing to handle that.

Re:People just doesn't get it (0)

Anonymous Coward | about a year and a half ago | (#42225929)

In his reality, that could never happen.

I think (0)

Anonymous Coward | about a year and a half ago | (#42225951)

..you are an idiot. Proper software diligently checks the error code of every method called. Real software is in the size of 50k to 50M lines of code and even star programmers sometimes make a mistake which will eventually be signalled by some error condition, probably a method/function which trips over some bad state. That error must be detected and reported.

Re:People just doesn't get it (1)

Smallpond (221300) | about a year and a half ago | (#42225817)

Exceptions should NOT be used for 'normal' errors. They should be used for events that are, well, exceptional. A healthy program should NEVER raise an exception, but may deal with a lot of error conditions.

[citation needed]

What is the basis of this strange belief? The non-error case should be simple and readable, not cluttered with tests for seldom-occurring errors. Putting a try-catch block around it pulls the messy error code out of it and is simpler to read and debug than inline code. Never worry about performance of error-handling code.

Re:People just doesn't get it (5, Insightful)

ruiner13 (527499) | about a year and a half ago | (#42226007)

I believe the reason for not wanting to throw exceptions unless really needed is that exceptions (and their handling) are relatively expensive and resource intensive operations. Most languages when exceptions are thrown do a lot of runtime stack analysis to, among other things, get a full stack trace. There are many research links on the interweb explaining how expensive it is in whatever language you happen to be using, but here is the first link I found: http://stackoverflow.com/questions/1282252/how-much-more-expensive-is-an-exception-than-a-return-value [stackoverflow.com]

In the case of the .net runtime, throwing an exception was > 1000x as expensive as using a return value, in processing time.

Re:People just doesn't get it (0)

Anonymous Coward | about a year and a half ago | (#42225937)

A healthy program should NEVER raise an exception

What is a healthy program?

  • A program where everything works as intended?
  • A program that works fine even after failing to connect to a server?
  • A program where everything fails and it is unable to do its work even with no corrupted state ?

AFAIK all three of those can be seen as healthy, so the only unhealthy state is one with corrupted memory and then calling abort() is the only sane thing to do, since handling corrupted memory is impossible (the cpu instructions themselves might be corrupted). Exceptions are an error handling mechanism, stating that healthy programs should not throw one is like stating a healthy community should not need a doctor.

Re:People just doesn't get it (2)

roninmagus (721889) | about a year and a half ago | (#42225941)

I think exceptions should be used at a reasonable point where the application cannot utilize the given parameters to continue.

For instance, Null argument exceptions. Your code should be written to assume that the arguments presented to it fit within the functional parameters of the code. An Exception should be thrown if it's determined they are not.

Another: SQL connection exceptions and other Network Exceptions. Your code should be written to assume that these resources are available. If they are not, that is a valid exception case.

Note I'm not saying the exception should crash the program. You catch it, report it, log it, move on.

Source: Years as a development consultant. If you've ever been to a hospital or even a walk-in clinic, chances are your MR and even your payment are a record in more than one of my client's databases.

Re:People just doesn't get it (0)

Anonymous Coward | about a year and a half ago | (#42226043)

For instance, Null argument exceptions. Your code should be written to assume that the arguments presented to it fit within the functional parameters of the code. An Exception should be thrown if it's determined they are not.

Nope. At least in server code, if someone passes you an argument you can't handle, just crash.

A core-dump will tell you _HOW_ you got those invalid arguments. An exception loses all that information and leaves you hunting through masses of code in the hope that you might be able to figure it out.

Re:People just doesn't get it (0)

Anonymous Coward | about a year and a half ago | (#42225943)

if(!file.isFile()) { //handle not a file
} else if(!file.exists()) { //backup parent directories until you find on that exists, then create each child folder going down along similar error handling
} else if(!file.canRead()) { //handle permission errors
} /* user or another program deletes the file */
try { //attempt to read file data
} catch { //repeat checking all the same errors, but this time within the exception framework //at least with good design each error handling code can be a function call, but then you got to pass around parameters and make sure they're not invalid. You skip those rechecks? You can't expect a new developer to know which variables are expected to be valid when. You expect them to read the method comments? Even on slashdot there are some who claim all code comments should be deleted and they never bother to read them. They claim the comments are out of date, but they're the ones who make them out of date. The lazy fuckers making my job writing 90%+ error checking and 10% application code.
}

I do write code this way. It really sucks, but we know exactly what and when something went wrong as soon as it goes wrong. Trying to unit test this sort of code is a nightmare. Exceptions make you double all your error checking code branches.

Exceptions in C++ (4, Insightful)

Anonymous Coward | about a year and a half ago | (#42225651)

While I have seen good error handing schemes in many languages, so far, I haven't seen anything as good as C++ exceptions combined with RAII. Exceptions alone aren't that great, but if you combine it with the way constructors / destructors work and compose in C++, it ends up working really well. A lot of languages with exceptions lack RAII. Java and C# have exceptions but don't have destructors (the language equivalent is much less useful than C++) much less ones that compose.

The only real problem is that lots of C++ code rely on return codes, no error handling at all, or poor use of exceptions and resource management. There are lots of C++ programmers who stumble on error handling code and haven't learned how to take advantage of the tools the language provides. Of course error handing logic can be quite hard, even if the language helps out a lot.

STM is also a great way of doing error handling. Transactions (like used in databases) make error conditions much easier. But they cannot be limited to databases; transactions in the file system (Microsoft has this with NTFS) and transactions in memory data structures (STM) are very valuable.

NOT (0)

Anonymous Coward | about a year and a half ago | (#42225993)

I am a fan of return values and proper testing of these. But your statements about destructors are 100% correct. Java and C# have nothing equivalent and that is why they are a pain in the rectum.

People are building massive systems using plain C and these are highly reliable (see Linux, BSD kernels). Exceptions and STM seem to be for the quick-and-dirty-overpriced corporate hacks.

setjmp/longjmp (0)

Anonymous Coward | about a year and a half ago | (#42225667)

That was the low-level C solution, which also doubled as a standard interview question throughout the '80s.

I don't know if Dennis R. was to blame or not.

What about you, Mr. Brainiac? (-1)

Anonymous Coward | about a year and a half ago | (#42225671)

Go smart guy. Step up to the plate. If you are such a friggin genius then why don't you show us a better way?

Maybe there isn't a better way. Ever thought of that, buster? Wake up and smell the coffee.

Exceptions (3, Insightful)

vargad (1948686) | about a year and a half ago | (#42225681)

Normally exceptions should be used in exceptional cases, not in normal control flow. Exceptions are usually quite expensive, especially in C++ compared to just returning an error code. Language APIs should be fast, but also convinient so they had to made a trade-off.

Re:Exceptions (1)

Hentes (2461350) | about a year and a half ago | (#42225797)

Speed is another reason why current exception handling mechanisms are insufficient.

Re:Exceptions (0)

Anonymous Coward | about a year and a half ago | (#42226031)

Why would speed be a problem if exceptions are only used for exceptional cases?

Why should exceptions be "exceptional"? (2)

Anonymous Brave Guy (457657) | about a year and a half ago | (#42225931)

Normally exceptions should be used in exceptional cases, not in normal control flow.

People keep saying that, but I've yet to find someone who can defend the position with a logical argument.

Fundamentally, you run some code to do a job. There are two ways it can finish early: either it succeeded, and we did all the work/figured out whatever information we were asked for, or it failed, and maybe we want to report this along with some related information. Either way, there is nothing useful left to do except hand control back to the higher level code that asked for the work to be done, along with the outcome of that work, as efficiently as possible without leaving anything in a mess as a side effect.

Exceptions, as provided in many mainstream programming languages today, could serve either purpose just fine. The semantics work the same way in each case. The performance implications are the same in each case. Aside from the unfortunate name "exception", which we could replace with something like "outcome" or "result" just as easily, and the commentary of certain commentators, whose arguments are rarely more than an appeal to their own authority, there is no difference between the two cases semantically or in terms of the code I want my computer to run.

So, why should exceptions be used only in exceptional cases, apart from dogma or convention? They're just a tool, like variables or functions.

Exceptions are usually quite expensive, especially in C++ compared to just returning an error code.

I'd like to see your profiling results to back up that claim. I've got a few years of working on high performance code that suggests most compilers from the past decade or more use some variant of table-based dispatch to handle exceptions. That means they will not need to manually unwind the stack step-by-step in the case where the exception is thrown/raised; they can just run any necessary clean-up handlers and otherwise skip over everything between throwing the exception and catching it. It also means there will be less error checking code required all the way up the call stack in every other case. In other words, this model runs faster and it does does so whether or not an exception is thrown. The overhead is in the space for storing the jump tables and the compiler's effort to generate them (both of which can be unpleasantly large) but not in the run-time speed.

Re:Exceptions (0)

Anonymous Coward | about a year and a half ago | (#42225973)

It seems like that could vary from case to case what exactly is the boundary between "exceptional" and "normal." I've had some code in tight loops where it was much quicker to overall to jump out of the code than to have another conditional or two running every loop. Although 95+% of the time it is not going to make that much of a performance difference, in which case making the code readable, maintainable and being sure it is doing the right thing would take priority.

Third option? (0)

Anonymous Coward | about a year and a half ago | (#42225685)

In Soviet Russia, third option errs on you!

Dobb's journal got nothing more to offer? (-1)

Anonymous Coward | about a year and a half ago | (#42225687)

public void shallowEditorial(String out)
throws PeanutGalleryException {
        System.out.println(out);
        throw new PeanutGalleryException();
}

First problem is considering it clutter (5, Insightful)

erroneus (253617) | about a year and a half ago | (#42225689)

It is not clutter. It is necessary. Trash cans in the home might be considered clutter too I suppose. Some people artfully conceal them within cabinets and such, but in whatever form, they are both necessary and either take up space or get in the way or both.

It is the reality we live in. If you want to code in a language that doesn't require error handling, you might look to one of those languages we use to teach 5 year olds how to program in.

Good code does everything needed to manage and filter input, process data accurately and deliver the output faithfully and ensuring that it was delivered well. All of this requires error checking along the way. If you leave it to the language or the OS to handle errors, your running code looks unprofessional and is likely to abort and close for unknown causes.

I think the short of this is that if anyone sees error checking as clutter or some sort of needless burden, they need to not code and to do something else... or just grow up.

+1 (0)

Anonymous Coward | about a year and a half ago | (#42226009)

..for heroic rationality !

Argumentum ad ignoratum (3, Informative)

overshoot (39700) | about a year and a half ago | (#42225703)

How can it be that after 60+ years of language development, errors are handled by only two comparatively verbose and crude options, return values or exceptions?

Of course, it could be that this just means that your own language horizons are too narrow. Prolog and icon [wikipedia.org] come to mind.

Re:Argumentum ad ignoratum (0)

Anonymous Coward | about a year and a half ago | (#42225757)

Or it could be that there isn't a better way.
Or that the author is too pedantic for his own good.
Or Doctor Dobbs didn't get any good submissions so they went with sensationalism.

Programming is a methodology of writing down the steps a human would take to accomplish a task. So writing it like a human would do it would be a good thing. Let the compiler take care of making it into something that works like a computer works.

Simple... (1)

dargaud (518470) | about a year and a half ago | (#42225709)

...write code without error. Or in other words:

"Never test for an error condition you don't know how to handle." -- Steinbach's Guideline for Systems Programmers.

Re:Simple... (0)

Anonymous Coward | about a year and a half ago | (#42225865)

Mod parent up. The right way to deal with an error is to terminate program execution.

What is needed is event-based programming... (1)

Anonymous Coward | about a year and a half ago | (#42225713)

...like the one described here:

http://www.reddit.com/r/ProgrammingLanguages/comments/m0f1o/how_about_a_programming_language_in_which/

In this way of programming, errors are just another set of events.

caught (2)

Marxdot (2699183) | about a year and a half ago | (#42225727)

Exceptions here provide greater readability

Nah, they don't.

Re:caught (2)

ruiner13 (527499) | about a year and a half ago | (#42226045)

I'll take good comments explaining difficult to read code over using exceptions to make it "appear" more readable any day. Exceptions should only be used when the code has no way to recover from the error gracefully. They should not be used to improve readability. That's what comments are for. Now, I'm not saying every trivial line should be commented, but blocks of code that are complex should at least have the intent of the code commented, so no one later on changes its behavior unintentionally (yes, there should be unit tests for that...)

Third option (4, Insightful)

wonkey_monkey (2592601) | about a year and a half ago | (#42225735)

How can it be that after 60+ years of language development, errors are handled by only two comparatively verbose and crude options, return values or exceptions? I've long felt we needed a third option.

Maybe - and admittedly this is just a guess from my fairly ignorant viewpoint - it's a very hard problem. How can it be that after 100+ years of industrial development, we're still heavily reliant on internal combustion engines to get us around? Why have we only got people as far as the moon in 60 years of space travel? Why, after x years, have we only achieved y?

Because that's the way it is. Is there some reason we should have the third option by now?

Too easily impressed (5, Insightful)

White Flame (1074973) | about a year and a half ago | (#42225737)

The author commends the use of multiple return values and a side-band error value that must be checked? Gee, multiple return values have been in Lisp forever, and maybe he's not aware of this little thing called "errno"?

Error handling is very, very tedious by nature. There are bajillions of ways that a system can go screwy, and many of these have individualized responses that we want distinguished for it to behave intelligently in response. We expect computers to become "smarter", and that means reacting intelligently to these problematic/unexpected situations. That is a lot of behavioral information to imbue into the system, all hooked into precise locations or ranges for which that response is applicable. That information is hard to compress.

There is a better way to use exceptions (2)

ribuck (943217) | about a year and a half ago | (#42225743)

But even in exception-based languages there is still a lot of code that tests returned values to determine whether to carry on or go down some error-handling path

The key to taming exceptions is to use them differently. Any exception that escapes a method means that the method has failed to meet its specification, and therefore you will need to clean up and abort at some level in the call chain. But you don't need to catch at every level (unless your language forces you to), nor should you need to do anything that relies on the "meaning" of the exception. Instead, you take a local action: close a file, roll back the database, prompt the user to save or abandon, etc, and either re-throw or not according to whether you have restored normality. There will only be a few places in your app where this type of cleanup is needed.

If you're not doing it this way, you're using exceptions as a control structure, and that's never going to be clean.

Condition System (1)

Anonymous Coward | about a year and a half ago | (#42225745)

We should also add to this discussion mention of Ken Pitman's and others Condition System from Lisp languages. It can be read about here:
http://www.nhplace.com/kent/Papers/Condition-Handling-2001.html
and
http://www.gigamonkeys.com/book/beyond-exception-handling-conditions-and-restarts.html

What do you propose ? (0)

Anonymous Coward | about a year and a half ago | (#42225747)

It's easy to say something is crude, inefficient etc. How about proposing a solution ? I find exceptions quite good. The only problem I have with exceptions is to decide on what level to put try block and where to handle the exceptions. For a single program this might not be a big deal but with code reuse it becomes a problem to memorize what scheme I have chosen months ago for particular piece of code and particular exception. For example opening a file can be handled internally by reusable piece of code that might display message box and loop back to opening file until user enters the right file. But one can chose to pass the exception to the calling program instead. If it would be just this one that would be no issue to describe it in the comments but there are many types of exceptions and some can be handled locally or not. With multiple exceptions some created by the author, others generated by the framework building a reasonable reusable scheme is a problem by itself.

JAM

CSI-error (0)

Anonymous Coward | about a year and a half ago | (#42225755)

Tag it, bag it, log it & blog it.

Why should Anti-virus companies have all the fun?

Mid-'70s PL/I Exception Handling is Alive & We (1)

theodp (442580) | about a year and a half ago | (#42225759)

Condition handling [ibm.com] and Conditions [ibm.com] . Old school, but does the job without too much clutter!

Hint: computers are binary (1)

Gothmolly (148874) | about a year and a half ago | (#42225761)

Things either work, or they do not. The function either completes, or it throws an exception. You can catch this, or you can choose not to.

Inconvenient? yes. Necessary? yes (1)

hardtofindanick (1105361) | about a year and a half ago | (#42225771)

Even if there was a shortcut for safely ignoring return values, I would (the company I work for would) still need to check and catch every return. Why? We have to log them all.

If you don't want to deal with failed returns, I find that a scripting language is the best way to go. I write my glue functions to handle nulls gracefully and I am done.

There is no such thing as an error. (2)

Cryptosmith (692059) | about a year and a half ago | (#42225785)

This is the real third option.

The so-called "error returns" from things like file opening are telling the program something very important about what's going on. The program's flow must be designed from the beginning to interpret and handle errors. This is in fact be much of what a good program does.

It doesn't matter whether we use exceptions or error codes to signal the errors as long as the program is designed to accurately interpret the errors that do occur. In some sense, exceptions may be easier to implement in today's event-driven interactive interfaces. Regardless, though, the design must not allow errors to be lost.

Was it Cooper in "About Face" who said that an error alert pop-up was essentially an admission of failure on the part of the programmer?

Rick.

Try-Catch blocks should not exist... (0)

Anonymous Coward | about a year and a half ago | (#42225787)

The Try/Catch block is an error handling paradigm that should never have existed. It creates nothing but programmers who have absolutely no idea how to code. A lot of coders just cover entire routines of code in t/c blocks because they don't really want to handle errors at all. T/C blocks also prevent you from seeing real problems in your code. A good coder knows to pre-prepare for errors and handle errors where they happen, and nowhere else. The T/C blocks also create needless code block indentation and much slower inefficient code. I have nothing but disdain for any code that crosses my desk that contains T/C blocks. It tells me that you just code recreation-ally and never intend to be a true programmer.

Re:Try-Catch blocks should not exist... (2)

interval1066 (668936) | about a year and a half ago | (#42225883)

A lot of coders just cover entire routines of code in t/c blocks because they don't really want to handle errors at all.

Ummm, I think that depends. If you enclose a code block with ~some~ exception handling, you obviously know there is a possibility for a problem. Its what you do with that exception that separates the coders from the slackers. Also, when coding an API, there's little more appropriate than using a "throws" clause, it should be up to the caller to deal with raised exceptions as it sees fit.

That said, exceptions are so expensive I tend to favor return codes in speed-sensitive code and turn off exception handling if the compiler allows it.

Re:Try-Catch blocks should not exist... (2)

jythie (914043) | about a year and a half ago | (#42225965)

In other words, you do not know how to use them effectively therefor any use of them must be bad?

T/C blocks are a tool, just like everything else in programming. They can be abused, and they can be perfect for the job. Anyone who tries to claim that some tool is universally bad and has distain for any piece of code using it regardless of its appropriateness does not strike me as a very good programmer, or at minimal a very limited programmer.

Sh!t happens! (0)

Anonymous Coward | about a year and a half ago | (#42225789)

The fact of the matter is that errors happen, and if you have a program that needs to continue functioning in face of them (until things REALLY go sideways), then handling errors will be 50-80% of your code. I have been developing HA (high-availability) large scale distributed systems for 30 years, and I have not yet figured out a way to reduce that "cost". If your software can afford to stop when some unhandled exception occurs, then don't bother handling it. If your software has to run 365x24 or people will die or factories will stop grinding out "stuff", then you have little recourse other than to anticipate all possible conditions that will affect the function of the program, including restarting it if necessary.

Doing it wrong (1)

Sarten-X (1102295) | about a year and a half ago | (#42225813)

But even in exception-based languages there is still a lot of code that tests returned values to determine whether to carry on or go down some error-handling path.

The whole idea of exceptions is that you don't need to worry about checking return codes. If you're putting a lot of work into checking return codes for error conditions, then you're working with some ugly code that probably needs refactoring. One place I see this a lot is in Java wrappers around libraries ported from C (or used directly with JNI). Often, to make the documentation and example code line up perfectly, the wrapper returns invalid values for exceptional circumstances rather than just throwing exceptions. This is wrong.

The only code that should be run routinely for error-checking is to see if an exception should be raised. That's fast, only needed once per major function (so you're not re-checking at every minor transformation), and doesn't incur the cost of exceptions unless they're actually raised (which should be fairly rare, as they're exceptional).

Re:Doing it wrong (0)

Anonymous Coward | about a year and a half ago | (#42225917)

Exceptions suck because they lose so much information about why something went wrong.

I currently maintain old server code that core-dumps every few months with an uncaught exception. So I know something is wrong, I know where the exception came from, but I have no idea how it got into the state that caused it because the stack has unwound and all the history which would tell me how it got there has gone. Nor can I install a modified version of the software with more debug output as it's a critical system running 24/7 (when it core dumps it restarts and recovers in a few seconds so it's not considered critical enough to justify a new software release).

If it just crashed I'd know exactly what the problem was, but someone decided to throw a meaningless exception instead so I have no idea.

Re:Doing it wrong (0)

Anonymous Coward | about a year and a half ago | (#42225983)

That doesn't mean all exceptions suck, just that the exception in that case sucks because it isn't returning enough information.

Most programmers use a third solution (2)

cstdenis (1118589) | about a year and a half ago | (#42225841)

Just don't bother checking for errors.

Re:Most programmers use a third solution (0)

Anonymous Coward | about a year and a half ago | (#42226005)

Handling errors is the job of the support staff, not the developers.

Error handling is code, not clutter (0)

Anonymous Coward | about a year and a half ago | (#42225849)

Programmers like to be able to see the logical flow of the program, and error handling messes that up. The problem is that error handling is half of the logic of a program. Hiding error handling logic in exceptions frequently mainly seems to be way to let poor programmers think even less about the unusual cases.

Akka (0)

Anonymous Coward | about a year and a half ago | (#42225881)

Anybody who wants to build truly error-tolerant systems on the java virtual machine should take a look at AKKA: www.akka.io.

They have a very refined approach for error handling that does not require you to clutter your code with try { } catch { case x, case y, ... }.

Problem with Exceptions (1)

shawnhcorey (1315781) | about a year and a half ago | (#42225921)

The biggest problem with exceptions is that they get thrown too far, changing them into comefroms (the opposite of a goto). And like gotos, they encourage spaghetti code. The best way to deal with them is to limit them to thrown exceptions only to their callers. That way, all exceptions become part of the subroutine's interface. Remember, for a programmer, out of sight is out of mind. If it's not part of the interface, it will be forgotten. For those who are interested, you can read my blog [blogspot.ca] for details and an example [blogspot.ca] .

Third option: have no errors (1)

pclminion (145572) | about a year and a half ago | (#42225923)

If possible, design a component such that no errors will ever occur (except for hardware failure). An entire program can't be designed that way, obviously, but individual components can be. Collecting all resource allocation into a small, well defined set of locations will relieve the majority of other code from the need to handle errors. In such a design, the majority of functions will return "void".

error handling in functions (1)

Khashishi (775369) | about a year and a half ago | (#42225933)

The nice thing about functions (rather than just simple subroutines) is that you can chain them in a single line. E.g.
a = geommean(factorial(b), zeta(c))
The single return value mechanic really makes it easy to use for math-style expressions. But the single return value mechanic isn't adequate when the function is allowed to have errors. In a language like c, one might do something like
f = factorial(b, &error);
z = zeta(c, &error2);
if (error==0 and error2==0) { a = geommean(f, z, &error3); } else {error3 = 1;}

Unfortunately, there's no longer any simple way to chain the functions, which kinda defeats the point of functions. So exceptions were invented.

Perhaps a better language would have some better handling of multiple-output functions. Maybe some way of chaining functions such that the error behavior can be defined. I'm not sure exactly how to do that.

Re:error handling in functions (0)

Anonymous Coward | about a year and a half ago | (#42226035)

The nice thing about functions (rather than just simple subroutines) is that you can chain them in a single line. E.g.
a = geommean(factorial(b), zeta(c))
The single return value mechanic really makes it easy to use for math-style expressions. But the single return value mechanic isn't adequate when the function is allowed to have errors. In a language like c, one might do something like
f = factorial(b, &error);
z = zeta(c, &error2);
if (error==0 and error2==0) { a = geommean(f, z, &error3); } else {error3 = 1;}

Unfortunately, there's no longer any simple way to chain the functions, which kinda defeats the point of functions. So exceptions were invented.

Perhaps a better language would have some better handling of multiple-output functions. Maybe some way of chaining functions such that the error behavior can be defined. I'm not sure exactly how to do that.

Languages like scala allow function composition while still preserving the ability to handle errors. The trick is to have a return value that can be either a result or an error, and make it monadic so it can be chained. The appropriate type for this is called Either, but there is a type just for the purpose of error handling, which is even more convenient, and which is called scala.util.Try.

There is no third option (4, Insightful)

gman003 (1693318) | about a year and a half ago | (#42225947)

There are two ways to do error-handling: try{}catch{}, or if{}else{}. That's "using exceptions" and "using return values", under Dobb's naming.

The difference in usage is simple: one handles errors immediately, thus cluttering the code with all the things that could go wrong, while the other separates error-handling out, pushing it to the end of a block (and away from the code that actually generates the error, which can complicate debugging).

I can really think of no other way to do it. You can handle the error where it happens, or handle the error at the end. I tend to look on anyone whining about how hard error-handling is with suspicion - their suggestions (if they even have any) are almost always "the language/compiler/interpreter/processor/operating system should handle errors for me", and there are enough obvious flaws in that logic that I need not point them out.

Haskell Error Monad Transformer (1)

Anonymous Coward | about a year and a half ago | (#42225955)

Check out Haskell's Error Monad transformer. Used properly it is a beautiful thing.

State logging (1)

roman_mir (125474) | about a year and a half ago | (#42225963)

Exceptions are named for what they stand: exceptional cases. Somebody pulled the network cable out somewhere while you are trying to get data from that networked device. A file is not there that you are checking for because some other piece of code didn't put it there or maybe the file is there but the format has changed and nobody notified the dev team.

New type of data is introduced into a file or maybe the data location changes or maybe the user input is outside of expected parameters (actually this one is the easiest to check and tell the user right away IF it is a synchronous session, if it's asynchronous, then again, you have to send back some notification and log it).

However I do think that there is a more interesting question around exceptions that can be answered: how about recording the total state of data before exception and after, of-course I am talking about data that is used within the process or the thread.

So the 'try / catch' mechanism becomes something more than just a trap, it becomes a frame by frame snapshot of data. Maybe a new type of exception handler, that is beyond the normal 'try / catch'. Call it: 'try-record / catch-record', something like that.

So here is what it could look like:

SomeClass {
static char A = 'a';
...
callerFunction() {
...
int input = 0;
someFunction(input);
...
}
...
someFunction(int input) {
a="blah string";
b=100;
try-record {
A='b';
a = a + String.valueOf(b / input);
} catch-record (Exception e) {
  log.exception();
}
}
}
------------
what you get out of the exception log file:
someFunction.try-record.0:
SomeClass.A='a'
input=0
a="blah string"
b=100
someFunction.try-record.1:
SomeClass.A='b'
input=0
a="blah string"
b=100
someFunction.try-record.2:
error at: b / input
 
(and your standard error, division by 0)
------------

Failure is not an error (0)

Anonymous Coward | about a year and a half ago | (#42225967)

The failure of an attempted operation may or may not be an error. If I want to allow the user to override the default value by means of an environment variable, I call getenv(3c). If the call fails I use the default. If it succeeds I use the value that is returned. On the other hand, I might want in some instances to require that an environment variable be set in which case failure *is* an error.

Spreading the logic out over several files doesn't help anyone other than people who shouldn't be programming in the first place.

Having worked w/ a large package that "helpfully" implemented automatic "error" checking I despise it. The result is bad error handling.

Programming is all about handling edge cases correctly. It takes careful thought and lots of work.

Exceptions sound like a good idea, but... (0)

Anonymous Coward | about a year and a half ago | (#42225977)

...the problem is any one exception is a nice, elegant way to handle an exceptional condition, but non-trivial code has page after page after page after page of exceptions, usually for trivial things like converting a string to an integer. In practice, exceptions clog up code and make it difficult to follow. Also, how do you recover from an exception? If you try ... catch, then you recover and fix the problem, you have to somehow goto the start of the try again. Most languages with exceptions don't have any clean way to say "I fixed it, let's try it again".

Basically, it's easy to just punt and let Java (for example) dump page after page after page of stack trace to the console.

I'll take a return code any day over an exception mess.

Pfff (2)

Greyfox (87712) | about a year and a half ago | (#42226001)

You don't write an article like this unless you're actually going to suggest a different solution in it. Otherwise it just comes off as whiny and inexperienced. "Oh, if only we could not do that thing that everyone must do if they want robust code!" Reminds me of beginner CS students who don't want to make an extra header file or prototype functions. We're not doing magic here, and no amount of wishing for magic will make it happen. Work with some magic module (ActiveRecord, maybe) for a while and you'll quickly learn to hate magic, anyway. Discipline is required to write code that will stand the test of time. If I were wishing for something, it'd be that more programmers had the discipline to write good code consistently.

I read the article (3, Insightful)

iplayfast (166447) | about a year and a half ago | (#42226003)

And I must say that as the Editor in Chief he has a very simplistic view of the problem. If I understand, his view is that a global exception added at the compiler level would somehow solve all the problems. He gives the example of calling "open" without worrying about it failing. Of course he doesn't state how to handle the failure when it occurs. For example

open(file1); // ok
open(file2); // failure

What happens to file1 in this case? How is the code cleaned up? There may be a case where you don't want to just close all files in the functions, but just create file2 if the open failed. (for example).

His complaint is that there is too many options available for error handling, and that they lead to cluttered code. As far as I can see the alternative is not enough options available and code not always doing what you want, and having to fight the compiler in order to get what you want.

third option: callbacks (2)

larry bagina (561269) | about a year and a half ago | (#42226041)

This is generally seen with asynchronous code, but it could apply anywhere.

Consider: (javascript) XmlHttpRequest has a readystatechange callback. Most javascript libs wrap it up so you pass in two callbacks, one for success and one for failure/error.

e.g.

jQuery.ajax(url, {
success: function(data, textStatus, jqXHR){ ... },
error: function(jqXHR, textStatus, errorThrown)) { ... }
);

No return, no exception, the programmer decides how to handle it.

Magic (1)

cheebie (459397) | about a year and a half ago | (#42226061)

We need the computer fairies to handle our errors, that way the beauty of our code will not be marred by mundane things like error checking.

Seriously, error checking is part of the process. It's not the fun part of the process but it's a necessary part. Return values and exceptions work just fine as long as you get off your high horse and realize that your code will not be hung in the Louvre. Working is more important than pretty.

Lisp (2)

Jmc23 (2353706) | about a year and a half ago | (#42226063)

One day, the majority of programmers will be able to grok Lisp and all these silly problems disappear.

Problems don't exist in reality, they exist in points of view.

Load More Comments
Slashdot Login

Need an Account?

Forgot your password?

Submission Text Formatting Tips

We support a small subset of HTML, namely these tags:

  • b
  • i
  • p
  • br
  • a
  • ol
  • ul
  • li
  • dl
  • dt
  • dd
  • em
  • strong
  • tt
  • blockquote
  • div
  • quote
  • ecode

"ecode" can be used for code snippets, for example:

<ecode>    while(1) { do_something(); } </ecode>