Slashdot Mirror


The Scourge of Error Handling

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.'"

536 comments

  1. The third option by Anonymous Coward · · Score: 5, Funny

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

    1. Re:The third option by MacDork · · Score: 2

      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.

    2. Re:The third option by MacDork · · Score: 1

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

    3. Re:The third option by Anonymous Coward · · Score: 0

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

    4. Re:The third option by Yetihehe · · Score: 4, Interesting

      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
      Apparently OP didn't heard about it, because this is the third way.

      --
      Extreme Programming - Redundant Array of Inexpensive Developers
    5. Re:The third option by pla · · Score: 4, Insightful

      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. ;)

    6. Re:The third option by jythie · · Score: 1

      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.

    7. Re:The third option by MurukeshM · · Score: 1

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

    8. Re:The third option by Anonymous Coward · · Score: 1

      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.

    9. Re:The third option by Nerdfest · · Score: 5, Interesting

      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.

    10. Re:The third option by PRMan · · Score: 2

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

      This is the option chosen by most developers...

      --
      Peter predicted that you would "deliberately forget" creation 2000 years ago...
    11. Re:The third option by Anonymous Coward · · Score: 5, Informative

      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.

    12. Re:The third option by White+Flame · · Score: 1

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

    13. Re:The third option by Simply+Curious · · Score: 4, Insightful

      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.

    14. Re:The third option by Anonymous Coward · · Score: 0

      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

    15. Re:The third option by Yetihehe · · Score: 1

      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.

      --
      Extreme Programming - Redundant Array of Inexpensive Developers
    16. Re:The third option by Yetihehe · · Score: 1

      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.

      --
      Extreme Programming - Redundant Array of Inexpensive Developers
    17. Re:The third option by Anonymous Coward · · Score: 0

      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!!!

    18. Re:The third option by mrvan · · Score: 5, Insightful

      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)

    19. Re:The third option by Yetihehe · · Score: 1

      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.

      It's good design decision in this case. Consider this:
      You call library function A().
      Library function A() calls some function B(), but you don't know this (closed source).
      Library function B() can throw some error, how can you know it? Either it should be catched in A or declared as thrown in A, so that you know that this exception CAN be thrown from A.

      --
      Extreme Programming - Redundant Array of Inexpensive Developers
    20. Re:The third option by TheLink · · Score: 1

      In theory you should just catch the specific exceptions that you can handle. But the reason why many programmers catch everything is because there is no easy way for the programmer to know upfront which exceptions could be thrown at that point, AND there are very many exceptions that can be ignored -as in you can go "ok that didn't work, we'll try again later" rather than, something really weird happened we better stop the program now! Yes you could go through every possible path and figure out all the possible exceptions then catch the ones you want one by one (the Pokemon School of Coding). But who has time to do that?

      If it were easier then we'd do stuff the "proper" way. As it is, catching everything works well enough in most cases- and if you log the details you can improve things later.

      Coarse-grained try isn't a problem if you can get a stack trace. At the cost of performance many of my programs by default log a lot of stuff in a log context buffer (debug level etc). If everything goes smoothly you only see stuff at the configured log level. But if something goes wrong, you see the error log message and some lines of context (debug logs etc) leading up to the error. I can configure that to be off if performance is needed, but so far performance hasn't been an issue- the DB stuff tends to be the bottleneck.

      If the storage drive vanishes there's nothing much you can do except show an error and abort (or if you're brave, retry after an interval :) ). Nowadays this is more likely to happen with SAN, NAS, iSCSI etc. And yes we've had experienced it a few times before - the datacenter guys go "oh yeah, we were doing some maintenance over the weekend and took the SAN down". Me: "...". They seem to like doing that when I'm on leave too. From what I see the database server doesn't like losing access to the SAN. So it doesn't really matter how well my stuff handles it. Someone still has got to manually go check and fix stuff.

      --
    21. Re:The third option by Capitaine · · Score: 5, Interesting

      My work implies writing aeronautical software specifications. In order to facilitate FAA/EASA certification of the system, we are required to stick to the KISS principle. Data validity checks are done almost everywhere, but we are asked to design the logics so that they do not need to use these data validity statuses. Degraded mode is done through the use of failsafe values. The consumer of a data do not need to know the status of the producer. The whole system is designed so that it works and is robust with minimal use of alternate logics.

      This principle works well with dataflow oriented program and might be adaptable to other domains.

    22. Re:The third option by Yetihehe · · Score: 1

      I did many times. What can you really do when FileReader.close() can throw an exception?

      --
      Extreme Programming - Redundant Array of Inexpensive Developers
    23. Re:The third option by Sarten-X · · Score: 4, Insightful

      If you're actually seeing #4 in practice, your coworkers need a nice bit of physical re-education.

      Each situation you describe has perfectly valid circumstances:

      1) Using a "try" on the whole function is suitable on functions where a particular caught exception can only mean one thing. If you're catching a FileNotFound exception, it means the file's missing. It doesn't matter that the error happened while opening the file, or at the first read. The exceptional situation is that the file can't be found. Exactly which call had the exception doesn't matter beyond debugging (for which there's usually extra information in the exception, such as line numbers).

      2) Revealing ugly text isn't user-friendly. Rather, it shows that the programmer has no idea what's going on and is putting the burden of debugging on the user. Ideally, the exception handler will first take steps to remedy the situation on its own (config file not found? Use sane defaults and save them for next time!), then log the exception somewhere with only the meaningful parts (such as a module name, line number, and a selection of parameters). Nobody really needs to know the whole stack trace up to main().

      3) Sometimes, an empty catch routine is fine, and if it isn't fine a good code audit should notice this anyway. Some errors can be safely discarded, but the code should reflect that they are being willfully ignored, rather than just ignored out of ignorance.

      4) Despite my glib comment earlier, there are also cases where blindly retrying a step is the cleanest solution. One example I've seen recently is where a database connection would reveal a timed-out disconnection only upon actually executing statements. The straightforward solution was that if the first statement failed due to a timeout, the connection (which was now in an error state) would be checked again, reconnected, and the statement would be retried.

      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...

      ...because it's a silly idea. Now you're just using exceptions as special return values. Exceptions are not supposed to mean "something went wrong here". They should mean "there's a situation that is so unexpected that I don't know how to handle". It's a different paradigm entirely. The idea is that rather than writing your program to anticipate every possible error (as the mathematicians so loved), the program should instead follow a more practical "hope for the best, plan for the worst" design. Rather than worrying about exactly which byte of a file couldn't be read, the program should just understand that something's wrong with the file, and its contents can't really be trusted.

      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. ;)

      If your program is supposed to run on transient resources (like, for instance, a cluster that has a weak master controller running your program, and the bulk of its processors scheduled to run computation), this should be expected. Perhaps a "system vanished" exception can be raised to signal that in-process calculations should be restarted the next time the system appears, and that previous calculations should be saved in case everything else disappears, too.

      Or in other words, it broke and you should prepare to try again later. :)

      --
      You do not have a moral or legal right to do absolutely anything you want.
    24. Re:The third option by Anonymous Coward · · Score: 0

      Write the error to a log file and leak a file handle? Possibly stop later when FileReader.open() finds a locked file.

    25. Re:The third option by angel'o'sphere · · Score: 0

      When used correctly, exception handling doesn't make your code cleaner, it reduces to a slightly more verbose way of checking return values.
      Exception handling used properly makes your code indeed cleaner. Just because you have never seen clean code does not mean it does not exist.

      You should, if you want any hope of really dealing with the error, wrap every call in its own try/catch.

      Yeah, +4 Insightful so far. However this advice clearly shows you have no clue about exception handling either, which makes your previous ranting pretty mood.

      --
      Cost free eBook I read (by iBook/Kobo/Amazon/ObookO/Gutenberg etc.): "The Green Odyssey" by Philip Jose Farmer.
    26. Re:The third option by ultranova · · Score: 1

      You should, if you want any hope of really dealing with the error, wrap every call in its own try/catch.

      And how would you deal with the error? Simply keep trying the failing sub-operation until you succeed or the user reboots? Cancel the whole operation, in which case letting the exception propagate up the code stack until it hits a try/catch wrapper is the correct thing to do. Or program the rest of the function so it can proceed with this operation having failed, which may or may not be theoretically possible in the general case but certainly isn't practical.

      The problem is that there simply isn't a good way to handle errors. The model of computing we use only allows two options: either everything goes perfectly or everything goes to Hell. Contrast this with, say, the human nervous system, which can maintain function even when errors are introduced - a drunken man gets progressively less steady on his feet, while a computer program encountering an unhandled error crashes unrecoverably.

      --

      Forget magic. Any technology distinguishable from divine power is insufficiently advanced.

    27. Re:The third option by Anonymous Coward · · Score: 0

      Yes, I know it's possible to catch errors in Erlang. Just pointing out that this is a philosophy best reserved for languages that have been built with that sort of thing in mind.

      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.

      And this is exactly what exception handling in other languages is for. You catch the error, do something about it and then allow the program to continue without crashing. This is why I said that Erlang restarts are like exception handling. However, I really don't like the idea of an exception killing the whole process and silently restarting without a logged stacktrace or similar logging to indicate what happened and why. This can lead to bugs that never get caught and fixed. I don't know if Erlang provides decent logging and alerting of restarts (my knowledge of Erlang is pretty much superficial) so I can't criticize it for the "let it crash" philosophy. However, it's dangerous to spread this into other languages as people start wrapping code in try...except...pass sort of code. That's a bad thing.

    28. Re:The third option by LordLimecat · · Score: 1

      4) Despite my glib comment earlier, there are also cases where blindly retrying a step is the cleanest solution. One example I've seen recently is where a database connection would reveal a timed-out disconnection only upon actually executing statements.

      Disclaimer, Im no programmer.

      But wouldnt it be a lot more sensical to have the exception check to see if the connection is now available, and simply call the parent function() again? Pasting the entire block of code that was used earlier seems to break a number of (good) programming conventions, like, i dont know, never using copy / paste coding methods. Functions are there for a reason, and your exception code has the unique opportunity to check and see if it makes sense to try again before doing so, and has the benefit of (in your example) allowing the try / catch block to work in the event of multiple consecutive timeouts. Your exception block could even get fancy and set a watchdog counter to make sure we arent stuck in an infinite loop...

    29. Re:The third option by Opportunist · · Score: 1

      I was about to say that. A tried and proven technology for ages for error handling: The app crash.

      --
      We used to have a Bill of Rights. Now, with the rights gone, all we have left is the bill.
    30. Re:The third option by Anonymous Coward · · Score: 0

      One thing exceptions do very nicely is move the error handling out of the main path. But yes, failing to make use of that effectively is possibly worse than simply ignoring the return values since it looks like something is being done when in fact it isn't.

      So in my own code I usually just 'throw strerror(errno);' or indeed 'throw "bad stuff happened";', and main() has a catch(const char *) just for that case. Unless, of course, I expect to actually do something useful with the exception, and then I'll replace that throw with something that can be handled in a fashion other than "display to user, bail out".

      This because most of the time the most that happens is exactly displaying and bailing, and if displaying is too hard, not even that. So better just go with the simplest and easiest way available and refactor if necessary. And that's fine, because code isn't really fit for re-use until refactored specifically for reusability (after proven successful use somewhere first), so best not kid ourselves about that and take the easy way out. Can always grep for throw later.

    31. Re:The third option by SplashMyBandit · · Score: 5, Interesting

      In Java you probably wouldn't do as you say. You would 'chain the exception; so that the original exception information is preserved even though you are transforming the exception type (eg. from a checked exception thrown from a library to an unchecked exception you don't have to declare throws clauses for). The code becomes:

      try {
      // Do something here that may throw an exception (which is 'checked').
      // eg. throw Exception();
      } catch (Throwable th) {
      throw new RuntimeException("A problem occurred when launching the SS-18 because the launch authorization code was invalid. The launch authorization code had a value of " + authCode, th);
      } finally {
      // Do any clean-up.
      }

      There are two import things to note in this contrived example:

      • * The use of the chained exception. When the exception type is transformed by the creation of the new exception we include the old exception in the constructor. That way the 'chain' of exceptions can be viewed and the original cause of the exception found. That will help you fix this issue.
      • * A message that tries to describe the exact decision used to throw the exception and the values of any contributing variables or boundary values. It is critical this information is recorded at the point of throwing because in a massively multithreaded system with millions of transactions you can't reproduce the same conditions exactly in your debugger. The only information you have is what you put in your log, and you must include all relevant information in that log. Otherwise you will not have enough data to diagnose the decision the program made to throw, and won't have enough info to fix the problem.

      Checked exceptions are valuable in Java. Those that are against them don't understand that they are very useful for certain classes of problems - systems that have to be reliable. The mistake the Java designers made was that they made the library throw checked exceptions rather than unchecked ones. If they had used unchecked exceptions everywhere (while still supporting checked exceptions for systems that need to force reliable operation under error conditions) then many of the gripes people have when encountering Java would be eliminated. Plus, programmer productively would increase because we wouldn't have to wrap and chain the checked exceptions produced by library calls all over the place. C# kinda gets it right in the fact the libraries don't have/use checked exceptions, but it lacks the option of using checked exceptions in critical systems. So neither Java nor C# have it perfect, IMHO.

      If you are a Java developer writing libraries intended for re-use by others then you should ensure your library never throws a checked exception to the caller. Only libraries for critical systems should do this. Unless you are working on nuclear plant control, avionics, medical devices, weapons systems or interplanetary probes then your system probably doesn't need to expose checked exceptions.

      The way you structure, handle and report exceptions is mundane, but is absolutely crucial for writing reliable and easily maintained software. Most programmers are sloppy about this, or consider it as unimportant as good documentation, but that is what makes then bad programmers (if you ever have to use or maintain their software).

      I hope this helps some developers out there understand how to use chained exceptions. The chaining *preserves information* about the cause of a failure. The adding sensible messages and program state is also about *preserving information* about the failure at the point of throw. Loss of information is what you are battling here, since once you lose/throw away information it is a huge effort to reconstruct it later. Avoiding loss of information is worth keeping that in mind as you develop, so you avoid doing it. Example: the built in NullPointerException being the worst example of providing zero additional information about what was null, a problem if you have multiple chained method calls on a single line. Don't write code like the Java code that raises NullPointerException.

    32. Re:The third option by Sarten-X · · Score: 1

      In my opinion, that depends really on how the rest of the code's written. If the "rerun the command" part is three lines out of fifty (as in the example), just copy/pasting may very well be fine. If the whole function needs to be rerun, recursion may be an option, and likely doesn't even need the infinite-loop check (because how likely is it that a newly-established database connection will time out before it can run a single command?).

      My point is that, for some exceptions, simply trying again may be the proper solution. Proper implementation, however, is left as an exercise to the reader.

      --
      You do not have a moral or legal right to do absolutely anything you want.
    33. Re:The third option by Nerdfest · · Score: 1

      Not really chosen ... it typically falls out of the design approach.

    34. Re:The third option by Sarten-X · · Score: 1

      Welcome to the Slashdot moderation system. "Insightful" usually just means "complains about things that I don't like".

      --
      You do not have a moral or legal right to do absolutely anything you want.
    35. Re:The third option by Impy+the+Impiuos+Imp · · Score: 1

      That's why I always liked LISP's unwind protect wrapper function. C saw it and said, "Let's build a shitty clone of it with all C's difficulties and none of the charm!"

      The very form of try/catch is LISP, which fits naturally there and not with C at all, which is why it seems so jarringly odd there. So does the LISP concept of manhandling code as data, which dovetails nicely with the concept. Something chokes on an error, and LISP kicks it in the balls as the code unwinds.

      --
      (-1: Post disagrees with my already-settled worldview) is not a valid mod option.
    36. Re:The third option by Anonymous Coward · · Score: 0

      your last point is really critical. alot of the machinery involved with error handling isn't doing any good, or as you also point out, actively
      obscures whats going on.

      what people forget to do as they madly pound out boilerplate is think about the semantic implications of the error. is there a meaningful
      recovery? does the user need to be informed at all?

      the downsides of shotgun error handling is a mess because it can make the code unreadable and generally doesn't get tested. java exceptions
      have a particular downside by propagating changes to exception interfaces widely across the call chain.

      however, if you can point to a piece of error handling functionality and say 'this connection had an error, and i'm going to flush it and
      reestablish a new one, which i can safely do because my protocol is idempotent', then everyone says 'oh good'...and it might actually
      get tested because its a nice behaviour

    37. Re:The third option by angel'o'sphere · · Score: 1

      I don't agree with your point 2)

      First of all, the stacktrace goes down, from the point where you made the call to the method/function throwing the error, and not up to main()

      Secondly, a full stacktrace is often very helpfull, and "module names" don't exist anymore in modern oo programming anyway.

      --
      Cost free eBook I read (by iBook/Kobo/Amazon/ObookO/Gutenberg etc.): "The Green Odyssey" by Philip Jose Farmer.
    38. Re:The third option by Z00L00K · · Score: 2

      And you can only catch errors if you know that they will appear.

      One example is when developing in C# you never know which exceptions to except unless you waste a lot of time reading the documentation for every class that you use or resort to do a general catch of Exception and try to guess what's best to do. In Java the amount of "blind" exceptions thrown are limited to the Runtime exceptions that you can get - which is bad enough, especially if some esoteric third party developer throws their exceptions as extensions of the RuntimeException.

      Exceptions are all good and fine but sometimes it's good enough with a return value of zero when an empty string is converted to a number. Even classic Basic had a crude exception handling in the "On Error Goto" statement. But every time you have an error you need to do some cleanup or take an alternate path. Just continuing blindly will give you a bad headache.

      Catch and re-throw has it's uses too, but it shall be used with some care. It may be useful when you run a client/server solution where you don't want to expose every exception up to the client since the client may then need to link third party libraries that you don't want the client to carry. Especially if there are two vendors, one on the server side and one on the client side.

      --
      If builders built buildings the way programmers wrote programs, then the first woodpecker would destroy civilization.
    39. Re:The third option by Z00L00K · · Score: 1

      Log4J / Log4Net has done more for software development than many other kinds of error handling. And I agree that capturing general exceptions to begin with and then when the need rises add more specific exceptions but still keep the general as last resort. Over time you can improve the system, but it takes time.

      --
      If builders built buildings the way programmers wrote programs, then the first woodpecker would destroy civilization.
    40. Re:The third option by Anonymous Coward · · Score: 0

      When the file object is closed, it is closed even if it throws.

      It turns out FileReader.close() can't throw; however FileWriter.close() can, and the implication is your previous writes failed at flush time. Good question what you do about it though.

    41. Re:The third option by Sarten-X · · Score: 1

      If left uncaught, Java exceptions will propagate all the way back past main() before being handled by the JRE. The JRE prints the whole stack down to where the exception was thrown. Often, that means a user viewing a console gets a nice big list of dozens (if not hundreds) of calls through the stack. This is a "full stack trace", and it's rather hideous.

      An exception handler in production code should resolve the exceptional situation as best it can. Anything that can't be handled should be logged as appropriate for the application, with just enough information that a developer can reproduce the error, though not necessarily understand it fully from the log alone. For a database, it might be sufficient to log only the offending statement. For a parser, the file name might be enough. In a big enterprisey application to balance bank accounts, optimize bus routes, and mash potatoes, it would definitely be useful to know whether the "sensor read error" problem was in the weather station polling module or in the blast furnace controller.

      Logging every trivial exception with a full stack trace and parameters quickly bloats log files beyond the point of being useful.

      --
      You do not have a moral or legal right to do absolutely anything you want.
    42. Re:The third option by Anonymous Coward · · Score: 0

      Unless you are working on nuclear plant control, avionics, medical devices, weapons systems or interplanetary probes then your system probably doesn't need to expose checked exceptions.

      I'm pretty sure I've seen specific clauses in Java and non-Unix OSs warning against using their product in exactly those situations, so the intended domain of the software is effectively changing "unless ... doesn't need to" to "Positively never" in "expose checked exceptions"

    43. Re:The third option by White+Flame · · Score: 1

      Right, and if you have a stateful server and just "let it crash" if something goes awry, then you lose that state.

      I used Erlang for a couple of years. I learned a lot of good concepts from it, but I don't recommend the language itself other than a learning experience.

    44. Re:The third option by sycodon · · Score: 1

      It always baffles me that .NET is smart enough to know that "an object has not been set to an instance of an object", but it is apparently clueless as to which object that is or, for some reason, thinks I should have to figure it out for myself.

      --
      When Fascism comes to America, it will call itself Anti-Fascism, and tell you to give up your guns.
    45. Re:The third option by TheLink · · Score: 1

      Probably but I don't think they log context the way I'm talking about.

      Their idea of context is something like prepending log messages with some string depending on the code context. I do that sort of stuff too, but that's code context, not log context.

      Example of the way my log context stuff works:
      do stuff
      log("lots of details",DEBUG)
      do stuff
      log("more details",DEBUG)
      do stuff
      log("some info", INFO)
      do stuff
      If an error happens, log("error info", ERROR).
      -
      Then assuming the log level is set at the INFO level and nothing goes wrong you will just see the "some info" message. But if an error is logged you will see the DEBUG messages too in addition to the INFO and ERROR messages. The log context buffer is emptied (default is 20 log entries of context).

      This way I don't have to set the log level to debug to get the details. I get the debug level details whenever an error is logged. Yes it's slower, but I don't care, I let Intel/AMD take care of that ;).

      --
    46. Re:The third option by cyber-vandal · · Score: 2

      Microsoft code is littered with technically correct but utterly useless error messages. Key not found in dictionary is another annoying one when it's thrown in code that you don't have the source for like CRM 2011. Which key would that be then? One of the 25 that I've just passed to you. Oh ok I'll just remove each one until the error no longer happens, that's a 21st century solution *rolls eyes*.

    47. Re:The third option by Anonymous Coward · · Score: 0

      Our COBOL at work does the same. We implemented a CALL "ABEND" for when we really want to crash and call it a day.

    48. Re:The third option by SuricouRaven · · Score: 1

      The language handles that for you. The exception gets thrown up and up until finally it reaches the runtime's own 'catch everything' handler. Which usually dumps a load of trace information to the user, tells them to send it to tech support, and terminates the process. Ugly, yes. But it works.

    49. Re:The third option by west · · Score: 5, Funny

      I have not ever seen that done

      I have. The coder handled every possible exception intelligently, handled the possible exceptions in the exception handlers, handled the possible exceptions in the exception exception handlers, etc. It was phenomenal. His code could practically handle a CPU burning out at the same time as the primary disk had been hit by lightening while the database had been accidentally converted into EBCDIC.

      Unfortunately, it was also completely unmaintainable. No human being, outside of the original programmer, could possibly grok all the conditions, sub-conditions, and contingencies. The code was also 3000 lines of error handling for about 25 lines of normal execution.

      It was my privilege to gaze upon the world's most complete error handling before I fulfilled my responsibility of burning it to the ground.

    50. Re:The third option by angel'o'sphere · · Score: 1

      If left uncaught, Java exceptions will propagate all the way back past main() before being handled by the JRE. The JRE prints the whole stack down to where the exception was thrown. Often, that means a user viewing a console gets a nice big list of dozens (if not hundreds) of calls through the stack. This is a "full stack trace", and it's rather hideous. Yeah, but such an exception is not logged, as it is not caught there is no handler to log it ;D It is only written on the console and you can hardly do anything about it.

      Logging every trivial exception with a full stack trace and parameters quickly bloats log files beyond the point of being useful. That is why we use logging frameworks with circling log files.
      If you can decide what to log and what not, than its fine. Many people can't, so I rather have everything instead of the vital thing missing.

      If you have so many exceptions that you can not read your logfile, then there is something seriously wrong anyway.

      My logfiles usually only contain SUCCESSFUL transactions and no errors. Errors only occure if the base on which the software is installed unexpectedly changed (DNS not working, SAN lost, hardware itself is defect etc.)

      If you have a failing "business rule" you don't log the relevant exceptions at all, but log the case why the business rule failed.

      --
      Cost free eBook I read (by iBook/Kobo/Amazon/ObookO/Gutenberg etc.): "The Green Odyssey" by Philip Jose Farmer.
    51. Re:The third option by QilessQi · · Score: 1

      Sadly, this is very common. I have seen developers go out of their way not to throw exceptions which by all rights should be thrown, such as checking for unexpected null values in variables and then setting those variables to dummy values... sigh...

    52. Re:The third option by Yetihehe · · Score: 1

      If your state is corrupted, you should either restart or try to fix the state. Restarting is often simpler, fixing state may even add more errors.

      --
      Extreme Programming - Redundant Array of Inexpensive Developers
    53. Re:The third option by Anonymous Coward · · Score: 0

      How about hiring competent software developers instead of hiring for the lowest salary or hourly wage? Ninety-nine percent of bugs in software are attributable to poor programming practises including failure to adequately capture invalid data early.

    54. Re:The third option by loufoque · · Score: 1

      How is that significantly different than exceptions?
      An exception, when thrown, will gracefully terminate any subcomponent up to the scope it is caught in.

    55. Re:The third option by JesseMcDonald · · Score: 1

      I think there are three sane ways of using a try/catch: ...

      I would say that there is a forth way, which is to add context-specific information to a low-level exception. For example, low-level code may throw an exception because a file can't be opened. It doesn't know why the file was being opened, or how failing to open the file will affect the program as a whole.

      I would say that the code which requested the file should catch the exception, and wrap it in a second exception providing the context, so that there is more information available than simply "this file couldn't be opened". The original exception data should obviously be preserved. You won't necessarily need something like that at every function call, but it may at least be useful whenever an exception crosses from one module to another. A wrapper around each public interface should suffice.

      One advantage of this is that you can still impose static exception type checking on the public interfaces, since the type will always be the outer wrapper type, not the type of the original exception. Callers need only handle "unable to read configuration data" exceptions, not "unable to open file", "parse error", "out of memory", etc.

      --
      "The state is that great fiction by which everyone tries to live at the expense of everyone else." - Bastiat
    56. Re:The third option by Yetihehe · · Score: 2

      Significantly - you don't (typically) catch exceptions in erlang. You plan what to do after some process fails.

      --
      Extreme Programming - Redundant Array of Inexpensive Developers
    57. Re:The third option by SuperTechnoNerd · · Score: 1

      Panic and catch fire.

    58. Re:The third option by Anonymous Coward · · Score: 0

      >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

      That is exactly what you get in classic visual basic when using error line numbers

      Dim Strm As ToolGen.Strm
      On Error Goto ErrHandler ' Try
      10: With ToolGen.gFactory.New_Obj(enmData.SQL_Def, 34)
      20: Set Strm = .Qry(enmBy.Name, "eKrain")
      30: With New SyraChem.MosTnk
      40: Call .Load(Strm)
      50: Let .AciMuE = .LimFER * CDbl(.Read(enmCfg.Port))
      60: Call .Save(Strm)
      70: End With
      80: Call .Update(Strm)
      90: End With
      On Error Goto 0
      ErrHandler:
            With ToolGen.gAsP.ExHndlr
                    Select Case erl
                          Case 20: Call ErrSQL_Qry(.OnErr )
                          Case 50: If ErrReadTnk(.OnErr, Strm) Then Resume
                          Case Else: Call .OnErr.Raise(Strm)
                    End Select
            End With

    59. Re:The third option by Tough+Love · · Score: 2

      lease 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.

      +1. An exception mechanism is absolutely necessary to being able to contruct sane error reporting and recovery in a nontrivial code base, without unduly obfuscating the code. Whether this powerful tool is used or abused depends on the the quality of the programmer, as nearly every aspect of software development does.

      One issue with exception handling: you generally lose the ability to get a traceback at the point of throw. So it is often difficult to find out where an exception came from. This can fairly be regarded as a flaw in the language implementation: there should be a way to tell the compiler to always generate a traceback before the throw. Or better, there should be an easy way to capture the traceback as, say, an array of strings, that can be logged or stored in the exception object. In absence of a facility like this, I typically add a macro to generate a trap to the debugger at any throw point where the call chain is not immediately obvious. Then there has to be a way to turn that off in production code, and then the ability to know the call chain for an exception in production code is lost. It's very much an unresolved issue. Funny, I haven't seen any of the language gods take note of this important point.

      --
      When all you have is a hammer, every problem starts to look like a thumb.
    60. Re:The third option by loufoque · · Score: 1

      I don't typically catch exceptions in C++ either. I only use them for graceful shutdown.

    61. Re:The third option by Wrath0fb0b · · Score: 1

      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.

      This. In some modern languages where you can reraise/chain exceptions, this can be very slightly modified so that "catch if you can do something about it" becomes "catch if you can add any useful information to the chain and then pass along to someone that can do something about it". It doesn't make for aesthetically nice code, since we're mixing functionality, error logging, error handling and resource management -- but it's very nice to debug issues that aren't easily reproducible interactively and you need to put things together from the logs.

      In Python, the copypasta pattern is:

      def FooTheBar(yarr, flags = None):
        if flags is None:
          flags = GetDefaultFlags()
       
        try:
          fooer = GetFooer()
          bar = fooer(yarr, flags)
        except Exception, e:
          LOG_ERROR( "Exception in FooInner, my state is %s" % locals() )
          LOG_ERROR( "I'd also like to note some relevant facts like %s %d %s" % (.....) )
          raise # Reraise for the caller to handle this exception
          raise MyException( parent = e, msg = "holy balls" ) # raise a new exception with the e chained on
        finally:
          fooer.dispose_nicely()

    62. Re:The third option by b4dc0d3r · · Score: 1

      Without debug symbols, it makes no sense to display any more information than that. If you are catching exceptions, you should have a logging function (preferably to persistent storage with a fallback to text file, and fallback to a simple dialog). This can capture exception information and stack trace, which will tell you roughly where to look. With debug symbols, it will tell you exactly where to look.

      What you seem to be complaining about is different. If you have piles of objects on one line, and chain things like repository.GetSomething()[0].ToString() then you are doing it wrong. Add tests, add local variables to isolate the line number, or suck it up and just keep guessing.

      In other words, the code you are working with does not match the recommended coding styles from the language creator(s). That can hardly be blamed on anyone but sample websites like CodeProject where any unchecked random junk gets puked up by someone who thinks they are clever, or as a proof of concept without intermediate steps. Then the code gets spread like a virus.

      I was thinking more along the lines of the Windows error messages, where something very specific gets bubbled up to a less and less specific error message until it makes no sense in the current context. That is a typical Microsoft screw-up, and exists in .NET, especially in some of the code which has been around since 1.x. You can't cure the runtime, but you sure as hell can fix your code.

    63. Re:The third option by BitZtream · · Score: 3, Insightful

      You're fired.

      unless you waste a lot of time reading the documentation for every class that you use

      Again I say, you are fired. I would throw you out on your ass so quick it would make your head spin if you told me that as one of my employees. If you aren't reading the documentation you don't know how the method works and you don't need to be writing code.

      That is the most idiotic argument I've ever heard. Its the definition of bad programing, ON PURPOSE no less.

      --
      Persistent Volume manager for Kubernetes - https://github.com/dwimsey/openshift-pvmanager
    64. Re:The third option by White+Flame · · Score: 1

      Your state should never get corrupted, unless you're running newly written code.

      But how is restarting simpler, if you lose whatever the user's been doing, or in the midst of interaction with external systems especially if they're not under your control? It's just not that simple once you get into real, large applications. When in the middle of doing something where you need to chain necessary but ephemeral state through a process, and restarting is expensive or impossible because of the scope of the tasks, error handling must be performed to protect that action.

      Also, non-theoretically, Erlang has terrible error reporting when things do tank. :-P

    65. Re:The third option by BitZtream · · Score: 1

      Actually, what you should do ... is fix the offending code that caused state corruption.

      --
      Persistent Volume manager for Kubernetes - https://github.com/dwimsey/openshift-pvmanager
    66. Re:The third option by b4dc0d3r · · Score: 1

      In C# if you have no idea which exceptions to catch, you can always log or report the actual type, as in ex.GetType() and then do what you need to with that information. It is much more useful for me to run in debug mode, let the debugger stop on all thrown exceptions, and examine the type. You can either add that type to the types you catch, or fix the code so it doesn't happen.

      Every catch block should have a generic Exception, which can do something with the specific exception type. If you know to look for specific ones, like timeout or network related ones, you have the option of adding those.

      But I still don't understand the problem. If you want to know how to properly use a method, you should read the documentation. Go to msdn, type the class and method name, and at the bottom is a reasonable list of exceptions to expect. That isn't a waste of time.

      If you write enough C#, you will learn which methods need specific handling for certain scenarios, and which ones halt all processing. "What's best to do" is always halt processing and clean up, unless you have a specific reason to take an alternate path, such as auto-retry.

      Just one page at random, in case you haven't seen the exception list at the bottom of the page. Really simple to find.

      http://msdn.microsoft.com/en-us/library/ms584311.aspx

    67. Re:The third option by zraider · · Score: 1
      I agree with the above. Most developers turn exception handling into a god awful mess. In our shop, we have rules with regard to Java return values and exceptions:
      1. A method should do one thing, and be named for exactly what it does or returns.
      2. If the method is unable to successfully perform the one thing it's supposed to do, it must throw an exception.
      3. Returning null is not an acceptable course for error situations within a method. Null values indicate non-existence of the return data the caller is seeking, not an error.
      4. It is the caller's responsibility to determine whether it can safely continue if a method cannot complete its task successfully. If not, it must throw the exception upward, as it then cannot complete its own task successfully. This includes the entire program itself.
      5. For methods that return a Collection, a null value should generally never be returned. The caller is seeking a Collection of something, so it's either empty or it's not.

      Nothing profound here, but putting these together and articulating them has helped our staff to write better, more reliable code.

    68. Re:The third option by Anonymous Coward · · Score: 0

      Does it ring the bell on the operator console so the duty guy can remount the quarter-inch tape and IPL the mainframe?

    69. Re:The third option by turbidostato · · Score: 1

      "Library function A() calls some function B(), but you don't know this (closed source)."

      It's not because it's closed source, it's because I neither give a damn nor I should. Don't they teach about encapsulation to you youngsters these days?

    70. Re:The third option by TapeCutter · · Score: 2

      An exception mechanism is absolutely necessary to being able to contruct sane error reporting and recovery in a nontrivial code base, without unduly obfuscating the code

      The one thing that exceptions offer that return values don't is they allow the programmer to forget about the stack unwind and assume someone else will catch it higher up the chain.

      Useful yes, "absolutely necessary" no. I can't think of a faster way to kill a non-trivial code base than to try and convert it from one error handling method to the other. The stack trace problem is one reason many commercial source trees avoid exceptions (particularly C/C++) code. There is nothing worse than finding a tree with thousands of files and the only error handling is a try/catch around the main loop. The only real difference between the two is how they unwind the stack. My personal preference is the return code method since the writer is forced to think about the stack unwind at the time of writing.

      No matter which way you do it, handling errors adds time to writing the code. Not handling errors adds even more time to maintaining the code. Also in a commercial setting error handling is often insufficient when there is a real bug in a complex production environment, you also want fine grained tracing that the customer can turn on and then send you the logs. Again this takes an investment of time, but IMHO, good trace logs that are easy for the customer to configure are far more useful for debugging problems than error messages.

      --
      And did you exchange a walk on part in the war for a lead role in a cage? - Pink Floyd.
    71. Re:The third option by Anonymous Coward · · Score: 0

      If you are a Java developer writing libraries intended for re-use by others then you should ensure your library never throws a checked exception to the caller. Only libraries for critical systems should do this.

      That seems backwards. As a library/API writer, your goal is to encapsulate whatever your library does as a "black box", to minimize the cognitive-load on the people using it. Checked-exceptions (as opposed to using unchecked ones) are much better at making failure modes self-documenting and clear.

      Unchecked exceptions, on the other hand, are when you're not trying to build those boundaries, and where the "mostly sloppy" programmers can be trusted to already have a good idea of where then/where/why problems occur in the implementation.

    72. Re:The third option by geminidomino · · Score: 2

      Exceptions are not supposed to mean "something went wrong here". They should mean "there's a situation that is so unexpected that I don't know how to handle"

      Wait, but when you write an exception handler for it, then it's not only expected, but you know how to handle it, so it's not an exception anymore, so the program doesn't know how to handle it, which means...

      ARGH.

      Exception: Out of Stack Space. System Halted.

    73. Re:The third option by ppentz123 · · Score: 1

      running your application as a windows service (I think Linux has similar) solves this problem. Perhaps all applications should be 'services'

    74. Re:The third option by Anonymous Coward · · Score: 0

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

      Microsoft has had this feature for years!

      On Error Resume Next

    75. Re:The third option by Anonymous Coward · · Score: 0

      run in debug mode

      No one should ever have to run in debug mode to sort out a production problem.

      CAPTCHA = explains

    76. Re:The third option by mabinogi · · Score: 1

      No checked exceptions put a massive burden on the user of your code.

      Checked exceptions should only be used when
      1. The exception is likely to happen in normal use of the method.
      2. The calling code can do something sensible to deal with it.

      If it's not likely to happen, then there's no point enforcing immediate handling of it. A generic top level exception handling routine will do.
      Likewise, if the immediate calling code can't do anything about it, then it's just going to have to pass it out a level anyway, and at that point your Exception is polluting someone else's API, resulting in tight coupling. Either that, or they wrap the exception anyway - probably in an unchecked one, effectively making your checked exception pointless.

      --
      Advanced users are users too!
    77. Re:The third option by AmiMoJo · · Score: 4, Insightful

      What a douchbag you are. In the real world there are deadlines and never enough people on hand, so you don't have time to read every bit documentation for everything. That is perfectly acceptable as long as you are still capable of developing software that is robust and does what the customer wants.

      This is why we have testing. It is more cost effective to avoid getting bogged down in making something perfect and instead get it tested as you go, making improvements based on feedback. The only people who do it any other way are writing mission critical code that costs a fortune to develop.

      You know what? You're fired. Your products are all late, way over budget, the development team hates your anal retentive attitude, while your competitors left you in the dust.

      --
      const int one = 65536; (Silvermoon, Texture.cs)
      SJW, n: "Someone I don't like, and by the way I'm a fuckwit" - AC
    78. Re:The third option by narcc · · Score: 1

      You're wasting your time with this one. Trying to explain simple things to him is like trying to teach physics to a rabid dog.

    79. Re:The third option by Anonymous Coward · · Score: 0

      Wow, here you are talking sense about Java. When it was time to move to Java at work, I just decided all the hassle wasn't worth it. Never regretted it since.

      C# is actually a pretty nice language though. Java? Could've been nice if people just were competent and having enough time to make it right. Instead they went the other way and made things more complicated, buggy and ugly.

      Kudos for pointing out a glaring hole in the way people implement Javacode. I try to say these things to coders, but they just lack comprehensionskills and believes nobody else can program like them. Oh, the irony.

    80. Re:The third option by Anonymous Coward · · Score: 0

      The answer lies in proper stack traces, dumping arguments and even codelines with values.
      If you want nice errormessages, you can have a stack of programprocedures with different levels, which can tell you what function was attempted, and that it failed.

      There is NO reason to clutter your code with debugging or informational nonsense. When done right, it will all self-document (remember long and good variable, class and method-names).

      It can be done right. It will save alot of effort, reduce complexity and make you more happy. It just requires some effort to invest in it. The real problem lies in making everyone agree on a convention, but therein lies also the solution.

    81. Re:The third option by Horshu · · Score: 1

      I wouldn't want to fire someone for not reading the class documentation (lots of folks are still coming up in the world and haven't yet learned to appreciate having good documentation), but it would definitely be a catalyst for a teaching moment. I've been programming for almost 30 years and still take the (small amount of) time to read class documentation. Less excusable with a senior-level developer, but it's a lesson better learned through positive reinforcement than negative.

    82. Re:The third option by Anonymous Coward · · Score: 0

      Clam down. This is /. It stands to reason the people who don't read the articles or the summaries don't read programming documentation. Heck, they'd still probably do a better job than most programmers who profess to do this and foist their own implement of GUIs, etc. on unsuspecting users.

    83. Re:The third option by Anonymous Coward · · Score: 0

      I did the essence of this with much less code. Basically it looked like:

            startup() {
                  try{
                        rollback_all_uncommitted();
                  catch(ex) {
                          notify_and_die("cannot start: " + ex.message);
                  } ...
            }

            operation() {
                  try {
                        begin_transaction();
                        do_work();
                        commit();
                  } catch (ex) {
                        try {
                              rollback();
                        } catch() {
                              recycle();
                        }
                        notify("opration failed: " + ex.Message);
                  }
            }

      rollback_all_uncommitted() was so heavily armored that it only died if the situation causing all transactions to fail (e.g. network failure or disk failure) was still in effect -or- something modified the system state from outside and left it inconsistant. However, no other code had to be armored as rollback() would almost always succeed and rollback_all_uncommitted() would be called if rollback() failed (indirectly via recycle setting a flag that caused the top-level handlers to terminate and startup() called again).

    84. Re:The third option by Sarten-X · · Score: 1

      Sorry. A bit of that got lost in revision.

      Throwing the exception says "there's a situation that is so unexpected that I don't know how to handle it. Maybe you do." to the calling routine, under the assumption that the caller might know a little bit more about what's going on, and might have a way to work around the situation.

      --
      You do not have a moral or legal right to do absolutely anything you want.
    85. Re:The third option by Anonymous Coward · · Score: 0

      Jesus, man. You could have just told him to "RTFM".

    86. Re:The third option by MacDork · · Score: 1

      I think you're missing the my point because my example was over simplified. Nobody is going to write what I wrote. That would be stupid. My point is an exception in the finally block swallows the original exception, which is bad. Consider:

      try {
          throw new ImportantException();
      } finally {
          cleanup(); //-- throws unexpected Unimportant runtime exception under some circumstances.
      }

      This happens. Somebody comes along, subclasses, overrides cleanup(), and throws a runtime exception that wasn't originally anticipated. What now? Only call private methods in catch and finally? Wrap everything in a second try block? That's turtles all the way down. Dr. Dobb is correct in that the two methods we currently use leave a lot to be desired.

    87. Re:The third option by Anonymous Coward · · Score: 0

      Another option would be to use callback functions as error handlers promoting greater re-use. Java catch blocks cannot be generalized and re-used. But in, say, coffeescript, you can have the following:


      logfatal = (error) -> ...do logging and try to deliver 500 page...

      request.on 'error', logfatal
      fstream.on 'error', logfatal
      whatever.on 'error', logfatal

      You're still writing the error handling code, but it's reusable and signaling its use takes one line of code.

      Disclaimer: I'm a Java developer by day, so I'm way too familiar with try/catch and the scourge of checked exceptions. One of my biggest frustrations with Java is that exceptions are checked by default...I wish Java had chosen to make Exception be unchecked and had added a CheckedException that inherited from Exception. Developers should be forced to think of a reason why an exception should be checked rather than a reason why it shouldn't.

    88. Re:The third option by Anonymous Coward · · Score: 0
      1. There's nothing at all wrong with having a try around the majority of a function(at least if you've factored your functions correctly). Your method should be a specific action and your exception handling should be about what you do when that action fails. Error checking is not a debugging tool, and if you've written an exception you don't know how to recover from you're either meeting compile requirements in Java(which is the same thing as doing nothing) or wasting everyone's god damned time.
      2. The whole point of exception handling is to keep the program running(or gracefully exit), it's not a debugging tool, and displaying detailed exception information directly to the user of your program is bad design. Sure, log it, but don't spew that crap up on the screen because for one it'll freak out most users and for another, if you don't log it you won't get any meaningful information anyway. I still get told that the system had a "java error" when an exception pops up despite the fact that I write .NET for a living, no customer has ever actually told me what the error was, they see the exception and ignore it.
      3. This one is actually pretty poor form, though we all do it from time to time. About the only time it's actually appropriate is if a certain action failing really doesn't matter, at the very least you ought to be logging from that block.
      4. This one is also incredibly stupid.
    89. Re:The third option by west · · Score: 2

      I did the essence of this with much less code.

      Not "the essence" - *an* essence. A mere shadow of this error handler.

      You and I might be content with "recycle" and a sad little notification in an error log somewhere, but not this error handler.

      When it detected the CPU was failing, it would comb the register for life signs, route around the dying CPU, say last rites, mournfully bury it, and continue on its mission (as well as sending an email to accounting to order a new CPU). If the disk drive had been hit by lightning, it moved fast enough that it would outpace the bolt traveling down the electrical cord, rewire the junction box to send it current into the ground, power up the secondary backup drive, and send a work order to building maintenance to repair the malfunctioning lightening rod on the building's roof.

      The database being converted to EBCDIC? Hah! The error handler converted it to Armenian, just to show it could, before converting it Aramaic, then English, then Unicode, and then sending an email to project manager to let him know he could remove the Unicode phase in our legacy database update project.

      The error handler's philosophy was clear and built for an earlier age that even then, realized that man would in time become a lesser, diminished being, incapable of understanding the intricacies of exactly how the error should be recovered. As such, it did not depend upon the fallible hands of men to repair an unexpected error condition. It simply handled them *all*.

      Alas, even the programmer, in his wisdom, could not foresee the changes that would one day occur, and for those of us who held but a hundredth of the knowledge that he had accumulated in his years of service, we could no more alter his code than a gorilla could rebuild a finely tuned Swiss watch.

      And so his code was lost to the knowledge of men (except the revision control system).

      I'm sorry. All you have there is good, maintainable, effective program.

      What we had, and then threw away, was art made code.

    90. Re:The third option by SplashMyBandit · · Score: 2

      My example was intended to be more representative of real code where you chain exceptions.

      What now? Only call private methods in catch and finally? Wrap everything in a second try block? That's turtles all the way down

      Yes, avoid having overridable methods in cleanup. The same applies to constructors (a principle you may be more familiar with). I do use a second try block if I have to. Generally I catch, log in full, and then supress clean up errors; they are not significant to the operation of the program. At the end of the clean up catch I re-throw the original exception, because that is the exception that matters.

      "Turtles all the way down" is a possibility but I've never seen more than two exceptions deep in practice. IMHO the problem wih most programs/programmers is they don't look for potential exception causing problems early enough. If you code is thoroughly unit/integratation tested there are only two conditions that can then cause your program to fail:

      • 1) bad input data, or
      • 2) resource failure of some kind (bad disk, bad network, out of memory etc).

      Bad data
      The bad data is easily handled by checking preconditions of your program: validating all input data at the point it is received, read from file/database/network (throw IllegalArgumentException here); also checking preconditions before use that combinations of data that were not actually bad are consistent and the operation you are about to perform will not fail due to the data it is given (throw IllegalStateException here). If you look for bad data *before* you make any modifying operations you can roll back to a consistent and safe state easily. Your cleanup is often trivial because you detected the issue before you modifed state, not half-way through.

      Resource exhaustion
      Resource exhaustion can happen at any time, the best thing to do there is go back to a safe state (consistent data) and try and release resources. Thn try again. If you can't release resources then you have to abort the operation or abort the program. If you log the problem in a very clear manner some wetware can come along and correct the environment before trying again. This is why I mentioned good messages in logging is so important.

      Safe states
      We all know that the operations of software transistion the system from state to state. In a well-tested system any state that is attempted can fail for either of the reasons I pointed out: bad (insufficient or contradictory) data, or environmental/resource problems. The important thing is that if the attempted operation fails and the transition is aborted then the system is returned to a consistent state. In almost all cases this can be achieved by ensuring that the needed resources and data are acquired before any writes are made. It is not always the case this is so, but it very often is. Because this is true the "turtles all the way down" rarely happens (well, hasn't on any of the huge projects I've been on). More importantly, the existing constructs we have are more than sufficient in the vast majority of cases. Yes, you occasionally get nested catches but this is quite rare in my experience (programs doing millions and millions of transactions with all interconnects with all sorts of external devices and systems).

      Things developers can do
      So, what we can do as developers is:

      • * unit and integration test with good coverage
      • * validate all input data at the point we receive it (we can't use it until it is validated)
      • * check preconditions that before we attempt any operation we have sufficient and consistent data, plus have acquired any required resources (files, memory, network) as much as we can
      • * assume our operation can fail for any reason, and try and recover back to a consistent/safe state. Autorecovery is an often an option (eg. automatically re-attempting a network or database operation in the failure is likely to have been due a transit
    91. Re:The third option by SplashMyBandit · · Score: 1

      What you have written was the theory. In practice checked exceptions are painful to use. It is far better to use unchecked exceptions unless you are writing a system where failure is catastrophic, in which case checked exceptions are a useful cross-check on your code, despite the large burden they impose.

    92. Re:The third option by swillden · · Score: 1

      Logging every trivial exception with a full stack trace and parameters quickly bloats log files beyond the point of being useful.

      Disk space is cheap. Any decent OS provides a very comprehensive suite of text searching and manipulation tools. If you can't find what you're looking for in a "bloated" log file, you need to learn how to use those tools. You can't look at what you don't log, but you can ignore what you do.

      There's a non-obvious reason why a full stack trace is really valuable: It provides a sort of error "fingerprint". The same line of code might throw for different root causes (especially when it's library code throwing), but if two logged exceptions have the exact same trace, they're very likely two instance of the same error. You can set up automated monitoring of your log files to identify and count exceptions, categorizing them by stack trace. Have your monitoring system file a bug report for every unique trace, then let developers who analyze the problems indicate whether the error really represents a problem. If they determine it isn't, but it's not worth changing the code, let them close the bug and tell the monitoring system that that trace should not be re-filed or re-opened... unless its occurrence spikes, then the monitoring system should re-open the bug.

      There is one exception-logging error I often see that really is a problem, though: There's almost never any reason to both log and throw the same exception. Throwing and logging results in the same exception showing up twice in the log, which is very confusing because there's rarely any way to be certain that the two traces are the same error.

      --
      Note to ACs: I usually delete AC replies without reading them. If you want to talk to me, log in.
    93. Re:The third option by SplashMyBandit · · Score: 3, Insightful

      I agree, C# is a nice language. The failure of C# is that *the libraries* are not cross-platform. Note that the Mono libraries are not used by the majority of C# developers, and the Mono libraries are incomplete compared to the Microsoft ones, and will never be complete according to the Mono roadmap.

      With the world becoming more and more heterogenous with regard to CPU (ARM & x86/64), Operating System (Linux, Android, Mac, Windows) and environment (embedded, rich client and web) then cross-platform matters more than ever.

      The language benefits of C# over Java do not compensate for the massive superiority of Java for cross-platform development due to the huge number of fully cross-platform Java libraries. This is why forward-looking people prefer Java, despite the fact that C# has a few nice constructs. Does that make sense?

    94. Re:The third option by Anonymous Coward · · Score: 0

      No, I think he's right. You want the retry logic outside of the method that's actually failing in some way. In your example, acquiring a database connection, blindly retrying is a recipe for stressing an over-stressed resource. There should be something similar to a exponential backoff rather than simply retrying a second time. And implementing something like that is too complicated for a catch block.

      This also follows the design principle that a method or class should do one thing. If you have to use the word 'and' when describing what a method does, chances are it's doing too much. "It gets a database connection" is a great description of a method. "It gets a database connection and, if it fails the first time, retries" is an indication of a problem. Another good clue is to look at the tests you now need to write to cover all the functionality. Presuming that the method only deals with one exceptional case (a rarity), you've increased the number of tests you need to write from 2 to 3 (test initial succes, test error at first then success, test error twice.) If you have multiple error conditions, you've got a geometric expansion in the number of tests you need to write. As programmers, we like to avoid the word geometric as much as possible, especially when it applies to a manual task.

    95. Re:The third option by Anonymous Coward · · Score: 0

      This has been somewhat addressed with the try-with feature added to Java 7. The boilerplate error handling around closing a resource is handled for you.

      try (FileReader reader = new FileReader(...)) {
              reader.read(...);
      }

    96. Re:The third option by Z00L00K · · Score: 1

      You forget that not all manuals are good at defining the possible Exceptions thrown and sometimes they aren't even well documented. Even worse is the case when Exceptions are thrown by badly documented third party libraries because the Exception is thrown by something that they call.

      One experience I also have is that the Exception handling in C# is horrible because it's slow. And that can cause code that's more complicated than necessary. E.g. when adding data to a Dictionary class you can have two approaches - either first check if the item exists or expect an Exception to be thrown. Going the Exception path is good enough when you have interactive data but when you do batch processing of data it will really slow down things. And you can't entirely exclude the Exception handling anyway because you may still encounter something that gives an exception in your path - like when two different items gives the same hash code and the Dictionary class gives you an Exception anyway. So there you have code duplication and some headache of "how do I test that".

      If on the other hand the compiler forces you to handle the Exceptions then you will implement the Exception handling one way or another. So my post was more a kick at the fact that C# isn't properly declaring Exceptions than anything else. Having developed both Java and C# I would say that C# lacks a lot of stuff that should be there and permits a lot of things that allows for sloppy coding. C# is Java for Basic coders and if you have the culture from coding Basic and not the culture from coding a strongly typed language and required Exception handling you end up with ignored Exceptions and stuff like that. People do read the manual to the extent that they do see what the in and out parameters are - or goes for the supported help suggestions in the IDE and are set with that. Do you really refer to the manual for every method you call - like "ToString()"? What if the class you use overrides that method and it suddenly throws an unexpected Exception?

      Of course - Java isn't perfect either.

      --
      If builders built buildings the way programmers wrote programs, then the first woodpecker would destroy civilization.
    97. Re:The third option by Z00L00K · · Score: 1

      If the compiler was requiring the handling of all the thrown Exceptions you would be forced to implement them. What if the "ToString()" method is overridden and can throw an Exception that it normally doesn't? Do you always check that in the manual? Most people don't since it should just present a string representation, but suddenly things goes "boom", and if the Exception isn't handled because it's not forced upon the developer it's way too easy to miss.

      --
      If builders built buildings the way programmers wrote programs, then the first woodpecker would destroy civilization.
    98. Re:The third option by bar-agent · · Score: 1

      Lisp and Dylan use something called conditions. The signal() function (equiv. to throw) calls condition handlers; the stack is not unwound. You get a perfectly understandable stack trace that looks like normal function calls.

      Even better, the code can retry operations, since the stack is not unwound so the context is preserved.

      Here is a brief overview: http://opendylan.org/documentation/intro-dylan/conditions.html

      --
      i'd hit it so hard, if you pulled me out you'd be the king of britain [bash.org]
    99. Re:The third option by Anonymous Coward · · Score: 1

      http://tirania.org/blog/archive/2007/Oct-03.html
      Microsoft Opens up the .NET Class Libraries Source Code

    100. Re:The third option by Bengie · · Score: 1

      One experience I also have is that the Exception handling in C# is horrible because it's slow. And that can cause code that's more complicated than necessary. E.g. when adding data to a Dictionary class you can have two approaches - either first check if the item exists or expect an Exception to be thrown.

      You don't need to use exceptions. Most if .Net is this way. Exceptions are for "exceptional" situations.

      if(!Dictionary.TryAdd(key, value))
      MessageBox.Show("Key already exists")

      Exceptions are slow because the actually cause a context switch. try/catch has absolutely no overhead except in the case of an exception occurring. No branching from checking values if you don't have to.

      That being said, exceptions should be an extreme corner case. .Net offers plenty of ways to validate without using exceptions.

    101. Re:The third option by Cassini2 · · Score: 1

      The documentation will be wrong, don't even bother.

      I've programmed in more languages and on more platforms that most of the people here. The documentation is always a poor description of what the code does, and the researchers focused on formal methods would argue that any english language description of code must be a bad description.

      If you are on a project where every exception must be handled properly, then you must cross-check against the upstream source. However, even this approach is dubious.

      I've worked on a great many real-time embedded projects. When rare fault cases are analyzed, the software engineers preconceptions and real-life differ so radically, that faults and exceptions cannot be handled properly in advance in software. Software engineering has its limits, and you need to let the application testing people do their jobs.

    102. Re:The third option by Anonymous Coward · · Score: 0

      The point is, if you use RAII obsessively enough, you don't need to do anything to handle errors, except rethrow from the function. This happens automatically if you don't use try/catch. So that would cover (1) since the only meaningful thing a function can do in that case is to add a remark that the exception was caused in this function (giving an exception chain which recreates the call flow resulting in the exception). Then you throw all that exception chain information away because, information hiding (that covers (2)). And (3) covers the common "don't bother to check return codes" case. As for (4), that's what goto is for ;)

      Personally I like it when I don't have to wrap every operation in a class for RAII, so I hate hate hate exceptions as much as you do. To make a "simpler" mechanism, it rams OO down your throat. But it is a simpler mechanism, and to say it should be used along the same lines as return codes is simply wrong - the whole point is to not have to do that.

      You mention recovery, which is another issue. Very rarely is it possible to recover from an error, at the level where the error is first detected. If you intend to recover from an error that soon, it's really not an "exceptional" circumstance, so it's arguable that exceptions are not appropriate anyway. I had a nasty bit of Lua code which caught errors from file open in order to find a leafname on a search path. I changed it to use fstat. No errors; cleaner code. Of course, that relies on a well-designed underlying library (the file system). If try/catch is your only option, that's what you use. But this covers a tiny fraction of function calls that could produce errors/exceptions.

    103. Re:The third option by PurplePhase · · Score: 1

      Greetings and Salutations!

      Sorry, this is all off the cuff stuff, but: I like what you're talking about (I appreciate a new, informed, well-thought out perspective) and your code example. However I don't agree with your suggested almost-all-unchecked exceptions philosophy. But that's me.

      What some people see as the gratuitous use of checked exceptions in Java is, in my mind, not only a safety measure as you mention but also an educational tool: if programmers aren't forced to deal with exceptions (one way or another) when would they, in a normal day, ever consider what might go wrong? (I do have a low opinion of people claiming to be programmers nowadays..)

      Frankly, I *hate* that there are unchecked exceptions except in a couple circumstances because when something *does* go wrong with those my code is caught unprepared because I never thought or never knew to catch them. If everyone were forced to at least include the 'throws MyRuntimeException' in their method declarations, I wouldn't have to pull a Ruby and dig through all the (black-box) APIs to guess what could possibly go wrong.

      I think check exceptions are *very* necessary in Java just to keep programming from falling down to a much lower lowest common denominator. It is one of the reasons I really like Java (not that I really like Java in total, but that's another discussion). Part of that is an educational thing, part of that is due to poor tools, etc. All of those could help make up for Exceptions all becoming unchecked, but why not have it at least continued to be supported within the language? Well.. or encourage people to use more checked Exceptions?

      - when I first started programing what I'll call modern Java (2000), the boss showing us the ropes used Exceptions not only for signalling the state of technical errors, but also in certain subsystems as business signals. Problem was the internet as it was at the time claimed Exceptions used many more resources within Java. Of course now we have Spring and Hibernate it looks like any concern for computation resources has completely died out wrt Java servers.

      Can we make a system where it is all possible? Where we can attach a context/note to an exception within our code (perhaps it just pops out an extra message within the stack trace?).. hmm, though I don't know that there is a better mechanism than try-catch. Unless we also roll in the optional ability to define it in (standardized!!) aspects: Class X @ Method Y [@ .. what, Call Z?] if QException thrown add "wow, did the database/hibernate/etc. really just barf while we tried finding a person? [ID=$personId]"

      How about adding a.. (runtime?) setting where you can let "maybe-checked" exceptions fly through and on my system I (and maybe other devs and on QA boxes) will have them set as checked?

      Curious what your thoughts are - I'd enjoy seeing Java improve (rather than degenerate to a place where you can no longer compare primitive variables to primitive types because of the auto-coersion to objects - thanks lots, guys ):

      8-PP

    104. Re:The third option by PurplePhase · · Score: 1

      Mod parent up!

      Yay: IllegalArgumentException! Yay: IllegalStateException! Thanks for promoting those - they aren't used nearly enough!

      Turles

      After the first catch-within-a-catch, you've likely exhausted your options, though I think I was in a 3-catch situation once. If there were a "thisCantFailLogIt(...)" we'd use it, right? But I will guess that the depths of the catches is a signal that something within the system's philosophy is wrong, not Java itself. Doesn't mean I wouldn't consider alternatives, but when most alternatives' philosophy is "don't care, pay no attention to this" that erodes any trust I can have for them.

      Safe states

      Wow, okay, I have not worked in as complex of systems as you, so I'll take your word for it 8) I think part of the more general problem is that there are times when programmers have a hard time determining when/where that safe state exists/existed. And at times it is outside of their code/outside of code they have influence over.

      There is no silver bullet

      Oh, darn - I'm sad to hear DrD approached it that way: that leaves him in the role of a complainer instead of a changer :(

      Also: I've been wanting a way to add @precondition and @postcondition to Java. I can't find one though - do you know of one? I'd throw most of the 'validate all input data' in @precondition - at least Level 0+1 checks (required + value verification). As for @postcondition.. that gets even trickier, especially mid-transaction.

      Thanks much for posting!

      8-PP

    105. Re:The third option by Anonymous Coward · · Score: 0

      One example is when developing in C# you never know which exceptions to except unless you waste a lot of time reading the documentation for every class that you use or resort to do a general catch of Exception and try to guess what's best to do..

      the exceptions thrown by a method call are displayed when you mouse over a method in visual studio (works so at least in 2010) for most library classes present in .NET.

    106. Re:The third option by Zero__Kelvin · · Score: 1

      " In the real world there are deadlines and never enough people on hand, so you don't have time to not read every bit documentation for everything."

      FTFY

      --
      Guns don't kill people; Physics kills people! - John Lithgow as Dick Solomon on Third Rock From The Sun
    107. Re:The third option by Anonymous Coward · · Score: 0


      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,

      meaningful? Where have you been living? It may be meaningful to someone with at least a few years of programming experience, but no to 99% of the average program users.

    108. Re:The third option by PurplePhase · · Score: 1

      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...

      ...because it's a silly idea. Now you're just using exceptions as special return values. Exceptions are not supposed to mean "something went wrong here". They should mean "there's a situation that is so unexpected that I don't know how to handle". It's a different paradigm entirely. The idea is that rather than writing your program to anticipate every possible error (as the mathematicians so loved), the program should instead follow a more practical "hope for the best, plan for the worst" design. Rather than worrying about exactly which byte of a file couldn't be read, the program should just understand that something's wrong with the file, and its contents can't really be trusted.

      I disagree. You are welcome to use Exceptions in that way, but I want to see IllegalArgumentExceptions and IllegalStateExceptions when the related situations do, in fact, exist. Or are you implying that you'd rather remove certain other types of exceptions? IOExceptions? DatabaseExceptions? IndexOutOfRangeExceptions?

      As for what needs to be known when about a problem, that's a completely fluid topic and your sentence addressing it seems terribly overly simplistic to me. If you define your methods such that the responsibilities for dealing with an error are somehow always scoped only to the calling method... well, good luck to you and please let me know what public JARs you're involved with so I can stay away from them. If you instead suggest passing less information back to successive stack levels until a point where a decision can actually be made about how to deal with it and/or report it to a typical user - then we're probably not so far apart. So long as you log it with all the info possible.

      8-PP

    109. Re:The third option by pep939 · · Score: 1

      Of course - Java isn't perfect either.

      You don't say!

    110. Re:The third option by Anonymous Coward · · Score: 0

      You're fired.

      unless you waste a lot of time reading the documentation for every class that you use

      Again I say, you are fired. I would throw you out on your ass so quick it would make your head spin if you told me that as one of my employees. If you aren't reading the documentation you don't know how the method works and you don't need to be writing code.

      That is the most idiotic argument I've ever heard. Its the definition of bad programing, ON PURPOSE no less.

      99% of the documentation produced in development is garbage, or developed early in the process and NEVER given priority (by the PM's) to be updated to match what was actually produced. I GREAT developer looks at and understands the code (and shakes their head when the look at the doco because of how OFF and badly written it all is)

      FIRED!! Your an idiot who doesn't understand what you employee's do and/or have to deal w/ every day. In fact, you are the worst kind of boss.... one that thinks WE employees are there to support YOU... a GOOD boss is there to US employees so that in the end we all can support the CUSTOMER.

      Let me know what company you work at so I can sell my shares. NOW.

    111. Re:The third option by TheRaven64 · · Score: 1

      This is actually how exceptions were implemented in Smalltalk-80. It has a non-local return, so that blocks (closures) could return into their enclosing scope. An exception handler was actually a block that was executed when an error occurred. It usually did something and then unwound the stack, but the stack unwinding was optional.

      --
      I am TheRaven on Soylent News
    112. Re:The third option by Anonymous Coward · · Score: 0

      That was an interesting reply but I disagree with you when you say: "If you are a Java developer writing libraries intended for re-use by others then you should ensure your library never throws a checked exception to the caller" .

      I never wrote code in Java but I have written code in C++ for embedded systems. Granted.. you did mentioned above that checked exceptions would be valuable in my case because I need this level of reliability. But the problem is that libraries are meant to be used in different ways by different programmers with different needs. In my case, I would sometimes get libraries written in C++ without the source code. I would have to rely on the poor documentation in order to make sure that my system does not crash due to an unhandled exception. How can I possibly prove reliabilty? In some cases, I had to try and read the assembly code in order to spot routines that would throw and others that wouldn't. It was often the case that I had to simply forego the usage of the C++ code because I could not prove that it wouldn't crash due to some exception we may not have caught in test.

      So I would argue exactly the opposite. If you write a library, all exceptions should be checked exceptions. If the developer who uses the library is not interested in this level of reliability, he can wrap it and throw unchecked exceptions... or ignore exceptions... or do whatever he wants. But when you write a library, you want it to be useful. If you do not use checked excitptions, you have simply eliminated the possibility of using that library in a number of applications that require that level of reliability.

    113. Re:The third option by Shingetsu · · Score: 1

      I would actually agree with that. Most of us forget that we've at one point spent tons of times reading documentation for the simplest things, like fprintf. At some point one just starts assuming that they know how to use a class/method by it's name and "auto-completion" in IDEs. However, from my experience anyway, that's where 90% of bugs happen. Kind of why I made the switch to vim and actually READ THE DOCS. It doesn't take that long, you just need to get the overall idea. And saves much more time in debugging later.

    114. Re:The third option by ultranova · · Score: 1

      Checked exceptions are valuable in Java. Those that are against them don't understand that they are very useful for certain classes of problems - systems that have to be reliable.

      Except that they're completely useless there, because as you demonstrated, they're easily wrapped into non-checked exceptions. Or better yet, just declare each and every function as throwing Exception. And of course our old friend NullPointerException is not checked, nor are stack- or heap overflow errors.

      The mistake the Java designers made was that they made the library throw checked exceptions rather than unchecked ones.

      No, the mistake they made was force some kind of reaction to checked exceptions. As is, it's impossible to automatically tell which functions actually handle the exceptions they might get rather than just use autogenerated copypasta to shut the compiler up. If un"handled" checked exceptions would simply default to propagating upwards the stack, it would be trivial. And besides, in most cases that's the best option anyway - if an operation fails, the chances are that the subsequent related operations can't be performed either.

      The whole "you must handle checked exceptions" thing is an attempt to make people who don't care care, and that's an impossible task.

      --

      Forget magic. Any technology distinguishable from divine power is insufficiently advanced.

    115. Re:The third option by SplashMyBandit · · Score: 2

      Interesting ideas.

      To solve the "how do I let the caller know what they can safely do problem" I use the @throws Javadoc tag. Usually I've have several @throws tags for the IllegalArgumentExceptions that can get raised, and some @throws IllegalStateException if some set-up or required previous method call has not been done.

      If you need to pass additional data back I'll just make an RuntimeException derived class of my own and add in the required properties. I'll even add in an enumeration of the reasons the exception is raised so I can pass causes back through webservices and have the client decide which enums they can handle and which enums they'll just log and abort the attempted operation. While enum error codes are discouraged when not using exceptions I find then convenient attached to exceptions as they provide nuances for making decisions on when handling runtime exceptions. In this case error code enums allow decision making without needing to create a whole class hierarchy of exceptions (a somewhat old fashioned and clunky way of doing the same thing, but requires a lot more lines of boilerplate code, and swells the number of classes you have to deal with).

      The idea of using RuntimeExceptions rather than checked exceptions is that the caller doesn't have to think about conditions they can't handle or recover from, not that they don't think about error handling at all (if you are checking preconditions and consistent state everywhere it will in your thinking anyway).

      The idea is to keep it all as lightweight. The client of your library doesn't have to deal with exceptions they have no chance of handling (eg. most resource exhaustion issues), but can easily see what not to do to avoid raising exceptions with the arguments they supply (because the JavaDoc tells them which objects can and cannot be null or blank/non-empty strings, what are valid ranges of values etc etc). Besides explaining the intent and responsibilities ('contract') of a method, what the caller can do that would cause the method to fail, the JavaDoc also needs to explain what units a parameter is in: is it in meters, feet, kilometers, nautical miles; is accrued interest for a period of days, months, a quarter, annual, etc. That's what makes the JavaDoc so useful and so important, and why good programmers also fuss about getting their JavaDoc right :)

      With regard to using exceptions for 'signalling'. Exceptions are supposed to be 'exceptional'. It is generally considered bad style to use them for flow control since alternatives designed for the purpose exist. Break/continue and labelled goto are all designed for doing that.

      Java can be crufty, but it can be made lightweight (less of a hassle to use, JavaBeans designed for ease of use), very robust, and easy to re-use (good Javadoc and JavaBeans). Unfortunately, most examples of Java are trying to demonstrate complex techniques rather than emphasizing that the code should be kept as simple and lightweight as one can manage (which is the real art of design).

    116. Re:The third option by Anonymous Coward · · Score: 0

      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 suggest that the majority of cases is actually a bit different. Seems to me, most of the time, while an exception cannot be reliably resolved and needs to be escalated, some action is also required from the code around the exception before escalating. In that case, exceptions as first class language features are great, because it makes it very easy to go from a simple exception catch to a more sophisticated clean-up, both for the general case (finally) and tailored to the exception situation (catch, do something, and rethrow, perhaps also stopping by in finally). All nice language features that unfortunately aren't always well utilized.

    117. Re:The third option by viperidaenz · · Score: 1

      That's nice, until someone does this:
      try {
      ....
      } catch (Exception e) { // BTW: NEVER catch Throwable unless you plan to manually re-throw the exception. I don't you swallowing OutOfMemoryError's or ThreadDeathException's.
      } finally {
      return blahblah;
      }
      Then the exception gets ignored and the return blahblah is what the caller sees.

    118. Re:The third option by viperidaenz · · Score: 1

      I like IE's Javascript error "Type Error". No line number, nothing.

    119. Re:The third option by SplashMyBandit · · Score: 1

      You are correct. If you re-look at my example you'll see I transform the exception before throwing. The finally clause is executed but the return is not. The exception still propagates (which is why you can use finally in the presence of exceptions). In addition, you'll find you get a warning that "finally does not complete normally" to indicate there is a problem (at least I do in Eclipse).

      So, I think you are a bit confused. Firstly, I don't advocate suppressing the exception, I advocate transforming and re-throwing. If an exception was happening on cleanup and we were to suppress it then it should be fully logged. Never simply annihilated.

      Secondly, you seem to think that the return in the finally will 'trump' the exception. It doesn't. Fortunately the Java designers and compiler writers foresaw this and do the 'right' thing by ignoring the exception. Therefore, my example still stands (provided you either throw and exception wrapping the cause, re-throw the original exception, or log the suppressed exception were you have 'handled' it). This is not hard :)

    120. Re:The third option by SplashMyBandit · · Score: 1

      Oops, I'm half asleep today. The line "do the "right' thing by ignoring the exception." should instead refer to ignoring the return statement if an exception is raised. Apologies. Hopefully it makes more sense now.

    121. Re:The third option by MacDork · · Score: 1

      It is a shame Dr Dobbs didn't talk about these good practices

      You have completely missed the point of the article.

      The point is that there should be some language design that makes these "good practices" entirely unnecessary. These rituals you've been taught are nothing more than an indication that the language designers haven't got it right yet. The article is a plea for new ideas, not a plea for instruction on how to make the old ones work when they obviously have serious limitations.

      This Dr. Dobbs piece reminds me of another article I read recently. It was very good. Perhaps you'll find it interesting.

    122. Re:The third option by viperidaenz · · Score: 1

      The return in the finally statement is not ignored, If the finally block does not complete normally, you'll lose the exception. That's the reason you get a "finally does not complete normally" warning.
      This code
      public class Main {
      public static void main(String[] args) {
      System.out.println("start");
      fail();
      System.out.println("end");
      }

      private static void fail() {
      try {
      throw new RuntimeException("oops");
      } finally {
      return;
      }
      }
      }
      will print the following:
      start
      end

      Not:
      start
      Exception in thread "main" java.lang.RuntimeException: oops

      I don't know where you learnt Java, but you learnt it wrong.

      It's usually bad practice to catch Errors and re-throw them as Exceptions. They're Errors because you're not supposed to recover from them.

    123. Re:The third option by SplashMyBandit · · Score: 1

      Thanks for the link. I skimmed it quickly and will read again once I have more time.

      To be honest I don't think you can reduce the complexity of error handling that much. The complexity arises not because we don't have the correct keywords but because it is application-specific as to whether an error is recoverable or non-recoverable and for the recoverable cases there are a whole bunch of mitigations that may or may not be applicable. To handle this you need application-specific code. Adding keywords will reduce complexity, but far less than most people think.

      Also, my original statements are still valid. In Java you would ordinarily need to write *zero* lines of code to cope with most error conditions. You cannot get more simple than this. The case I was describing is because the standard library, or poorly written user-defined libraries, force you to deal with problems instead of allowing them to propagate through to someone that can handle them (which may be the highest level of the program). The problem is the standard libraries, not the language itself.

      Now the associated problem with exception throwing is handling cleanup. Again in Java it should require *zero* lines of code. That is the whole point of the Java garbage collector (GC), to ensure eventual resource release under exceptional and multi-threaded conditions (that is, in non-deterministic situations). For most resources the GC works perfectly. You may choose to release resources sooner for efficiency (eg. closing network connections) or if you are accessing native libraries. A 'using' keyword (like C#) would be handy here. I believe having such a feature is under consideration.

      So, I personally think Java as a language has reasonable design for error handling. In general zero extra code needs to be written. Only application-specific handling code needs to be written if the developer chooses to handle and log exceptional conditions (which I would argue is good practice no matter what language you are using, but it is not strictly necessary). Apart from 'using', adding arbitrary keywords is unlikely to help reduce the complexity below the zero lines required at present. So no, it wasn't I missed the point they were trying to make - I simply disagree that adding extra keywords would help (since Java does most reclaimation automatically without programmer intervention). The problem is in the Java libraries, both with checked exceptions forcing the programmer to propagate exceptions they cannot handle (eg. at the current level of a layered system), and in special cases that require manual resource release rather than letting the GC do its job. That is the real problem to be solved (while still retaining Java's fantastic runtime performance - which doesn't matter for many applications, but does happen to matter for mine).

    124. Re:The third option by Anonymous Coward · · Score: 0

      Cara Mencari Pacar. Namanya manusia kalo gk punya pacar, rasanya gimana gitu. Setiap manusia normal yang belum punya pastinya ingin cepat punya pacar. Wajar menginginkan kekasih yang sempurna secara fisik/kepribadian. Punya pacar lebih dari satu, enak gak ya Di posting ala pepino, Cara Mengatasi Patah Hati. Setiap orang mungkin pernah merasakan patah hati. Saat-saat patah hati serasa dunia akan hancur, gak ada lagi harapan yang bisa jadi semangat. Di posting ala pepino, Cara Menghilangkan Jerawat. Semua orang pasti menginginkan punya wajah halus,bersih dan tak berjerawat. Di posting ala pepino, Cara Menghilangkan Komedo. Kurang percaya diri gara-gara komedo? Masalah komedo memang bisa bikin kepercayaan diri kita turun. Menghilangkankan komedo tidak susah kok, asal kita mau merawat secara rajin dan teratur. Di posting ala pepino

    125. Re:The third option by SplashMyBandit · · Score: 1

      Thanks for the link. The license is not Open Source, which makes it useless for many of us. In fact, because the code is not Free Software we are best to avoid looking at it - there is a world of legal pain to be had if it is proved you copied code or ideas (just ask Google, fortunately Oracle pretty much lost that battle so OpenJDK is in the clear).

    126. Re:The third option by SplashMyBandit · · Score: 1

      Lol. Before I posted I wrote and tested an example myself and got a result where the exception was caught in main (I had a catch clause there). When I try your example I get as you do. So I'll consider myself corrected (see, I'm willing to accept I was wrong, how often does that happen on Slashdot). Of course it is a style mistake to return in finally (just as it is a mistake to use a non-final method in finally or in a constructor). The correct style is there should be a single return should be at the end of the method (which is why lint tools like Findbugs/PMD will whinge when you don't do this) - to make the code readable and possibly to avoid the issue you raised. I hadn't encountered this before because I've never made the mistake of returning in finally, since I try follow the style rules of Findbugs/PMD (got into the 'lint' habit as a C/C++ dev) :)

    127. Re:The third option by SplashMyBandit · · Score: 1

      FYI: return from finally is described in the Java Language Spec 14.20.2.
      Because of the nastiness they banned return from finally in C#. Unfortunately it is not enforced in Java, so it just has to be a matter of style (and pay heed to the warning you get - of course code should be written to avoid warnings, they're there for a reason, yeah?).

    128. Re:The third option by Anonymous Coward · · Score: 0

      Don't hide the error text goddammit! Way too many progrmers think that the error text is too technical or scary for the end user and as a result whenever something goes wrong it is almost impossible to figure out why. Even if your errors are a cryptic mess they at least give the end user something to plug into Google.

    129. Re:The third option by Your.Master · · Score: 1

      Generally, the later you catch a flaw, the more it costs to fix it, and it scales exponentially. Testing finds failures earlier in the stack. Some amount of failure is unavoidable, thus testing is incredibly important -- you're never going to know whether your new UI idea really works in practice without actual usability testing, for example. But it's also a last resort.

      Reading documentation is almost always worth it in the final analysis. I'm sure you can come up with counterexamples of trivial classes with self-explanatory functionality, and to some extent you can pattern-match against an existing codebase to use something without explicitly going through the documentation, but it's never ever wasted*, and that's especially true in a world with deadlines. In a world without deadlines, you can do your black box coding as an intellectual exercise and get great insight into why things are the way they are. If you want to come in on time and in budget, you need to understand what you're doing quickly.

      * Well, it can be wasted if the documentation is inaccurate or otherwise terrible, which are also development realities.

    130. Re:The third option by viperidaenz · · Score: 1

      I don't see a problem in calling a non-final method in a finally block. It's done all the time (mostly methods like java.io.Closeable#close, etc)

    131. Re:The third option by SplashMyBandit · · Score: 1

      It is a recognized problem. It is more well known that a non-final should not be used in a constructor - perhaps you've heard of this?

    132. Re:The third option by viperidaenz · · Score: 1

      I have. Leaking instances of uninitialised objects can cause many headaches. I don't see a problem with calling non-final methods in a finally block. There are security concerns with calling non-final methods (you can override a method and throw an exception to change the expected program flow) but that's about it.

    133. Re:The third option by Anonymous Coward · · Score: 0

      Very few things will crash *the* Erlang OS process. An Erlang process is *not* an OS process. It is a persistent function call's highest scope. In other words, a specialized closure-based coroutine, inside of Erlang's VM, who's interface and data handling is very OS-like. The idea is not that your application should fail, but that the application state that is coupled to the exception should fail, and then something else pick up the pieces, because you can't and won't always be able to plan for, or figure out, every little error that might happen (especially external errors, such as hardware errors, or OS policy side effects). But, you typically can figure out points in a program where errors are either going to be likely, or where they may be especially dangerous to your results.

      These Erlang processes do not share data (lock-free asynchronous concurrency!). They must create messages, which are sent to another process, to communicate. With no shared mutable state (failure-prone IO handling obviously blurs this, sometimes), you can start at a root process, or pool of root processes, and effectively model failure boundaries as subprocesses. Of course, if you go across a network, that needs to be a failure boundary. But, while you may have to do some work to get the servers initially set up, talking on a connection that's suitable, etc, there is no difference in *the code* between communicating to a local Erlang process and an Erlang process running a thousand miles away.

      Also, Erlang is an impure functional language, with continuation passing for looping, so even in-process work gets one thinking in a data-flow kind of way (IE, CSP). It's obvious what state exists and is being manipulated, on one hand. But, you also have to explicitly keep passing it around, on the other, and usually end up making as many processes as you otherwise would make distinct objects.

      So, it's not a case of application crash, typically, but rather isolation of the fault, and removal of the corrupted state, where the stateful process (coroutine) "crashing" does not mean the whole OS process goes down (though it may, on some errors, and that can get tricky, so it by no means replaces the need for external persistence mechanisms, though there are a couple written in Erlang, and at least one, Mnesia, *for* Erlang). What it allows is for you to basically say:
      - This chunk of code should be sent parameters, and do something that may cause problems if it fails, so I'm going to spawn a process for it, or keep up a persistent worker process. It will receive its work orders by way of a serialized message.
      - If I can gracefully recover locally, I will implement try/catch blocks, and do so.
      - If I cannot recover gracefully, or if my graceful recovery methods fail, the failure will automatically propagate to some higher-scoped point, until it is is handled, which may involve the process (coroutine) being killed.

      It is fine to do the above, because any state change that may propagate from one Erlang process to another, by way of messages, is effectively a transaction. Nested function calls, and nested Erlang process communication represent a way to manage nested transactions.

      So, you get to choose if, where, and how an error is handled, and it's typically easy to isolate it. It's common to create processes that just handle an external IO layer, that just act as watchdogs, that are proxies between groups of processes, etc, to allow quick and easy restarting of small portions of the program, and to explicitly keep checkpoints for sets of intermingled state interactions.

      Useful logging requires setup, but it's easy enough. The base system doesn't want to have to know or care where or how the logs exist.
      http://www.erlang.org/doc/system_principles/error_logging.html
      http://www.erlang.org/doc/man/error_logger.html

      The one huge downside to Erlang, in my view, is that even semi-adequate OOP implementations, like Java, handle coupling responsibilities to their data structures better, using well-defined object

    134. Re:The third option by Anonymous Coward · · Score: 0

      >...and then let them deal with it.
      Hahaha! What makes you think 'them' will deal with it any better?

    135. Re:The third option by Anonymous Coward · · Score: 0

      I've got new for you, the original programmer can't handle it either...

    136. Re:The third option by Anonymous Coward · · Score: 0

      You just lost your stack trace. If you're going to do this, you'll want:

      throw new UnimportantException(e);

    137. Re:The third option by Anonymous Coward · · Score: 0

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

      I have seen a lot of programs that just ignore errors. It screws up testing so bad that they would get the product out faster by putting in proper handling in the first place.

      In fact, the handling of errors is part of the job. Problems occur, and the user has to have a way to get back to work. Many non-fatal errors should actually be handled at the top level as part of the visible code, with understandable messages. Even technically fatal error should often have a recovery path.

      The code for the main "no errors" path is not the whole thing. The program is not done until it is robust and usable. To do otherwise is just lazy, because it does not actually save time.

    138. Re:The third option by SplashMyBandit · · Score: 1

      Can't see the problem? what happens when the overridden method doesn't call the parent implementation. You then don't get resource cleanup. Same thing for constructors (don't get the allocation you expect). These are very dangerous so most style guides recommend not to do it (at least in the constructor). Here's a link with a discussion for you to ponder (since Netbeans warns you that overriding in certain methods is bad):
      http://stackoverflow.com/questions/3404301/whats-wrong-with-overridable-method-calls-in-constructors

    139. Re:The third option by viperidaenz · · Score: 1

      That's not the reason why you shouldn't call non-final methods from a constructor.

    140. Re:The third option by Anonymous Coward · · Score: 0

      I agree this is my philosophy as well: "Throw as early as possible, catch as late as possible"

      I would list these as the ways of dealing with errors:
      1. All return values are for error conditions. (C tends to do this.)
      2. Some return values are error conditions. (Null or NaN)
      3. Exception handling.
      4. Errors are ignored. (Perl)

      But in regards to #2, let's have separate it into:
      2a. Some return values are error conditions, but error conditions don't cause more exceptions. (NaN)
      2b. Some return values are error conditions, but error conditions cause many more exceptions. (Null)

      I think 2a is a powerful concept. The code doesn't blow up but the NaN value is preserved so the final result is NaN. The concept works in numerical programming. I wonder how it can be extended to general programming?

    141. Re:The third option by n7ytd · · Score: 1

      In the real world there are deadlines and never enough people on hand, so you don't have time to read every bit documentation for everything. That is perfectly acceptable as long as you are still capable of developing software that is robust and does what the customer wants.

      This is why we have testing. It is more cost effective to avoid getting bogged down in making something perfect and instead get it tested as you go, making improvements based on feedback.

      How do you develop "software that is robust" without understanding the libraries you are using enough to understand what the range of valid values it accepts and what exceptions it may throw?

      Shops that take shortcuts like not gaining an understanding of what they are doing, because "this is why we have testing" are also the type of shops that never have enough time for proper testing.

    142. Re:The third option by MikeBabcock · · Score: 1

      I have a lot of situations like this where I simply do error counters in a helper function like this:


      for (int attempt = 1; attempt <= MAX_RETRIES; attempt++) {
              try {
                      return something_that_might_fail();
              } except (expectederror e) {
                      log_error(attempt);
              }
              return null;
      }

      --
      - Michael T. Babcock (Yes, I blog)
    143. Re:The third option by MikeBabcock · · Score: 1

      One of the reasons I've always liked DJB's code is that his C style is to check every return and just die on errors. The philosophy being that its much more secure to stop doing everything when a real error happens than to hobble along and pretend it wasn't one. Unfortunately, that ends up looking a lot like this:


      int readclose_append(int fd,stralloc *sa,unsigned int bufsize)
      {
          int r;
          for (;;) {
              if (!stralloc_readyplus(sa,bufsize)) { close(fd); return -1; }
              r = read(fd,sa->s + sa->len,bufsize);
              if (r == -1) if (errno == error_intr) continue;
              if (r len += r;
          }
      }

      --
      - Michael T. Babcock (Yes, I blog)
    144. Re:The third option by MikeBabcock · · Score: 1

      That's why you do a FileWriter.flush() inside your exception handled code and put the close() in the finally block where it will essentially never throw now.

      --
      - Michael T. Babcock (Yes, I blog)
    145. Re:The third option by MikeBabcock · · Score: 1

      I have a piece of code that relies on several complex regular expressions. Taking unit testing a bit far because I know random changes might get made to the code, I threw in a function that tests the regex's against various edge cases I've run into. That few wasted CPU cycles in this type of situation has saved me accidentally shipping bad code several times, which is much more valuable than the cycles themselves.


      Pattern regex1 = Pattern.compile(REGEX1);
      for (String regex1test: REGEX1TESTS) {
              if (regex1.matcher(regex1test).groupcount() != 1) {
                      throw ...
              }
      }

      --
      - Michael T. Babcock (Yes, I blog)
    146. Re:The third option by Brandybuck · · Score: 1

      And if it crashes and pukes all over the user's desktop, then that's their problem...

      I must be a bad developer, because I never throw an exception if I don't know explicitly who is going to catch it. Because the minute I do some other developer will fail to catch it and the program will crash.

      --
      Don't blame me, I didn't vote for either of them!
    147. Re:The third option by Anonymous Coward · · Score: 0

      I often pose exception handling dilemmas to interviewees. My favourite answer so far is to call System.exit from the catch block. Before you say it - no, we were not implementing a main method.

    148. Re:The third option by Hognoxious · · Score: 1

      I've programmed in more languages and on more platforms that most of the people here.

      Carry on, maybe you'll find one you're good at.

      The documentation is always a poor description of what the code does

      Teaspoons are pretty useless for carving a roast.

      the researchers focused on formal methods would argue that any english language description of code must be a bad description.

      What would they suggest you do in the real world, when there's a horrid kludge that's there because the dickwads in sales reused a product code, because WiFi card foo doesn't report error codes properly, or because whoever designed the payroll system had never heard of twins?

      --
      Confucius say, "Find worm in apple - bad. Find half a worm - worse."
    149. Re:The third option by Hognoxious · · Score: 1

      Generally, the later you catch a flaw, the more it costs to fix it, and it scales exponentially.

      I bet it doesn't. Apart from nuclear chain reactions and diseases, very few things do.

      --
      Confucius say, "Find worm in apple - bad. Find half a worm - worse."
    150. Re:The third option by Hognoxious · · Score: 1

      I would say that there is a forth way

      You're a Jupiter Ace enthusiast?

      --
      Confucius say, "Find worm in apple - bad. Find half a worm - worse."
  2. here come the category theory nerds by Anonymous Coward · · Score: 0, Troll

    Monadian beef bbq.

  3. Third option. by Andy+Prough · · Score: 5, Funny

    I think MS already tried the blue screen.

    1. Re:Third option. by LordLimecat · · Score: 1

      And of course Linux just says "oops" and tries to continue...

    2. Re:Third option. by Anonymous Coward · · Score: 0

      That's so 20 years old code. Now they only show a big, sad ASCII face, with blue background.

    3. Re:Third option. by Osgeld · · Score: 2

      then usually fails

  4. ON ERROR GOSUB 30000 by bunratty · · Score: 3, Funny

    BASIC has had it all along!

    --
    What a fool believes, he sees, no wise man has the power to reason away.
    1. Re:ON ERROR GOSUB 30000 by TheGratefulNet · · Score: 1

      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.

      --

      --
      "It is now safe to switch off your computer."
    2. Re:ON ERROR GOSUB 30000 by Z00L00K · · Score: 1

      OK, then we have the following:
      0 = Go to 200.
      =0 = Go to 300.
      NaN = Go to 400.

      Of course - the NaN was not implemented in classic Basic.

      --
      If builders built buildings the way programmers wrote programs, then the first woodpecker would destroy civilization.
  5. Errors by Anonymous Coward · · Score: 0

    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);
    }:

    1. Re:Errors by Smallpond · · Score: 1

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

    2. Re:Errors by interval1066 · · Score: 2

      errno is just a return code in other clothing.

      --
      Python: 'And then suddenly you have a language which says "we're all stuck with whatever the whiniest coder wants".'
    3. Re:Errors by Smallpond · · Score: 1, Insightful

      All code is just assembly language in other clothing.

    4. Re:Errors by Carewolf · · Score: 1

      In other ways it is more like an exception in that you can ignore it and thereby pass it to functions higher on the stack as long as you do not set a new error yourself.

    5. Re:Errors by Carewolf · · Score: 1

      Btw there are even more options. For something truely exception worthy you can also throw a POSIX signal, and let the signal handler either handle it and resume the process/thread, or give up and terminate the process/thread.

    6. Re:Errors by shutdown+-p+now · · Score: 1

      In case of errno, though, there are no further levels of abstraction added here. It's literally the same exact thing, just moved to a thread-local variable instead of a return value. But it still has all the disadvantages - you have to remember to check for it (which, if anything, is even easier with errno), and it uses a single nondescript integer to describe any error.

    7. Re:Errors by TopSpin · · Score: 2

      POSIX signals themselves are a bit of a horror. Like C++ exceptions (as Google correctly points out) they have implications for `other' code, the worst case being code that has not be written to cope with interrupted system calls. Also, signal dispatch has portability problems; signals did not anticipate threads and POSIX was slow and iterative in its promulgation the standard solution, so many subtleties have appeared among implementations.

      However, I think you have the right instinct. I personally find myself working in explicitly event driven environments frequently. Node and TCL for example. Here you can not indulge the illusion of absolute control over the fate of the instruction pointer. Any time you `yield' to the runtime you wind up entering your code at some other point as the runtime dispatches events.

      Using the event model to cope with errors and exceptions would mean that anything that would traditionally throw an exception or return a error code would instead be a yield point and may generate an error event. You would then provide a handler to receive these events with enough context to cope with the problem.

      I've come to the believe the event driven model is a far better model for the actual conditions one assumes when implementing logic. The moment you write main(){...} you are subject to signals that are handled by a collection of default handlers. One day the system becomes non-trivial and you must 'fix' these handlers. Perhaps you have no business writing main(){...} and adopting a naive, linear model in the first place. Instead, you're supposed to implement (the moral equivalent of) a signal handler instead.

      Down at the bottom, where CPUs process machine code, hardware interrupts are endemic. The hardware itself imposes the event model. It may be the case that most machine/assembly code still written by humans today are simply event handlers; logic servicing hardware interrupts.

      --
      Lurking at the bottom of the gravity well, getting old
  6. People just doesn't get it by Anonymous Coward · · Score: 3, Insightful

    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.

    1. Re:People just doesn't get it by Anonymous Coward · · Score: 0

      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.

    2. Re:People just doesn't get it by Smallpond · · Score: 1

      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.

    3. Re:People just doesn't get it by joe_frisch · · Score: 4, Interesting

      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.

    4. Re:People just doesn't get it by pla · · Score: 4, Insightful

      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.

    5. Re:People just doesn't get it by generalized · · Score: 1

      The words 'error' and 'exception' do not have fixed interpretations. Indeed, they can be the exact opposite of your usage: http://www.haskell.org/haskellwiki/Error_vs._Exception.

    6. Re:People just doesn't get it by Anonymous Coward · · Score: 0

      In his reality, that could never happen.

    7. Re:People just doesn't get it by Anonymous Coward · · Score: 0

      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.

    8. Re:People just doesn't get it by roninmagus · · Score: 2

      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.

    9. Re:People just doesn't get it by Anonymous Coward · · Score: 0

      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.

    10. Re:People just doesn't get it by ruiner13 · · Score: 5, Insightful

      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

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

      --

      today is spelling optional day.

    11. Re:People just doesn't get it by Anonymous Coward · · Score: 0

      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.

    12. Re:People just doesn't get it by Anonymous Coward · · Score: 0

      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

      I've always found that while it makes things "easier to read", that's a false sense of easiness. The code is doing things that you can't see immediately. Easier to debug? No way, because you've got that same problem of things being non-local.

      If your code is complicated, it should look complicated. If it's too complicated, maybe you should refactor rather than shoving all the error handling code into la-la land.

    13. Re:People just doesn't get it by Decameron81 · · Score: 1

      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.

      Sorry but that can only come from a lack of experience. No offense intended, but your point of view is extremely naive.

      For instance: you should use assertions to detect coding errors within your module / your scope of trust (app makes a call to another method in the same app), and other traditional mechanisms outside that scope, when distrust is needed (app shouldn't trust server & vice-versa, app shouldn't trust user input, library shouldn't trust app, config files should never be trusted to be properly formatted or have valid data, etc). If you blindly trusted all components from ever failing, you would be letting an eventual error in one component propagate to all other components. This basically translates to unhappy clients calling you at night because your app is crashing, and you finding out hours later that someone unplugged the server or put a bad configuration value somewhere.

      --
      diegoT
    14. Re:People just doesn't get it by Anonymous Coward · · Score: 0

      Ironically, the case you link to is about using exceptions for control flow. I doubt anyone really thinks the happy path should be handled with exceptions. A file which doesn't exist or a hostname that can't be contacted IS an exceptional situation. But returning some data isn't exceptional at all.

      As for the WAY more expensive in .NET thing: Yes, relatively they are more expensive. But the quoted SO itself says:

      Using the code below, testing revealed that the the call+return with no exceptions took about 1.6 microseconds per iteration, whereas exceptions (throw plus catch) added about 4000 microseconds each.(!)

      Which is almost exactly the amount of time I was expecting when I chuckled at your "OMG OVER 1000" style response. 4000 microseconds = 4 milliseconds. If you are doing this in a tight loop or something, or this event happens often, then yes perhaps exceptions are going to bite you. But then, why are you doing the same thing over and over and expecting a different result anyway? Some people call that insanity.

    15. Re:People just doesn't get it by Anonymous Coward · · Score: 0

      This is partially due to the fact that all .Net exceptions are unchecked. This means that every time you throw, you might end up in the debugger (or a crash dialogue box). If you throw a checked exception, it should be possible for the compiler to rewrite this as an extra return value. And there are other clever ways to optimise exceptions. In Java exception speed will depend on your VM but numbers I've seen quoted a lot are: twice as slow, no difference, and slightly faster.

    16. Re:People just doesn't get it by Smallpond · · Score: 1

      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

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

      And why would anyone care? Is there a benchmark somewhere on how many errors per second your program can process? If you unplug the ethernet cable is it important to tell the user that their session is gone in 1 microsecond rather than 10?

    17. Re:People just doesn't get it by ruiner13 · · Score: 2

      You could possibly be looping through an array or reading lines in a data file (such as CSV) and have some elements or lines with errors that you just want to handle and keep processing. Exceptions would be a bad choice here. You assume if one entry is bad, they all must be, which is almost never the case. I code for a company that deals with huge (million+ entry) data sets. Using and dealing with exceptions is to be avoided when possible. If you think 4ms is trivial, I would not trust you to write any of our performance code.

      --

      today is spelling optional day.

    18. Re:People just doesn't get it by Charliemopps · · Score: 1

      You clearly are coding inside a box. Sure, there are certain types of programs where you can predict and handle all errors that arise from user input and the only "Exceptions" would be when ram or hard disk starts failing. Your basic note taking program or a calculator. But there are plenty of situations where input may very well not come from a controllable source. For example, a lot of my code involves API calls and such. And when my code is taking inputs from someone elses code, I can only do so much to prevent them from doing things that are absolutely insane. Or worse, when your code works off a database that 30 other people are writing code for. You never know what someones going to dump into a field. Or when the DB admin is going to change the field type. When you do not have absolute control over your data source, you can never be sure that the data you're getting will resemble anything like what you had planned on. I think this is more representative of what most programmers are dealing with every day.

    19. Re:People just doesn't get it by Charliemopps · · Score: 1

      The point of exception handling is to prevent unwinding the entire stack.

    20. Re:People just doesn't get it by Anonymous Coward · · Score: 0

      Not true: you must use exceptions if you want to see if a serial port is locked or not.

    21. Re:People just doesn't get it by wcrisman · · Score: 2

      You are assuming that the stack trace is generated, which for many anticipated exceptions it is not. For anticipated exceptions, you would simply catch it and adjust. For example, the code is attempting to use a connection to the database to execute a query, but the connection timed out before the query could be transmitted. To handle this error, one would simply need to reconnect and retry and the problem is solved without any fuss. I would rather have an exception here because I'd rather not see every call in the stack between the beginning of the query call and the attempt to use the connection have to return and check an error code.

      That leaves unanticipated exceptions, for which the engineer will likely want the error output to help them track down what happened. In the case of unanticipated exceptions, yes you have a much slower method of logging, but you get a lot of useful information that helps the engineer track down the problem quickly. For example a query to the database is malformed which generates an exception which likely will end the execution of at least that part of the application. Having the exception take 1000x longer to handle in this case is trivial compared to the fact that it happened at all, and well worth the cost for the information about the error that it provides (a stack trace, versus nothing but an error condition).

    22. Re:People just doesn't get it by gbjbaanb · · Score: 4, Insightful

      yes you really do care. Once you've started using exceptions for normal things, then you quickly find your program will be throwing the buggers all the time. In many server applications you'll be getting 3 or 4 exceptions per request (I see this, even in the Microsoft code that you have no control over)

      net result: really slow code, exceptions don't just run slowly, they also screw your CPU caches and other bits that we rely on to get data through the CPU as quickly as it can handle it - a CPU today, if it had to fetch instructions from main RAM every time, would run about as quickly as a old 8bit computer.

      So using an exception to return the fact that you have no network connectivity (a condition you'd usually expect to be either exceptional - when the network goes down - or a non-performance issue - in that the user can't do anything). Using an exception to handle a missing entry in a data collection (eg so you can then take steps to populate it) will kill you. Too bad that I see exceptions used for this kind of behaviour :(

    23. Re:People just doesn't get it by gbjbaanb · · Score: 1

      not really - often the exception contains little of use, except a stack trace and that would show you little in most cases too.

      If you end up throwing an exception with some custom text saying what the problem was - then you could just as easily log that text there and then.

      Exceptions are just a different way of returning the error information - that's all, nothing particularly special about them except you cannot totally ignore them, and they are slow.

    24. Re:People just doesn't get it by angel'o'sphere · · Score: 0

      In the case of the .net runtime, throwing an exception was > 1000x as expensive as using a return value, in processing time.
      Then .Net does something wrong.
      C++ has zero overhead exception handling since decades. Why should that not be possible for .Net as well?

      --
      Cost free eBook I read (by iBook/Kobo/Amazon/ObookO/Gutenberg etc.): "The Green Odyssey" by Philip Jose Farmer.
    25. Re:People just doesn't get it by jez9999 · · Score: 1

      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.

      So why don't we have lightweight exceptions yet? The benefit of handling all the error code at the end of a try/catch block, without much of the regular exception overhead?

    26. Re:People just doesn't get it by Ziggitz · · Score: 1

      Good luck finding any Java or C libraries that handle network traffic that won't occasionally throw an exception from an inherently unreliable service.

      --
      There is no memory shortage. yes I have heard of XFCE. Go away.
    27. Re:People just doesn't get it by Ziggitz · · Score: 3, Insightful

      This. It's not difficult to write good defensive programs that check for nulls before performing operations and can fairly consistently never raise an exception. However, most programs need to handle inputs from other applications that the program cannot guarantee are valid, a lot of complex inputs cannot be verified by simply null checks. Additionally any developer who writes code that touches the internet(i.e. most of us) have to cope with unreliable services, deployment engineers, or worse the lack thereof setting up applications with incorrect configurations, bad inputs and network failures.

      What a try catch block should really be used for, is a conscious decision point to identify where a valid program might meet an error conditions and deal with the implications of that error. Maybe the error is not finding crucial initialization parameters and all you can do is log an error, set a pretty error message for the user and kill the program. Maybe you can flush the current parameters and try again with some defaults. Maybe you can still run but with impaired functionality. Maybe you are a secondary function and it's ok if you fail but you need to let the user know.

      The author's arguments boil down to "try catch blocks make my code look ugly." There is no valid solution to error handling that doesn't involve developers proactively identifying and addressing unreliable operations. Any valid solution that isn't current exception handling is going to look a lot like it because error handling is not some boilerplate task that you can wave a magic wand at and make disappear.

      --
      There is no memory shortage. yes I have heard of XFCE. Go away.
    28. Re:People just doesn't get it by Ziggitz · · Score: 1

      Congrats you're an edge case! Most people recognize that your code should be written to meet the requirements of the system and yeah, if you're writing code that needs to loop over a million tuples of structured data then writing logic from scratch to deal with the error handling cleanly and efficiently is a good idea. If the error is with complex data such as "the file uploaded was not a recognized image format" then you're not really going to find a much less expensive way, both in developer time and computational time than catching the exception from the method that was used to parse the file expected to be an image. While people like you working in such problem domains are greatly appreciated, yours is not the only space.

      --
      There is no memory shortage. yes I have heard of XFCE. Go away.
    29. Re:People just doesn't get it by loufoque · · Score: 1

      You're building critical components with MATLAB?
      Are you crazy?

    30. Re:People just doesn't get it by Anonymous Coward · · Score: 0

      What about the class-not-found (due to lack of memory, file descriptors, ....). Ops is about 'things that should not ever happen' and are 'hard to repeat'.

    31. Re:People just doesn't get it by shutdown+-p+now · · Score: 1

      This all is language-specific. Yes, in Java and C#, exceptions are expensive, but I would argue that it is rather the flaw of the language / VM in question. On the other hand, in Python, exceptions are so cheap that they're used for regular flow control by the language itself.

      Really, an exception is nothing more than an Error monad. There's no reason why they shouldn't be just as cheap, too.

    32. Re:People just doesn't get it by shutdown+-p+now · · Score: 1

      The stack trace, in some form, is generated when exception is thrown, regardless of whether it's caught or not (since, by the time it's caught, the original stack is lost, so there's no way to trace lazily if the guy who caught it suddenly asks for a trace).

    33. Re:People just doesn't get it by shutdown+-p+now · · Score: 4, Informative

      This is plainly false. C++ exception is near-zero-overhead, but only for success scenarios - i.e. when no exception is thrown. Actually throwing an exception is quite expensive in most C++ implementations. Java and .NET are similar - no-exception path is very fast, near-zero-overhead, but throwing is expensive.

      Generally, that's exactly the trade-off you make. You can do exceptions cheap if you basically implement them the same as hand-checked error codes, but then you have the overhead of checking for the error code on every single function call - and those do add up. If you don't want that overhead, then you need some form of stack unwinding, where frames that need to inspect thrown exceptions, or to cleanup during unwinding, can register their handlers (and those that don't need either don't do anything at all - it's literally zero overhead for them). But then the exception throwing code has to walk through those handlers and invoke them, which is more costly then just return ERROR_CODE.

    34. Re:People just doesn't get it by shutdown+-p+now · · Score: 2

      You should never, ever catch a NullPointerException. It indicates a bug in your code, not some external error condition. If it happens, you fix your code.

      I mean, how exactly do you expect to recover from it even if you catch it?

      The same goes for all other exceptions that are actually contract violations - various range- and bound-checks etc.

    35. Re:People just doesn't get it by VortexCortex · · Score: 5, Funny

      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.

      Well, it's simple: Sane defaults. Try again with "localhost". What? "localhost" doesn't have anything listening on port 80? system( "apt-get install LAMP" ); It does now. Oh, Apache failed to install? Spawn a thread that opens a socket and listens on port 80. Can't spawn a thread? Cooperative Multitasking mode enabled (hint: function pointers for main loops). Can't listen on port 80? Virtualize a socket in memory, etc.

      "Error Handling" Pffffbt, how about a Solution Handler? Hint: Don't focus on the Problem, focus on the Solution. You'd know this already if you posted in HTML mode... It's doesn't throw errors when displaying my malformed post. Quote it and see

    36. Re:People just doesn't get it by VortexCortex · · Score: 3, Interesting

      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.

      Well, it's simple: Sane defaults. Try again with "localhost". What? "localhost" doesn't have anything listening on port 80? system( "apt-get install LAMP" ); It does now. Oh, Apache failed to install? Spawn a thread that opens a socket and listens on port 80. Can't spawn a thread? Cooperative Multitasking mode enabled (hint: function pointers for main loops). Can't listen on port 80? Virtualize a socket in memory, etc.

      "Error Handling" Pffffbt, how about a Solution Handler? Hint: Don't focus on the Problem, focus on the Solution. You'd know this already if you posted in HTML mode... It's doesn't throw errors when displaying my malformed post. Quote it and see

    37. Re:People just doesn't get it by VortexCortex · · Score: 1, Funny

      See? Backup post, just in case you missed the 1st one... Defensive Datagramming.

    38. Re:People just doesn't get it by BitZtream · · Score: 1

      Really ... stack unwinding is free then I guess? Not sure what world you're actually from but exceptions have to unwind the stack since you can't unwind it later since it won't be the same or you have to save it. Neither of these are free or even cheap. If you're not providing a stack trace then you're just calling something exception handling when it isn't.

      --
      Persistent Volume manager for Kubernetes - https://github.com/dwimsey/openshift-pvmanager
    39. Re:People just doesn't get it by nabsltd · · Score: 1

      Exceptions should NOT be used for 'normal' errors. They should be used for events that are, well, exceptional.

      What is the basis of this strange belief?

      The standard case is trying to open a file that doesn't exist. This isn't an "exception", or even really an error. Many times, it's a test to see if the file exists to allow an overwrite warning. Yes, there are ways to check this without the "error" (like iterating through all the file names returned in the directory list to see if the file is there), but these have their own issues (what if the directory itself doesn't exist?), and can also be slow.

      There are many languages/libraries that force you to handle a "file doesn't exist" using the try/catch syntax, while others place any result in the return value. Since you really need to examine that return value anyway, handling an exception is a lot of extra work for no good reason.

      Truly exceptional things are like running of disk space, having the disk removed/fail/whatever. In other words, if the problem has to be solved outside the program that is catching the exception, then that is a good use of an exception. If the program can resolve the issue, then an exception is usually overkill.

    40. Re:People just doesn't get it by glitch23 · · Score: 1

      What if I wasn't trying to connect to localhost? Why then would I would to have LAMP installed on my machine? Installing software is not a sane default. It's a security risk because it's being installed without testing.

      --
      this nation, under God, shall have a new birth of freedom. -- Lincoln, Gettysburg Address
    41. Re:People just doesn't get it by shutdown+-p+now · · Score: 1

      Every time you return from a function, you unwind the stack by one frame. If you add a monad such that returning an error would (by default) cause the caller to also immediately return it, you get exceptions with performance of return codes (of course, it also means that you have extra checks on success ).

    42. Re:People just doesn't get it by ios+and+web+coder · · Score: 1

      As someone who uses a modular development approach, I can tell you that throwing exceptions across library links is all kinds of fun.

      --

      "For every complex problem there is an answer that is clear, simple, and wrong."

      -H. L. Mencken

    43. Re:People just doesn't get it by Anonymous Coward · · Score: 0

      I wouldn't trust you to write our mundane scripts either. our mundane scripts.

      You also could be coding CSS, in which case exceptions make no sense.

    44. Re:People just doesn't get it by Horshu · · Score: 1

      A well-written program is still at the mercy of its runtime's own exceptions. OutOfMemoryException is another one that can bite you through little-to-no fault of your own, but you still want to handle it in some fashion (assuming "well-written" includes "is graceful", which I believe in)

    45. Re:People just doesn't get it by Anonymous Coward · · Score: 0

      You return to the top level handlers and hope the next user-initiated action does something else.

    46. Re:People just doesn't get it by Brian+Feldman · · Score: 1

      Are you serious?

      unsigned int line = 1;
      while (!done) {
      try {
      while (!done)
      dostuff(i++);
      } catch (excepion &whatever) {
      logstuff();
      }

      --
      Brian Fundakowski Feldman
    47. Re:People just doesn't get it by Darinbob · · Score: 1

      Well, two main uses for exceptions, error handling but also non-error exceptions. Ie, the end of a file is not an error but an exception can be used to handle it as an exceptional condition. Ie, you use exceptions to implement a non-traditional flow control. Somewhere along the way people started treating exceptions as only a form of error handling only. I've seen some big fans of exceptions just say something stupid like "I can just throw an exception and catch it at the top level, it's so easy"; Using exceptions as a catch-all at the top level only completely misses what they're all about.

      I don't use them much. In embedded systems too expensive. But both exceptions and normal error handling from return codes both suffer from the same faulst. First you need to have a consistent error handling design but almost everyone has something ad-hoc instead. Second you need to know what your goals are with error handling, whereas too many people just want to hand the error off to someone else to deal with at a higher level.

    48. Re:People just doesn't get it by Darinbob · · Score: 1

      First, exceptions are not synonyms for errors. They may be used in cases where you aren't handling an error. A floating point exception for instance where you just want to fall back to a slightly different mathematical model, or a resource is in use and you just need to schedule a retry.

      The other problem is that in some implementations, exceptions in use anywhere will cause overhead in all function calls and returns, and in different implementations it will consume a lot more program space.

    49. Re:People just doesn't get it by shutdown+-p+now · · Score: 1

      At this point, your program is basically in an indeterminate state. You have a null pointer somewhere that shouldn't be there. Your preconditions no longer hold (and you don't even know which ones), so your post-conditions cannot be guaranteed. If it is a document-centric app, and the user tries to save, chances are you'll crash mid-save and corrupt the data.

      It's much better to just crash right away and not pretend that your program has recovered when it did not and cannot.

    50. Re:People just doesn't get it by Anonymous Coward · · Score: 0

      I doubt anyone really thinks the happy path should be handled with exceptions.

      You'd be surprised. There are examples in almost every major public API where the designers got those things wrong. In Java, for instance, ResourceBundle.getString() throws a MissingResourceException if it can't find a value corresponding to the given key. However ResourceBundle also implements an inheritance mechanism whereby it first checks the file for the language variant, then the language and, finally, the default. At each stage, if it can't find the resource, it will throw the exception. This becomes a problem when you've got a webpage or other UI that has a ton of localized text. I've written pages that contained > 500 localized strings. We were forced to eschew the inheritance and put all values in the most specific bundles because the fallback mechanism was too slow (at the time, capturing the stack trace would take ~15ms, so if even 10% of string lookups threw an exception, it would add almost a second to the total page load time.)

    51. Re:People just doesn't get it by Jonner · · Score: 1

      Yeah, if the network connection resets, the user probably bumped the cable. File not Found? User error. Such lusers don't deserve to use software.

    52. Re:People just doesn't get it by joe_frisch · · Score: 2

      Its dramatically saved development time - the physicists can write code that does what they need, rather than specifying in enough detail for the software department. This reduced our development times for new control functions from months to days. We originally planned to gradually replace the Matlab with lower level code, but Matlab (operated in text mode without GUIs) has been very reliable, and the machine operates with very high uptime. The code is also readable by the operations staff who can modify / improve it if needed. The Matlab code interacts with an EPICS distributed control system.

      Code that needs to have fast response, or to be realtime is not written in matlab. Hardware protection code is generally in PLC type logic and safety systems use certified safety PLC like controllers ( don't know much about this).

      The LCLS (our X-ray laser) operates with something like 95% of scheduled uptime (~9 months a year, 24-hours a day, for the last few years), and that includes probably dozen constantly running Matlab scripts and feedbacks,and hundreds of real time processor crates, not to mention a kilometer of high power RF systems (many of them 50 yeras old), 2 kilometers of vacuum system, undulators, x-ray controls and diagnostics, and the experimental end stations. Its by a significant margin the brightest (photons/%bw/mm^2/mr^2) X-ray source every built, and substantially exceeds all of its design parameters.

      So no, we're not crazy - (just damn good. ).

    53. Re:People just doesn't get it by Anonymous Coward · · Score: 0

      You should compare the cost of not throwing an exception to the cost of returning and checking an "OK" return code every time. C++ exceptions can easily be less than zero overhead once you do this, even when there's per-function overhead to set up the EH stack, if each function calls more than one function on average (more precisely, more than one function that could return an error).

      Similarly, you don't compare throw overhead to the overhead of returning a number. You compare it to the overhead of returning a number, checking it, cleaning up, returning (including destructors), all the way up the callstack to the ultimate catcher. It is likely that C++ implementations can match ad-hoc code for this, or even beat it in some cases.

      Once you compare apples to apples, C++ EH can easily achieve zero overhead or better. OTOH, I'm not convinced that many C++ compilers achieve this in practice. YMMV. Also, for numerical code which can't cause errors, EH quickly becomes high overhead, as you're no longer comparing to the return-value-and-check case, but only to the return-void-and-do-nothing case.

    54. Re:People just doesn't get it by DerPflanz · · Score: 1

      Or it indicates a bug in someone else's code.

      For example if you build a piece of software that supports thirdparty plugins. Run it, and catch *everything*. When something is caught, disable the plugin, do not crash your application.

      --
      -- The Internet is a too slow way of doing things, you'd never do without it.
    55. Re:People just doesn't get it by Mr+Z · · Score: 2

      I happen to agree that exceptions should be left to exceptional events—something entirely outside the scope of the algorithm—and not something that seems well within the purview of the task at hand. For example, when validating data sets, which is something it sounds like your code does, detecting and handling an invalid datum sounds like the code's raison d'etre. An exception here would be ridiculous.

      Another example might be a parser of some sort (for example, in the compiler itself). If it detects an error in the input, that's not an exception. It's a well defined state transition in the parser. Exception handling is not error handling in the general sense. It's only for errors for which the right course of action isn't even knowable except perhaps a couple levels up, and is unlikely to happen much in practice.

      For example, if you have data structures that automatically resize to fit whatever your program needs, and you hit an OOM situation, what then? There's likely to be no good way forward. You want to unwind far enough that you can leave things in as consistent a state as possible, and otherwise probably just crash with a hopefully-useful error message. Depending on the nature of the program, "crash" could mean widely different things here. If it's a command-line program or a restartable system service, "error message and exit" is probably the best thing. If it's a GUI environment, if you can close the document or whatever triggered the blow-up and free the resources, that's probably a better idea.

      Drifting topics here...

      I'm fortunate that most of the programming I have to do is best served by Perl's "die", "croak" and "carp" functions. Usually, whatever error my scripts encounter is best handled outside the script, because the error is either bad input, or a bug in the code. Neither of those can really be handled within the script itself. So, we pop out an error message and a stack trace and say "here, you fix it."

      Before you say "you're putting an undue burden on your users," most of this code is developed for ourselves to use. I work with a chip design team, and we manufacture and eat our own dog food. Just as the scaffolding around a skyscraper-under-construction doesn't need to be ADA compliant ("What, no wheelchair ramp up here?"), our scripts for internal use don't need quite as much polish as something we'd ship as a product. :-)

      That said, I do also work on code that I intend other less-technical people to use. It takes considerably more work to make that code bulletproof and friendly. I'd say more work goes into polish than into the core algorithms.

    56. Re:People just doesn't get it by Mr+Z · · Score: 1

      yes you really do care. Once you've started using exceptions for normal things, then you quickly find your program will be throwing the buggers all the time. In many server applications you'll be getting 3 or 4 exceptions per request (I see this, even in the Microsoft code that you have no control over)

      Wow, that sounds like the programming equivalent of bumper bowling.

    57. Re:People just doesn't get it by Anonymous Coward · · Score: 0

      The examples you provide are reasonable, but you ignore the specific one that pla used.

      If the program is working with some device over a network, and suddenly the network is gone (stupid dog pulling out all those wires!), trying localhost isn't going to make the situation any better.

      Programs need to be able to recover gracefully in the presence of exceptional behavior.

    58. Re:People just doesn't get it by loufoque · · Score: 1

      The limit between good and crazy is sometimes very thin...

    59. Re:People just doesn't get it by smellotron · · Score: 1

      The standard case is trying to open a file that doesn't exist. This isn't an "exception", or even really an error. Many times, it's a test to see if the file exists to allow an overwrite warning.

      Truly exceptional things are like running of disk space, having the disk removed/fail/whatever. In other words, if the problem has to be solved outside the program that is catching the exception, then that is a good use of an exception.

      Well now you end up with a file API which returns error enumerations in one situation (open or fopen) and throws exceptions in another situation (read,write or fflush,fclose). That will definitely throw developers for a loop. I'd rather have the API pick one or the other and stick with it. I'm actually rather fond of POSIX C's approach to this (int fd and FILE * with thread-local errno) because it provides minimal-overhead building blocks for application-specific file abstractions. It requires an encapsulation layer for C++ applications, but it means I can cater the encapsulation layer's behavior to my exact needs. Configuration files, cache files, log files, temporary work files, saved-state files all have very different needs and should respond to faulty scenarios differently.

    60. Re:People just doesn't get it by Anonymous Coward · · Score: 0

      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
      ...

      Looks like really bad code to me. If the file doesn't exists, file.isFile() should return false, meaning your first condition is true, so you never get to the "if(!file.exists())" check...

      I do write code this way.

      Bad programmer! Go stand in the corner.

      It really sucks,

      Yes.

      but we know exactly what and when something went wrong as soon as it goes wrong.

      You know nothing!

      Trying to unit test this sort of code is a nightmare. Exceptions make you double all your error checking code branches.

      Trying to unit test your code is a nightmare, partly because your logic is faulty.

    61. Re:People just doesn't get it by Anonymous Coward · · Score: 0

      WTF do you mean "sane defaults"?
      I'm building an enterprise system where a system MUST contact an external compute cluster, and your suggestion is what - use localhost instead?

      Genius

    62. Re:People just doesn't get it by shutdown+-p+now · · Score: 1

      By zero overhead, I mean just that - zero overhead relative to no error checking at all. Returning error codes and checking for them is, obviously, not zero overhead.

    63. Re:People just doesn't get it by shutdown+-p+now · · Score: 1

      For plugins and such, it's better to use more stringent isolation, such as they can crash all they want without bringing the process down. In .NET, for example, you'd run them in their own appdomains.

    64. Re:People just doesn't get it by Anonymous Coward · · Score: 0

      Even if there's no exception you have to carry all the information for stack unwinding with you. You can imagine the cost of that..

    65. Re:People just doesn't get it by shutdown+-p+now · · Score: 2

      You don't "carry it around", you just place your unwind handlers where they can be found if needed when exception is to be thrown. Which is done once when the frame is entered. And which you don't have to do if you have nothing to clean up and just want to pass the exception throw.

      But, yes, that's why I wrote "near-zero".

    66. Re:People just doesn't get it by MikeBabcock · · Score: 1

      I suppose you've never tried to open a file before.

      In a multitasking multi-threaded multi-user environment, even doing a stat() check on a file before trying to open it doesn't guarantee its still there by the time the next line is executed.

      --
      - Michael T. Babcock (Yes, I blog)
    67. Re:People just doesn't get it by MikeBabcock · · Score: 1

      Edge case? Looping over millions of records is pretty common, from data processing to log files to file sorting ...

      Even seemingly simple situations like your file browser trying to show you thumbnails of each picture in a directory can be riddled with exceptions which would slow down the whole process dramatically.

      --
      - Michael T. Babcock (Yes, I blog)
    68. Re:People just doesn't get it by MikeBabcock · · Score: 1

      Just encapsulate that file in its own class and realize how crazy OO can become.


      try {
              MyConfiguration config = new MyConfigFile().readConfig();
              config.read();
      } catch { /* we don't have a config file, lets die. */
      }

      Then in your MyConfigFile class, you can check if the file exists, if not, create one, enter default config values, etc. and push all that horrible file handling garbage into its own neat package ...

      --
      - Michael T. Babcock (Yes, I blog)
    69. Re:People just doesn't get it by Brandybuck · · Score: 1

      That's not an error, that's the normal state of being. Sheesh.

      --
      Don't blame me, I didn't vote for either of them!
    70. Re:People just doesn't get it by Anonymous Coward · · Score: 0

      Thanks for the informative post about the operations at the SLAC. Sounds like you have a great system running there!

  7. Exceptions in C++ by Anonymous Coward · · Score: 4, Insightful

    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.

    1. Re:Exceptions in C++ by msclrhd · · Score: 1

      Exceptions can make code harder to maintain. Specifically:

      1. you have to be careful not to throw across COM calls, Windows message handlers, thread handlers, etc. otherwise you are going to get hard to diagnose crashes;

      2. you lose context -- where did that "file not found" error originate from;

      3. generic catch blocks make it difficult to understand the control flow, and if you localise the try ... catch blocks you end up with verbose code.

      I am not saying that error codes are the solution. I think both are equally bad for different reasons. I do not have a good replacement either.

      At the moment, I like the way Java tells you what exceptions will be propagated -- this helps you add code to deal with the exception at the place where it is called. I also like the C++ RAII model -- it is better than try ... finally or using statements, as it reduces the amount of code I need to write while maintaining safety.

    2. Re:Exceptions in C++ by loufoque · · Score: 1

      The most important primitive for good exception-safe code is an atomic swap.
      Microsoft Windows doesn't have an atomic swap for files AFAIK, which is a very big problem. No wonder video games end up with corrupt save files...

    3. Re:Exceptions in C++ by devent · · Score: 2

      You have got to be kidding me. C++ have the worst exception implementation by far.

      First, you can throw anything. String, int, object, etc. That means that you can't use a catch-all and do anything useful.
      Second, you are losing the stack trace, which means debugging is pain.
      Third, you can't throw an exception in the dtor, which means you can't use RAII. What if an exception is occurring while you close a resource? For example, disk is full; the socket is gone; memory full; disk is broken; the user removed the USB stick, etc.

      --
      http://www.mueller-public.de - My site http://www.anr-institute.com/ - Advanced Natural Research Institute
    4. Re:Exceptions in C++ by Anonymous Coward · · Score: 0

      "You can't use a catch-all and do anything useful."

      This is always true, regardless of exception types...

    5. Re:Exceptions in C++ by serviscope_minor · · Score: 1

      First, you can throw anything. String, int, object, etc. That means that you can't use a catch-all and do anything useful.

      How's that different from catching "throwable"? An Any type by definition has no semantics and conveys no useful information.

      Second, you are losing the stack trace, which means debugging is pain.

      What stack trace? If you're running optimized code, then the optimizer makes such a mess of things that a stack trace is often not meaningful since there is no reasonable mapping between machine coe and program lines.

      If you're debugging, well, then comment out the catch statements and get the stack trace.

      Third, you can't throw an exception in the dtor

      You can, you just have to take care. Not the best feature of C++, admittedly.

      , which means you can't use RAII.

      Or you could just make sure you catch all exceptions.

      For example, disk is full;

      The best workaround is to issue an explicit close if you want to catch those sorts of errors. You can even make a wrapper for it. Again, it's not an ideal feature (and proposals are in the works) but it's hardly a showstopper.

      --
      SJW n. One who posts facts.
    6. Re:Exceptions in C++ by BitZtream · · Score: 1

      rename/move is an atomic operation on Windows just like any POSIX OS as long as its done on the same file system.

      --
      Persistent Volume manager for Kubernetes - https://github.com/dwimsey/openshift-pvmanager
    7. Re:Exceptions in C++ by loufoque · · Score: 1

      Note that I didn't say renaming files, I said swapping files.
      On POSIX, the function called "rename" allows to swap files. On Windows, it doesn't.

    8. Re:Exceptions in C++ by devent · · Score: 1

      Throwable (in Java) is a well defined type with useful methods. Like get the stack trace.
      Funny how other languages can optimize all the like but don't need workarounds like "comment out the catch statements and get the stack trace".

      That is funny because AC put C++ exceptions as the best thing ever and gets +5 insightful.

      http://stackoverflow.com/questions/130117/throwing-exceptions-out-of-a-destructor

      Throwing an exception out of a destructor is dangerous.
      If another exception is already propagating the application will terminate.

      http://home.ustc.edu.cn/~zixin/More%20Effective%20C++/MEC/MI11_FR.HTM

      C++ calls the terminate function. That function does just what its name suggests: it terminates execution of your program. Furthermore, it terminates it immediately; not even local objects are destroyed.

      http://home.ustc.edu.cn/~zixin/More%20Effective%20C++/MAGAZINE/SU_DIR.HTM#dingp134

      The standard says you get undefined behavior if a T destructor throws anywhere in this code, which means that any code that allocates or deallocates an array of objects whose destructors could throw can result in undefined behavior. This may raise some eyebrows, so let's see why this is so:

      The best workaround is to issue an explicit close if you want to catch those sorts of errors. You can even make a wrapper for it

      And thus makes RAII pretty useless with resources. Any external resource (not inside the application like an object), can throw an exception/error while closing it.

      --
      http://www.mueller-public.de - My site http://www.anr-institute.com/ - Advanced Natural Research Institute
    9. Re:Exceptions in C++ by hh10k · · Score: 1

      I agree, I love the way RAII works with exceptions in C++. It's just a shame most people still learn C++ as "C with classes".

      C#'s IDisposable and using statement are probably the best you're going to get in a nondeterministic garbage collected language though, so I wouldn't complain about that.

      Java can go die in a fire.

    10. Re:Exceptions in C++ by SpinyNorman · · Score: 1

      2. you lose context -- where did that "file not found" error originate from

      Well, the main solution to that is of course to choose the appropriate scope of your try-catch blocks, but on occasion I've also found use for something as simple as:

      string where;
      try {
          where = "doing A";
          A;
          where = "doing B";
          B; // etc
      } catch (...) { // print where
      }

    11. Re:Exceptions in C++ by Anonymous Coward · · Score: 0

      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.

      Java 7 has try-with-resources:

      http://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html

      Other than resources, resources, destructors are far less useful in Java than in C++ due to using the garbage collector for memory allocation.

    12. Re:Exceptions in C++ by smellotron · · Score: 1

      1. you have to be careful not to throw across COM calls, Windows message handlers, thread handlers, etc. otherwise you are going to get hard to diagnose crashes;

      On the Linux side, there are also restrictions for throwing/catching across shared object (library or program) boundaries. AFAIK both shared objects must reference the same RTTI "database", which means for GCC users that both must be dynamically linked with libgcc_s. This rules out purely-static executables. While most developers don't care about this limitation, there is a very small set of developers for whom this makes a significant difference.

    13. Re:Exceptions in C++ by smellotron · · Score: 1

      First, you can throw anything. String, int, object, etc. That means that you can't use a catch-all and do anything useful.

      Yeah, it's a bit silly at first, but it's not a surprise when you consider that std::exception is not a language construct, and is instead a Very Important language idiom. If a peer developer programs "outside of the box" in this regard, they are deserving of a hefty smack.

      Second, you are losing the stack trace, which means debugging is pain.

      I have to agree with you on this one. I wish __cxa_throw would snapshot the backtrace by default. Since that is horribly implementation-specific, it would be sufficient if a standard API was created which intercepted exception throwing, so I could call backtrace on my own.

      Third, you can't throw an exception in the dtor, which means you can't use RAII. What if an exception is occurring while you close a resource? For example, disk is full; the socket is gone; memory full; disk is broken; the user removed the USB stick, etc.

      This is absurd. If you want to provide visibility to errors when closing a resource, provide a close() member or similar which can throw. Destructors exist to release resources while unwinding the stack. Since you don't know the state of the program (other than "this lexical scope is going away"), there's no reason to report errors. Again, enforcing no-throw destructors is a Very Important language idiom. Do not break it.

    14. Re:Exceptions in C++ by smellotron · · Score: 1

      Any external resource (not inside the application like an object), can throw an exception/error while closing it.

      You are expected to enforce a no-throw destructor regardless of the work that happens within it. Yes, you are expected to suppress errors if it is possible for resource-closing to throw. It sounds weird I know, but it works just fine. If the API users care about failure, they will call close() first.

    15. Re:Exceptions in C++ by devent · · Score: 1

      Yes "it works just fine". How about this example:

      void write_important_data() {
          file = open_file "File"
          file.write "Some important data"
      // the dtor calls close() which will flush the data so it's written to the medium
      // before the method finish, the user unplugs the USB stick
      // now the close() method in the dtor will normally throw a I/O exception
      // and thus the application can warn the user that the data is not written to the USB stick
      // because he/she unplugged it
      // but since dtors can't throw anything, the exception is "swallowed"

      }

      The user assumes that the data is written, because no error was shown. The data was an important presentation for the next management meeting. The user opens the sticks and to his surprise the USB stick is empty. RIIA for the win.

      Of course in a real application the programmer would use the close() method and catch the I/O exception to show an error dialog to the user. But since every C++ developer is so fond about RIIA and dtors in C++ I just show how it could be.

      I personally find dtors pretty useless. They are only useful if you manage memory allocation. For example, you create in the ctor an array on the heap and now you need to de-allocate the array again. But that is not "resource management" it's "memory management". So if you could rename it to MIIA I would find it just fine.

      But since I long ego realized that memory management is best done by the GC I find dtor are just useless.

      --
      http://www.mueller-public.de - My site http://www.anr-institute.com/ - Advanced Natural Research Institute
    16. Re:Exceptions in C++ by smellotron · · Score: 1

      Yes, your example is a good demonstration of how not to use destructors and RAII. The same "disappearing filesystem" problem holds true for the C API: many people don't think about checking the return code of fclose, but it can fail with exactly the same errors as fflush if there is still any data buffered. A seasoned C++ developer will understand that because a destructor must be fail-proof, operations with mandatory side-effects (e.g. I/O) should not be relied upon within them.

      Personally, I find destructors quite useful for a number of tasks:

      • Closing input files
      • Closing socket file descriptors (note: for a TCP connection, I would still call shutdown() first... I have been burned by file descriptors cloned on a fork before, and close() only decrements the refcount whereas shutdown() actually sends a FIN)
      • Decrementing an external refcount
      • Releasing a held mutex
      • Releasing an advisory lock on a file

      I can't blame you if you haven't been exposed to these tasks, as they are heavily dependent on the type of application being developed. But maybe this will help you to see why we do use RAII and not MAII.

    17. Re:Exceptions in C++ by devent · · Score: 1

      I don't think you understand me at all.
      How can you make a dtor "fail-proof" if you are using dtors for resource management? Resources are: files, sockets, locks, printers, scanners, cameras, and memory. But only memory management can you make "fail-proof", because the delete statement in C++ is guaranteed to success. The term "resource" applies to any kind of resource, including "memory". But only memory can be managed in a dtor, because delete() do not throw.

      I'm developing all kinds of applications in Java, including threading, sockets and files. And I'm really do not miss dtors or RIIA. Also I'm glad for Java's style of exceptions. I have used other languages before without checked exceptions and I'm glad we have them in Java. It's really a paid to search the documentation from top to bottom to get what kind of exceptions a method can throw.

      Checked exceptions are like static typing: you want your compiler to help you catch errors fast. Checked exceptions are exceptions that I can catch and react to. They are "recoverable errors". For example I can recover that a file was not found, or I/O error: I can ask the user to specify the correct file or I can use defaults. Not recoverable errors are (in Java) runtime-Errors/Exceptions: NullPointerException, etc.

      --
      http://www.mueller-public.de - My site http://www.anr-institute.com/ - Advanced Natural Research Institute
    18. Re:Exceptions in C++ by alexo · · Score: 1

      C++ has the problem that exceptions cannot be chained.
      Therefore dtors are not allowed to throw.
      Therefore, doing non-trivial work in dtors becomes a pain in the posterior.
      Which limits the usability of dtors.

    19. Re:Exceptions in C++ by Anonymous Coward · · Score: 0

      Can you throw exceptions in Java finalizers?

  8. On Error Resume next by xaxa · · Score: 4, Informative

    Visual Basic had:
    On Error Resume Next

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

    The documentation shows a couple of valid uses for it.

    1. Re: On Error Resume next by circletimessquare · · Score: 1

      I typed it last week at work

      VBScript to archive files accumulating in a folder, run on a Windows scheduled task

      in life you just gotta get something done be damned theoretical perfection. and most of the time you dealing with unimportant stuff not nuclear submarines

      --
      intellectual property law is philosophically incoherent. it is your moral duty to ignore it or sabotage it
    2. Re: On Error Resume next by xaxa · · Score: 5, Informative

      (You probably know all this, but it might be interesting to someone. One of the sysadmins at work could do with reading it...)

      I practically never write scripts for Windows machines, hence never having a genuine use for that VB feature, but on Linux (etc) there's a close-enough equivalent for getting things done; and for shell scripts the default is to continue in case of error. The -e flag to the interpreter prevents this.

      #!/bin/sh
      cd /put/archives/here
      tar cjvf archive-$(date +%Y%m%d).tar.bz2 /files/to/archive/*
      rm -f /files/to/archive/*
      echo "files archived in archive-$(date +%Y%m%d).tar.bz2"

      The cd failing (network down? Disc had errors and wasn't mounted? someone moved the directory?) and the tar failing (filesystem suddenly read-only?) won't stop the rm happening, but "#!/bin/sh -e" would.

      (Alternatively, tar has a --remove-files option, which would prevent removing a file created since tar was executed, but you could still end up with the archive being put in the wrong place.)

      You can let a command fail by using ||, for example:

      #!/bin/sh -e
      cd /put/archives/here
      tar cvf archive-$(date +%Y%m%d).tar /files/to/archive/* --remove-files
      xz --best archive-$(date +%Y%m%d).tar || echo "Compression failed"

    3. Re:On Error Resume next by Anonymous Coward · · Score: 0

      I did this last week in Autocad 2012 (A VBA program opening Excel files, and testing if a sheet in it exists)
      You can then look at the results to see if it worked, and then restore normal error handling (using on error goto 0), without the interpreter stopping the program.
      Programming on Windows is.... adventures. Everything is mind-numbing inconsistent, unpredictable and therefore undocumented.

    4. Re:On Error Resume next by ArcadeNut · · Score: 1

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

      Are you 14 or 41 now? It's all relative.

      VB has
      On Error Goto <label>|<line number>
      On Error Goto 0
      On Error Goto -1
      On Error Resume Next

      All of which I'm happy to never see or use again. Ever.

      --
      Visit the Arcade Restoration Workshop @ http://www.arcaderestoration.com
    5. Re: On Error Resume next by Anonymous Coward · · Score: 0

      Just my $.03, it's better to use 'set -e'. Just in case someone invokes 'sh yourscript.sh'.

    6. Re: On Error Resume next by MobyDisk · · Score: 1

      I found the only other person on the planet who puts error handling into scripts. Thank you.

      And for anyone who reads this: yes, there is also error handling in Windows batch files too! It's painful and ugly, but possible.

    7. Re: On Error Resume next by Anonymous Coward · · Score: 0

      #!/bin/sh
      cd /put/archives/here
      tar cjvf archive-$(date +%Y%m%d).tar.bz2 /files/to/archive/*
      rm -f /files/to/archive/*
      echo "files archived in archive-$(date +%Y%m%d).tar.bz2"

      If your backup script is started at 23:59 and tar takes more than a minute to finish, your script is going to lie to the user.
      Fix: Run date once and storing the output (or better, the name of the archive) in a variable. Then use the variable in the tar and echo line.

      Doing so would also make the script easier to maintain as you only have to change the code in one place, if you want to switch to just "$(date +%F).tar.bz2" (as the "archive-" part is a bit redundant) for the archive-name.

    8. Re: On Error Resume next by Anonymous Coward · · Score: 0

      You sound like you've been programming as long as I have :-).

      And really, if "rm -f" (or the dreaded "rm -rf") ever occurs in a shell script, you'd have to be insane to not do massive error checking before it. I once wrote a similar shell script where I actually did a reality check of the size of the output tar file vs the input and failed out if it seemed unreasonable.

      I'd also mv the files that were allegedly archived to a backup spot so they'd still be there. Only on the next run would I delete the files to make room for the new backup. So they'd always exist on the original drive and the backup, at least for a day.

    9. Re:On Error Resume next by Anonymous Coward · · Score: 0

      Which led to the following interesting support call ...

      User: it just crashed!
      Me: Ah, ok. And what was the error message?
      User: No Resumé ...
      Me: err.....

    10. Re: On Error Resume next by MikeBabcock · · Score: 1

      Nearly all my BASH scripts are long sequences of &&


      cd $LOCATION \
          && tar -cvf $TARFILE $PATTERN \
          && xz $TARFILE \
          && scp "${TARFILE}.xz" remotehost: \
          && exit 0
      echo "Error"

      --
      - Michael T. Babcock (Yes, I blog)
  9. setjmp/longjmp by Anonymous Coward · · Score: 0

    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.

  10. Exceptions by vargad · · Score: 3, Insightful

    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.

    1. Re:Exceptions by Hentes · · Score: 1

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

    2. Re:Exceptions by Anonymous Coward · · Score: 0

      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.

    3. Re:Exceptions by Anonymous Coward · · Score: 0

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

    4. Re:Exceptions by Anonymous+Brave+Guy · · Score: 4, Insightful

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

      Why?

      Whether I'm aborting due to an error or exiting early from an intricate recursive graph processing algorithm, I'm still only doing it once.

      On the other hand, adding extra conditions on every pass around a nested loop to check whether a flag is set to cause an early exit creates code you're going to run lots of times (but only actually helps once).

      And in any case, for reasons I explained in my first post to this subthread, exceptions can actually be faster than relying on things like flags and error codes in both exceptional and non-exceptional code paths, obviously depending on your language's implementation strategy.

      --
      If you disagree, post your argument. (-1, Overrated) isn't your personal censorship tool for views you don't like.
    5. Re:Exceptions by Darinbob · · Score: 1

      Exception handling in quite a lot of implementations involves overhead in every function entry and exit. In other implementations it can have a lot of program space overhead instead; ie, no function call/return overhead but very expensive to call the exception itself which encourages people to really only use it for errors and fatal conditions.

    6. Re:Exceptions by Anonymous+Brave+Guy · · Score: 1

      Exception handling in quite a lot of implementations involves overhead in every function entry and exit.

      Really? If that's true, then either those implementations are decades behind the state of the art or they are doing something more than merely propagating a different kind of result in the way we've been talking about for most of this Slashdot discussion.

      --
      If you disagree, post your argument. (-1, Overrated) isn't your personal censorship tool for views you don't like.
    7. Re:Exceptions by PurplePhase · · Score: 1

      Like!

      I've wondered why more languages don't include mechanisms (like Java's Exception handling) while implementing them in more CPU-friendly terms. Perhaps it would have a complex return object which already captured the stack trace when it ... well, except the interrupt-or-equivalent is still needed... hmm.. Or maybe that's what got us Spring. Ick.

      Nevermind.

      8-PP

    8. Re:Exceptions by MobyDisk · · Score: 1

      No, he is right - just not in the degree. Most of the overhead is in the throw/catch, but there is some overhead in each function to setup the stack cleanup routine. One of the nice benefits of AMD's x64 is that it minimizes that down to like 1 CPU instruction. But it is there regardless of language or CPU. Although in practicality, it is probably comparable to the C-style error handling overhead that Darinbob mentioned. People forget that error handling in C is not free. If the developer checked the return of every malloc, every API call, and every C standard library call the code would be no faster than the rather minimal exception handling overhead.

    9. Re:Exceptions by Anonymous+Brave+Guy · · Score: 1

      Although in practicality, it is probably comparable to the C-style error handling overhead that Darinbob mentioned. People forget that error handling in C is not free.

      Exactly. The point isn't whether using an exception magically requires no code, it's whether whatever the exception requires is different to what you'd have to do anyway if you manually implemented error codes and clean-up logic to get the same behaviour.

      --
      If you disagree, post your argument. (-1, Overrated) isn't your personal censorship tool for views you don't like.
  11. Third option? by Anonymous Coward · · Score: 0

    In Soviet Russia, third option errs on you!

  12. First problem is considering it clutter by erroneus · · Score: 5, Insightful

    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. Re:First problem is considering it clutter by TheGratefulNet · · Score: 1

      yeah, file this under 'life is hard and so is programming'. you make calls, you check errors and do stuff based on what you can do at that point in the code. if a queue is full, I'll retry it later, etc.

      ob disc: been programming in C (and its variants) for a few decades, now, and it pretty much is all the tool I need to get any software problem done. you really don't need a lot of fanciness to get most jobs done, truth be told.

      --

      --
      "It is now safe to switch off your computer."
    2. Re:First problem is considering it clutter by Cutterman · · Score: 1

      Agree. Most of the code I've written for handling lab instruments is about 30% doing stuff and 70% input validation, sanitizing, sanity checking and error handling. Can't leave it to the OS. Bloody tedious but you get used to it and a lot of it is boilerplate that once written just transfers to another rountine or app. Just habit. Assume things will break or that the user is demented. Mac

    3. Re:First problem is considering it clutter by sjames · · Score: 1

      The analogy is a bit off. Checking return values is the strategy of covering every open surface in the house in trashcans.

    4. Re:First problem is considering it clutter by Ritchie70 · · Score: 1

      Exactly, but it's hard to get people to actually believe that this is how a professional's work should be.

      I have worked on one interactive system that was originally designed in the mid 1980's by people with a mainframe background. If anything goes wrong in one of its programs (except for validating user input) the program exits immediately and a cryptic error message is displayed.

      The system is still in use and still in development, and it's very hard to get the development team to break away from that mindset and actually give useful error messages to the user, preferably without dumping all of the user's work in the bit bucket.

      --
      The preferred solution is to not have a problem.
    5. Re:First problem is considering it clutter by Anonymous Coward · · Score: 1

      not really, its more like having several trash cans for different items, not every return value is trash

    6. Re:First problem is considering it clutter by Anonymous Coward · · Score: 0

      I strongly agree.

      The modern fetish in software development seems to be talking about "clean" code and what that usually means is "terse" code. Note that I don't mean "concise" code which is to the point and does only what a given component logically needs to do but "terse" in the sense that they want to use as few characters as possible to express the logic.

      Personally, I prefer return codes since I don't like the "hidden" control flow created by exceptions but I can see their real value (if for no other reason than allowing the return value to be the result of the function, alone, while errors are returned via an orthogonal channel).

      Whatever the preferred approach, either handle the error or assert that you haven't handled it so that you don't see random behaviour and everything else is just a matter of writing the text.

    7. Re:First problem is considering it clutter by Anonymous Coward · · Score: 0

      Let's pray that is not the attitude of autopilot programmers.

    8. Re:First problem is considering it clutter by Anonymous Coward · · Score: 0

      With an ironically-misspelled user name like "erroneus", I think you might be biased on the subject of error handling. But, perhaps you are the exception!

    9. Re:First problem is considering it clutter by sjames · · Score: 1

      Why is that? Sure, if the API uses return values, you're stuck checking them all, but I would prefer exceptions for error conditions.

  13. Argumentum ad ignoratum by overshoot · · Score: 3, Informative

    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 come to mind.

    --
    Lacking <sarcasm> tags, /. substitutes moderation as "Troll."
    1. Re:Argumentum ad ignoratum by Anonymous Coward · · Score: 0

      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.

    2. Re:Argumentum ad ignoratum by mdmkolbe · · Score: 4, Interesting

      Haskell also comes to mind. Errors are so well handled in that language, you probably won't notice that they are so well handled. Because of the way things are structured, errors are rare (so no need to check them). When they are present, there are a number of techniques from "Maybe" types to "Error" monads to throwing "IO" monad errors. The "Maybe" type is particularly interesting as it ensures that the user will check the error, and provides convenient notations and combinators for doing that checking.

    3. Re:Argumentum ad ignoratum by shutdown+-p+now · · Score: 1

      "Maybe" does not really ensure that the user will check the error - he only has to do that if he wants to extract the value. But he can just return a "Maybe" of his own, and so on, all the way to the entry point. In other words, exactly like exceptions (which is unsurprising, since exceptions are monads).

      The only difference is that in Haskell, since the entry point is not Maybe-returning, someone will eventually have to handle it, even if it's main. In Java, it can actually go beyond the entry point.

    4. Re:Argumentum ad ignoratum by BitZtream · · Score: 1

      So haskell magically manages a temporary DNS error or malformed input from a file? I call bullshit. Your description sounds far more complex instead.

      --
      Persistent Volume manager for Kubernetes - https://github.com/dwimsey/openshift-pvmanager
    5. Re:Argumentum ad ignoratum by Anonymous Coward · · Score: 0

      On the other hand there is a reason to why Haskell so seldom is chosen as a way to solve a problem.

    6. Re:Argumentum ad ignoratum by dkf · · Score: 1

      So haskell magically manages a temporary DNS error or malformed input from a file? I call bullshit.

      Let's see, those are both problems with the external world and so would probably become thrown errors in the IO monad, at least to start with. (OTOH, a DNS lookup would probably have to return a Maybe anyway, as there's no guarantee that a failure will be transient; the address could have been retired from service and there's nothing at the level of code to distinguish "temporary" from "permanent"; the name resolution library itself doesn't know.) You thought you were calling the GP out, but instead just demonstrated your ignorance.

      Of course, the programmer will still have to work out what to do with the failing case. I suspect that that's the part that most people writing code actually suck at, and that's a language-independent suck.

      --
      "Little does he know, but there is no 'I' in 'Idiot'!"
  14. Simple... by dargaud · · Score: 1
    ...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.

    --
    Non-Linux Penguins ?
    1. Re:Simple... by Anonymous Coward · · Score: 0

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

    2. Re:Simple... by Mr+Z · · Score: 1

      ...write code without error.

      How to I find users that won't give it incorrect or inconsistent input, or hardware that won't fail unexpectedly? I don't program the users, and I've yet to find 100% reliable hardware that never wears out.

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

      Ah, that's a bit different. It's advice as to what level you should place your error checking. For example, if you do "fd = open( ... )", you probably should at least check the file descriptor, since you know you can't proceed without it. But, you don't know how to fix it, so pass it up. But, if a subsequent call to "write( )" fails, most of the time you don't actually care. (In the event you do care, because it's critical that your write succeed, then check. But, I argue in most cases, it's OK to let the write silently fail; folks will notice their disk got full in other ways.)

  15. What is needed is event-based programming... by Anonymous Coward · · Score: 1

    ...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.

  16. caught by Marxdot · · Score: 2

    Exceptions here provide greater readability

    Nah, they don't.

    1. Re:caught by ruiner13 · · Score: 2

      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...)

      --

      today is spelling optional day.

    2. Re:caught by Jonner · · Score: 1

      Please, tell us how to handle errors correctly, oh enlightened one.

    3. Re:caught by Marxdot · · Score: 1

      You've already seen it. It features in the article.

    4. Re:caught by K.+S.+Kyosuke · · Score: 1

      Please, tell us how to handle errors correctly, oh enlightened one.

      Most likely by making them go away at as low a level as possible, without forcing the higher layers to handle that messy stuff. The problem with error codes is that using them complicates your control flow. The problem with using exceptions is that using them only makes that complex control flow non-obvious and partially hidden. It doesn't eliminate it.

      --
      Ezekiel 23:20
  17. Third option by wonkey_monkey · · Score: 4, Insightful

    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?

    --
    systemd is Roko's Basilisk.
    1. Re:Third option by Anonymous Coward · · Score: 0

      How can it be that after 60+ years of language development, users still think that exceptions are a bad thing when used properly?

    2. Re:Third option by epine · · Score: 4, Interesting

      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?

      This is a good illustration of the wisdom in Thinking Fast and Slow: the people most likely to highlight what they don't know proceed to the most sensible conclusions.

      I haven't sat down in front of a keyboard to write code since 1985 without this issue foremost on my mind. In the majority of serious programs what the program does is a tiny minority of what you need to think about. Dijkstra wrote some chapters where he illustrates that some programs will actually write themselves if you adhere rigorously to what the program is allowed/not allowed to do at each step, and bear in mind that you need to progress on the variant.

      I do everything humanly possible when I write code to work within the model of tasks accomplished / not accomplished rather than the domain of everything that could possible go wrong (error codes). It's a lot harder when error codes unreliably signal transient / persistent error distinctions. I view programs as precondition graphs, where the edges are some chunk of code that tries to do something, typically a call into an API of some kind. Who cares if it reports an error? What you care about is did it establish the precondition necessary to visit edges departing the destination vertex in the dependency graph?

      Dijkstra also cautions about getting hot and bothered about order relations in terms of which edges execute in which order. In general, any edge departing a vertex with all input conditions satisfied is suitable to execute next. Because he was so interested in concurrency, he assumed that when multiple valid code blocks were viable to run that scheduling was non-deterministic. It can make a difference to program performance which blocks are executed in which order. We enter the domain of premature optimization much sooner than we suspect simply by writing our code with overdetermined linearity (few languages even have a non-deterministic "any of" control operator).

      I had a micro-controller application in which there were many variable references of the form a->b->c->d. This is hell to be strict about precondition testing.


      bool ok;
      ok = a != NULL && a->b != NULL && a->b->c;
      if (ok) {
      ok = fragile_api_call (a->b->c->d);
      if (!ok) sideband_error_info = ERR_YUCK;
      }
      if (ok) { // lather, rinse, repeat
      }

      // ...

      // end of graph, did we succeed or fail?
      if (!ok) {
      barf_out (sideband_error_info);
      }
      return ok;

      This is the fall-through do everything possible and not a thing more programming idiom. It doesn't end up highly nested, because you flatten the dependency graph. Assignments to ok often occur at deeper nesting points than where they are later tested.

      This kind of code often looks horrible, but it's incredibly easy to analyze and debug. The preconditions and post-conditions at every step are local to the action. Invariants are restored at the first possible statement. For the following piece of code, the desired invariant is that if thingX is non NULL, it points to a valid allocation block. In the entire scope of the program, this invariant is untrue only for the duration of the statement whose job is to restore the invariant.

      bool ok = true;

      void* thing1 = NULL;
      thing1 () = malloc (SIZE_MATTERS);
      ok &&= thing1 != NULL;

      void* thing2 = NULL;
      thing2 () = malloc (SIZE_MATTERS+6);
      ok &&= thing1 != NULL;

      if (ok) {
      // more logic
      }

      if (thing1 != NULL) {

    3. Re:Third option by PurplePhase · · Score: 1

      +1: first use of 'invariant' in this topic
      +5: for

      What you care about is did it establish the precondition necessary to visit edges departing the destination vertex in the dependency graph?

      Later you said:

      Error handling involving deeply nested if statements is a nightmare to maintain. The only thing stopping the programmer from flattening it out as I've illustrated is a high pain tolerance for the variable ok.

      Huh. I will consider that much more seriously given what you've presented.

      Also: I've seen both Ruby and Groovy try giving you a shortcut for

      ok = a != NULL && a->b != NULL && a->b->c;

      Unfortunately they didn't make them compiler-required and included some false versions of duck-typing, so they're both off my Ideal Programming Language list anyway.

    4. Re:Third option by sakti · · Score: 1

      You are missing at least 1 third options that is already in practice today. A side channel which propagates errors. PHP's error handler setup does this and stderr in shell programming is akin to this as well.

      --
      "It is better to die on one's feet than to live on one's knees." - Albert Camus
    5. Re:Third option by Anonymous Coward · · Score: 0

      bool ok = true;

      void* thing1 = NULL;
      thing1 () = malloc (SIZE_MATTERS);
      ok &&= thing1 != NULL;

      thing1 () = ...
      What language is that?

      void* thing2 = NULL;
      thing2 () = malloc (SIZE_MATTERS+6);
      ok &&= thing1 != NULL;

      You forgot to change the variable when copy/pasting, so ok is not really ok at this point, but I like that coding-style...

  18. Too easily impressed by White+Flame · · Score: 5, Insightful

    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.

    1. Re:Too easily impressed by Mr+Z · · Score: 1

      I guess the "innovation" here is that it brought it to a C like language? And errno sucks because it's a single global.

  19. There is a better way to use exceptions by ribuck · · Score: 2

    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.

    1. Re:There is a better way to use exceptions by Anonymous Coward · · Score: 0

      I don't think you have written multi-process, mult-threaded applications - or at least not very sohpisticated ones. Your approach describes usage for something akin to hello world and completely fails to scale and fails when other threads and processes are required to keep running even if one thread (i.e. a user session) fails.

      Most of the solutions here make the assumption that it is okay for an application to quit/abort when an exeption / error condition is encountered. FAIL. Error HANDLING implies just that: The "Handling" of errors - not just giving up and letting the application crash - that's not what "Handling" means.. Logging has nothing to do with this. The mechanism (error codes or exceptions) has nothing do with this.

      And YES, it's very difficult to write good error handling and YES it does take about 50% of the source dedicated to this, but that's why we get paid what we get paid. If this was easy, everybody would be able to do it. Some can, some can't. This separates the Men from the boys (or Woman from the girls). And this is why the state of software is so sad today. Functionaliy 1st (to get VC money) and then let the customers do the testing and reporting of bugs. It worked for Microsoft for a long time..

      The 1st rule is that an app should never crash in an unanticpated manner, the 2nd rule is an app should accomplish what it was intended to do. The 3rd rule is see rule #1.

  20. Condition System by Anonymous Coward · · Score: 1

    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

  21. What do you propose ? by Anonymous Coward · · Score: 0

    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

    1. Re:What do you propose ? by Anonymous Coward · · Score: 0

      A structure like a with or case block, that allows the application programmer to decide what to do on all but the most dire of exceptions (uncorrectable machine check errors, for instance), and neatly contains any locally handled exception. What are commonly used as exceptions may be a normal part of control flow, and not exceptional at all, while sometimes status function returns may need to be exceptional. Sideband status, rather than exceptions that must be caught, are not bad to use at all, for this purpose.

      For example, some pseudocode:

      result = null
      result = try MyObject.Method(param) as funcrun {
          on buffer_full {
              wait(2); funcrun(param); }
          on permission_denied {
              alert("I'm sorry Dave, I'm afraid I can't do that"); exit(); }
          on timeout(5) {
              log_error(MyObject.toString(), funcrun.toString(), param.toString); }
          on default {
              log_error(MyObject.toString(), funcrun.toString(), param.toString); exit(); }
      }

  22. CSI-error by Anonymous Coward · · Score: 0

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

    Why should Anti-virus companies have all the fun?

  23. Mid-'70s PL/I Exception Handling is Alive & We by theodp · · Score: 1

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

  24. Hint: computers are binary by Gothmolly · · Score: 1

    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.

    --
    I want to delete my account but Slashdot doesn't allow it.
    1. Re:Hint: computers are binary by gbjbaanb · · Score: 1

      sorry, fail.

      there are functions that successfully return 0 which indicates a failure. (Microsoft even defines the S_FALSE return code for COM).

      eg, you want to look up an entry in a lookup table: you pass in the thing you want to get the associated data for, and there is no entry in the table - its a failure, but its not an unexpected failure (there might be cases where you are the first one to add to the table, this 'error' condition says you need to initialise the data).

      So if you use exceptions for this case, you're going to be unhappy. If you use return codes, what do you return? success? Nothing failed per se, but it didn't succeed either as you don't have the data you requested and you have to take alternative action.

    2. Re:Hint: computers are binary by shutdown+-p+now · · Score: 1

      S_FALSE is not an error code. S_ stands for "success". It's a success code that's different from the usual S_OK (=0), and is a rather blunt optimization for those functions that basically return a Boolean value, so that you don't have to pass in an extra pointer for it to write into.

    3. Re:Hint: computers are binary by BitZtream · · Score: 1

      You're confused.

      Functions either succeed or fail, period. That statement is fact.

      What you are confusing is when functions/methods appear to succeed but have actually failed.

      If the function/method performs within its design ... like say returning a special value when the key doesn't exist in the table, then it is not failing. The function succeeded in its design parameters. If the function was supposed to return NULL but instead returned the first item in the table or some random value, then it would have failed.

      --
      Persistent Volume manager for Kubernetes - https://github.com/dwimsey/openshift-pvmanager
    4. Re:Hint: computers are binary by dkf · · Score: 2

      Functions either succeed or fail, period. That statement is fact.

      Alan Turing and Kurt Gödel might not entirely agree with that statement. (Functions can also not terminate, and it can even be impossible to work out if they are going to terminate or not.)

      --
      "Little does he know, but there is no 'I' in 'Idiot'!"
  25. Inconvenient? yes. Necessary? yes by hardtofindanick · · Score: 1

    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.

    1. Re:Inconvenient? yes. Necessary? yes by loufoque · · Score: 1

      You only have to log when the error occurs, not when it is forwarded to the parent scope, so I don't see how it would add any verbosity.

  26. There is no such thing as an error. by Cryptosmith · · Score: 2

    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.

    1. Re:There is no such thing as an error. by Jonner · · Score: 1

      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.

      Good luck anticipating every error condition possible during your program's run time.

    2. Re:There is no such thing as an error. by Mr+Z · · Score: 1

      Hmmm... so if I ask a program to read a file that doesn't exist, should it just create an empty document of that name? Possibly the right answer for a word processor, but quite probably the wrong answer when specifying an attachment to an email.

      I think that statement needs to be clarified: An internal error alert pop-up that could happen without a hardware failure is an admission of failure on the part of the programmer, no doubt. But, if the user truly is in error, there's nothing to admit on the programmer's part when they tell the user they're wrong. The program still has to check the user, though.

    3. Re:There is no such thing as an error. by Anonymous Coward · · Score: 0

      Hmmm... so if I ask a program to read a file that doesn't exist, should it just create an empty document of that name? Possibly the right answer for a word processor, but quite probably the wrong answer when specifying an attachment to an email.

      The answer isn't to ignore or make guesses about the things you call errors. You use them as signals of user intent, or of the progress of the task. Programs need guidance, but they're not really asking for guidance when they just give up and ask "abort or retry?"

      I think that statement needs to be clarified: An internal error alert pop-up that could happen without a hardware failure is an admission of failure on the part of the programmer, no doubt. But, if the user truly is in error, there's nothing to admit on the programmer's part when they tell the user they're wrong. The program still has to check the user, though.

      Hardware failures happen. If your program can detect them, then your program should handle them.

      Both the program and the user must share a simple notion of what is happening with storage and communications. This is one reason that iOS adopted the "don't worry about saving" model.

    4. Re:There is no such thing as an error. by Mr+Z · · Score: 2

      Speaking of iOS: Are you saying that if the battery is low, the phone should shut off without warning, saving all data, or give a few warnings as the battery gets low? The no-error-alert paradigm is just stupid.

      My car warns me when it detects a failure, and I think it's no failure of software designers if they also warn me when things are amiss. I'd hate it if my car just tried to "handle" low fuel, low oil pressure, low tire pressure, or what-have-you, as about the only thing it could do for any of those is just stop. iOS devices are in a similar circumstance with low battery.

      Are you still of the opinion that there should never be an error alert unless it's the programmer admitting some sort of failure? "I failed to program an infinite capacity battery."

  27. Try-Catch blocks should not exist... by Anonymous Coward · · Score: 0

    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.

    1. Re:Try-Catch blocks should not exist... by interval1066 · · Score: 2

      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.

      --
      Python: 'And then suddenly you have a language which says "we're all stuck with whatever the whiniest coder wants".'
    2. Re:Try-Catch blocks should not exist... by jythie · · Score: 2

      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.

    3. Re:Try-Catch blocks should not exist... by Waffle+Iron · · Score: 1

      Yoda agrees: "Do or do not. There is no try."

    4. Re:Try-Catch blocks should not exist... by sjames · · Score: 1

      Sometimes, a low level function cannot know what to do about an error condition without a huge violation of scope. The right thing to do is throw an exception and let it be caught within the scope that has some way to deal with it.

      The try block should be the size of the dependent code. If A raises an exception, everything that needed A to actually workk in order to do anything meaningful should be in the try block. In many cases, that will be the entire rest of the function.

      There is no reason at all that try/catch MUST create slower or less efficient code.

    5. Re:Try-Catch blocks should not exist... by Marxdot · · Score: 1

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

      Any objection to the current fashion/buzzword/hegemony (e.g. OOP, exceptions, multiple inheritance, mortgage-driven agile development, subversion) in programming quickly gets battered down with "You're just angry that you don't know how to use it, and you don't understand it." Don't you find that argument tiresome? I certainly do.

      Furthermore, the belief that all tools have a good purpose, or that they are "perfect" for some set of tasks no matter what, is fallacious. You probably wouldn't jump to the defense of an intentionally esoteric programming language in such a manner.

    6. Re:Try-Catch blocks should not exist... by BitZtream · · Score: 1

      Okay, now take all those things you said a 'good coder' does, and then add that person using Try/Catch on top of it.

      I doubt you would know a 'true programmer' if he/she slapped you in the face.

      --
      Persistent Volume manager for Kubernetes - https://github.com/dwimsey/openshift-pvmanager
    7. Re:Try-Catch blocks should not exist... by jythie · · Score: 1

      Considering how mature exception handling is at this point, I would hardly call it the 'current fashion'.

      Exceptions have their uses. If someone is writing them off completely, then that speaks to them either not considering those cases, being willfully ignorant, or not being competent in the tool.

      While normally I agree with your argument here, I think you are way over applying it as a way to shut down defense of a tool you do not like.

      Besides, the 'you don't understand it' argument is tiresome when people use it to silence people who fail to acknowledge as the one true solution, so essentially the opposite usage since in this case it is being used to attack a 'one false way' argument, with no accompanying 'one true way' one.

    8. Re:Try-Catch blocks should not exist... by Marxdot · · Score: 1

      Exceptions have their uses, but those use cases completely overlap with simply checking for Bad Things there and then & taking appropriate action, even if that appropriate action is using a goto that jumps to the 'relinquish & return nil' part of a routine (which is essentially what exceptions are when coupled with destructors -- exceptions are fancy implicit goto statements/longjmps).

      I agree it's a bit far to claim that exceptions should never have existed, as the OP did. I quite appreciate Haskell's 'Maybe' monad, and the exceptional circumstances you can explicitly declare as bodies of a function; that is a sort of exception handling that I like because it combines both a clear indication that exceptional circumstances may arise at that place, and the immediacy of checking for bad circumstances and bailing out there and then.

    9. Re:Try-Catch blocks should not exist... by jythie · · Score: 1

      I think one of the core uses comes from that 'appropriate action' part. It is not always possible or even desirable to handle an error where the error actually occurred.

      Another major use case would be where the programmer does not have control over the code, such as loadable modules or libraries linked to.

      I can see the argument that they are a fancy goto, but then again events are just fancy function calls. That exceptions can propegate up a call stack until something catches them (without the throwing function needing any knowledge of anything earlier on the stack) gives them significant extra functionality.

  28. Sh!t happens! by Anonymous Coward · · Score: 0

    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.

  29. Miine is better: increases revenue by Anonymous Coward · · Score: 0

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

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

  30. Doing it wrong by Sarten-X · · Score: 1

    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).

    --
    You do not have a moral or legal right to do absolutely anything you want.
    1. Re:Doing it wrong by Anonymous Coward · · Score: 0

      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.

    2. Re:Doing it wrong by Anonymous Coward · · Score: 0

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

    3. Re:Doing it wrong by Anonymous Coward · · Score: 0

      This is my biggest gripe with exceptions, and particularly, the MS way of handling exceptions.

      I double dare anyone to get meaningful debug info from MS C#, i.e. line # and file or function
      in a production environment.

      It is very frustrating. I explain to junior developers that the first class that should be written is a
      log class, and everything else should depend on it. But we've, for the most part, have allowed
      the lazy culture of happy coding to become entrenched. Sadly, most code has logging or
      proper error handling implemented as an afterthought.

      CAPTCHA = tempted

    4. Re:Doing it wrong by Sarten-X · · Score: 1

      As you mentioned, it sounds like your old server code needs better logging from a better programmer.

      An exception should mean that something crazy happened that the code can't handle, so the managing routine should try to handle it instead. If no managing routine knows how to handle the situation, then it's left to the user.

      Since your managing routines can't handle the exceptional circumstance, and your managing staff won't let you install better code, I'll have to say your problem is with the management, not the exceptions. Any error handler can discard (or fail to collect) useful information.

      --
      You do not have a moral or legal right to do absolutely anything you want.
    5. Re:Doing it wrong by mevets · · Score: 1

      Your server code needs better exception handling.

      Try adding a line like *(volatile char *)0=1 at the point where it throws, and examine the resultant dump with a decent debugger.

  31. Yes Monads! by Weezul · · Score: 4, Interesting

    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.

    --
    The Christian religion has been and still is the principal enemy of moral progress in the world. -- Bertrand Russell
    1. Re:Yes Monads! by shutdown+-p+now · · Score: 1

      Exceptions are monads, though, quite literally so. Any expression in a language with exceptions is just returning type result<'a> = Value of 'a | Error of exception, basically (with exception being polymorphic). And in a language like Java with checked exceptions, you get even more specific types there.

  32. Most programmers use a third solution by cstdenis · · Score: 2

    Just don't bother checking for errors.

    --
    1984 was not supposed to be an instruction manual.
    1. Re:Most programmers use a third solution by Anonymous Coward · · Score: 0

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

  33. Error handling is code, not clutter by Anonymous Coward · · Score: 0

    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.

  34. Akka by Anonymous Coward · · Score: 0

    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, ... }.

  35. Problem with Exceptions by shawnhcorey · · Score: 1

    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 for details and an example.

    --
    Don't stop where the ink does.
    1. Re:Problem with Exceptions by Meneth · · Score: 1

      Java (and C#, I think) enforces this; every exception you don't catch must be declared.

    2. Re:Problem with Exceptions by Anonymous Coward · · Score: 1

      C# does not have checked exceptions

    3. Re:Problem with Exceptions by angel'o'sphere · · Score: 1

      Unfortunately C# has no declared/checked exceptions.

      --
      Cost free eBook I read (by iBook/Kobo/Amazon/ObookO/Gutenberg etc.): "The Green Odyssey" by Philip Jose Farmer.
    4. Re:Problem with Exceptions by Anonymous Coward · · Score: 1

      C# doesn't have the exception declaration rules of Java. In C# the exception propagates upward until the code or the runtime itself logs it into the Windows Event Log as a fatal event.

      I don't much care for systems that allow that behavior despite being a die hard C# coder. It let's you push executable code out of the app domain and into system domain with a deceptively simple exploit. I use such exploit to ensure logs are written, even when the app is ran without usage privileges to create a new file in it's folder. That exploit has been there for as long as I can remember, a malicious app could use it to perform function replacements in the GAC. I've sent several samples to Microsoft demonstrating it, have yet to get a response or see it fixed, one of the sample captured encryption keys passed into .Net's decryption methods.

    5. Re:Problem with Exceptions by loufoque · · Score: 1

      This is the most stupid idea ever.
      You have completely misunderstood the point of exceptions.

      If the exception can be handled directly by the caller, then you should use return values. Exceptions are for situations where you want the abstraction that the operation never fails, while still keeping the ability to handle such failure at a higher level.

    6. Re:Problem with Exceptions by Jonner · · Score: 1

      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 for details and an example.

      Yeah, writing five exception handlers, each just throwing the exception again is so much better than handling it once.

    7. Re:Problem with Exceptions by PhamNguyen · · Score: 1

      I can't believe that a person who advertises a blog for their own new language, wouldn't already be familiar with such related features in popular languages like Java. So you must be mistaken.

    8. Re:Problem with Exceptions by shawnhcorey · · Score: 1

      Yeah, writing five exception handlers, each just throwing the exception again is so much better than handling it once.

      Yes, it is. Not being thorough is bad always engineering.

      --
      Don't stop where the ink does.
    9. Re:Problem with Exceptions by smellotron · · Score: 1

      ... writing five exception handlers ...

      If you think every caller should have logic which reacts to errors, why do you need automatic stack unwinding? Just use error codes.

      Not being thorough is bad always engineering.

      But catching exceptions—only to re-throw them—is not "being thorough". It is boilerplate. If the caller is not exception-safe then you should consider a more transactional paradigm, so that you don't need to catch and re-throw. If you want to force callers to handle errors immediately, then stop using exceptions and start using "checked error codes" (i.e. lightweight objects which represent error codes and verify that the caller has acknowledged the error state).

    10. Re:Problem with Exceptions by shawnhcorey · · Score: 1

      The difference between exceptions and error codes is that uncaught exceptions cause the program to terminate. To ignore them, the programmer must add code. If there's no code to handle an error code, you don't know if the programmer wants it ignored, or that he was completely unaware of it.

      --
      Don't stop where the ink does.
  36. Third option: have no errors by pclminion · · Score: 1

    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".

  37. Why should exceptions be "exceptional"? by Anonymous+Brave+Guy · · Score: 2

    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.

    --
    If you disagree, post your argument. (-1, Overrated) isn't your personal censorship tool for views you don't like.
    1. Re:Why should exceptions be "exceptional"? by Bomazi · · Score: 1

      Reserving exceptions for error handling is a convention that makes it easy to distinguish error handling code from normal code and therefore improves readability.

      This rule is mainly intended to discourage this kind of monstrosity:
      int find (int val, char *t, int n)
      {
              try {
                      for (int i = 0; i n; i++) {
                              if (t[i] == val)
                                      throw i;
                      }
              }
              catch (int i) {
                      return i;
              }
              return -1;
      }

      If however you had to return across multiple function calls you would have to choose between exceptions and longjmp. Non-purists wouldn't object to exceptions in that case as they are safer.

    2. Re:Why should exceptions be "exceptional"? by Anonymous+Brave+Guy · · Score: 1

      Sure, the code you gave there would obviously be a bad example. But that's partly due to the obvious redundancy and partly due to awkward syntax that tries to give different names to essentially the same result ("I know the answer now") in different contexts.

      What would you think of code in a hypothetical language that looked something like this (apologies for the syntax; I have no idea how to get trendy modern Slashdot to do basic things like not screw up the formatting for a source code listing):

      function find values target:
      ..for (index, value) in enumerate values:
      ....if value = target:
      ......result FoundAt index
      ..result NotFound

      ...

      match find colours Orange with:
      ..FoundAt index -> doSomethingWith index
      ..NotFound -> doSomethingElse

      I haven't said anything about return codes or exceptions there, because I don't think it matters. The important thing is that the find function either results in finding the value at a certain index or it doesn't, not the mechanics we happened to use to tell the code asking the question what the answer is.

      --
      If you disagree, post your argument. (-1, Overrated) isn't your personal censorship tool for views you don't like.
    3. Re:Why should exceptions be "exceptional"? by gbjbaanb · · Score: 1

      Here you go: the guy who wrote the .NET system explaining just why they are slow - in detail, lots of detail.

      Performance in particular is detailed near the end, find "Performance and Trends" if you can't cope with the first half:

      However, there is a serious long term performance problem with exceptions and this must be factored into your decision.

      Consider some of the things that happen when you throw an exception:

              Grab a stack trace by interpreting metadata emitted by the compiler to guide our stack unwind.
              Run through a chain of handlers up the stack, calling each handler twice.
              Compensate for mismatches between SEH, C++ and managed exceptions.
              Allocate a managed Exception instance and run its constructor. Most likely, this involves looking up resources for the various error messages.
              Probably take a trip through the OS kernel. Often take a hardware exception.
              Notify any attached debuggers, profilers, vectored exception handlers and other interested parties.

      This is light years away from returning a -1 from your function call. Exceptions are inherently non-local, and if there's an obvious and enduring trend for today's architectures, it's that you must remain local for good performance.

    4. Re:Why should exceptions be "exceptional"? by Anonymous+Brave+Guy · · Score: 1

      Those are problems (if they're problems at all) only because Microsoft's particular managed environment imposes all kinds of overheads and mixes up hardware/OS/managed runtime functionality with a language feature. Not one of those examples is a fundamental or essential problem with the concept of exceptions.

      Grab a stack trace by interpreting metadata emitted by the compiler to guide our stack unwind.

      That can be done with simple table look-ups, a negligible overhead for something we're only running once where we're probably already talking about unwinding several stack frames and running tidy up code along the way. As I mentioned before, I have spent significant time looking at and profiling generated code in this area, and I'm telling you that jump tables as used in many even slightly modern C++ compilers do this faster than a return code approach can unwind a stack one frame at a time using return codes.

      Run through a chain of handlers up the stack, calling each handler twice.

      That sounds like an architectural compromise made by that specific managed environment. Presumably there is some reason in .Net that calling each handler twice is necessary, but in general it isn't. And since the only thing handlers generally need to do until you get to the final one is tidy up side effects by freeing resources and the like, which you also need to do if you're unwinding manually, there's no additional overhead there at all.

      Compensate for mismatches between SEH, C++ and managed exceptions.

      Again, that's an overhead if you're running in Microsoft's managed environment, not a problem with exceptions as such. You're talking about a non-standard behaviour projecting OS-level functionality (SEH) onto a language level feature (C++ exceptions), which is apples to oranges.

      Allocate a managed Exception instance and run its constructor. Most likely, this involves looking up resources for the various error messages.

      As opposed to either not returning the useful information at all (if you just dump a trivial return code on the caller) or constructing an object with more information to pass back by some other means (which will incur essentially the same overheads to build it, set up error messages, etc.). Again, there's no fundamental overhead implied by exceptions here. It's the same work you'd do to return the same information using return codes anyway.

      Probably take a trip through the OS kernel. Often take a hardware exception.

      Again, this is conflating hardware/OS level functions with exceptions as a tool in a programming language. Just because Microsoft project one onto the other, that doesn't mean everyone else does or wants to.

      Notify any attached debuggers, profilers, vectored exception handlers and other interested parties.

      So now I'm not allowed to use the best tool for the job if it's inconvenient for people writing developer tools? I put it to you that in this case, the development tools have the problem. And in any case, presumably this overhead only applies if any such development tools are actually in use, so in production code it's a no-op.

      This is light years away from returning a -1 from your function call.

      It's also light years away from what most people mean when they talk about exceptions as a language feature.

      Exceptions are inherently non-local, and if there's an obvious and enduring trend for today's architectures, it's that you must remain local for good performance.

      Programming any non-trivial system is inherently non-local, particularly if you use things like modular designs and functional decomposition. You can use exceptions, which dovetail neatly with that approach, or you can throw the logic into your big ball of mud architecture, and not fit in the cache anyway.

      --
      If you disagree, post your argument. (-1, Overrated) isn't your personal censorship tool for views you don't like.
    5. Re:Why should exceptions be "exceptional"? by serviscope_minor · · Score: 1

      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.

      As far as I know, C++ compilers have gone in the direction of making exceptions free at the expense of high cost if they are thrown. As a result the common exception free path is fast--faster than the error code version, but the uncommon path is substantially slower.

      A fair tradeoff, IMO.

      --
      SJW n. One who posts facts.
    6. Re:Why should exceptions be "exceptional"? by Darinbob · · Score: 1

      You split things up into fail or succeed. But there's more than that. The routine itself may need to figure out what to do instead of naively throwing an error and giving up. You reach an end of file, maybe that means throw an exception which causes the next file to be opened, which is not an error or a success but it is an exceptional condition. Or you get an underflow when dividing floating point so you fall back to using a default value; not an error or a success but an exceptional condition.

    7. Re:Why should exceptions be "exceptional"? by Anonymous+Brave+Guy · · Score: 1

      As far as I know, C++ compilers have gone in the direction of making exceptions free at the expense of high cost if they are thrown.

      Not necessarily. Several major C++ compilers implement exceptions using some variation of jump tables, where the exceptional paths are effectively precomputed. Unless you start doing tricky things like calling functions indirectly via pointers, where obviously you can't precompute everything as effectively, there is negligible (time) cost even if the exception is thrown. Effectively, you just call any relevant destructors that would have been encountered as you unwound the stack (each of which you would necessarily also have run even if you had returned from each function one by one) and then jump directly to the nearest matching handler. The main trade-off is that a lot of space may be used to hold those jump tables.

      (This isn't necessarily true of implementations of similar exception features in other languages/environments, or even of all C++ compilers on all platforms, but it does demonstrate what is possible.)

      --
      If you disagree, post your argument. (-1, Overrated) isn't your personal censorship tool for views you don't like.
    8. Re:Why should exceptions be "exceptional"? by Anonymous+Brave+Guy · · Score: 1

      Any given routine can only ever succeed or fail. When it returns control, either it hands back the result and/or causes the side effects you asked for, or it doesn't.

      I'm not sure what realistic scenarios you had in mind when describing those other cases, but they sound like simply applying the same principles at a lower level to me: something causes a low level function to complete, and a higher level function detects that and then carries on with whatever behaviour is appropriate for the overall design/algorithm being implemented. If the higher level code can recover gracefully from any problems lower down, the overall algorithm might still succeed. If the higher level code can't continue its work once a lower level component has failed, at some point the higher level function is going to indicate failure as well.

      --
      If you disagree, post your argument. (-1, Overrated) isn't your personal censorship tool for views you don't like.
    9. Re:Why should exceptions be "exceptional"? by Darinbob · · Score: 1

      How about a function can succeed in different ways. Maybe one of those successful ways is to finish up some work and then throw an exception to a higher level routine to continue? Ie, reaching end-of-file or end of a network stream is not a failure. Or how about processing some background operations until a semaphore can be acquired at which point it's time to finish up and return to a higher level.

    10. Re:Why should exceptions be "exceptional"? by Anonymous+Brave+Guy · · Score: 1

      Sorry, I'm not quite sure what point you're trying to make here. If you're arguing that sometimes an exception-like mechanism can be useful for returning control in expected cases as well as unexpected ones, then I agree with you, as long as the mechanism in the particular language/environment you're using is suitable of course.

      --
      If you disagree, post your argument. (-1, Overrated) isn't your personal censorship tool for views you don't like.
    11. Re:Why should exceptions be "exceptional"? by gbjbaanb · · Score: 1

      all in all, I'm highlighting that real-world usage of exceptions will be slow. I don't care why that is too much, nor whether it could theoretically be made better, my day-job says "make it fast" so I need to know how to achieve that.

      Of course, I'd love to go back to C++ programming which would solve half my problems with the .NET bolloxs I have to use at the moment. Note that most people were told that exceptions were essentially free when used in a managed environment... so you do see a lot of kids thinking they can use them for program flow, but they're still not free even in C++ code.

    12. Re:Why should exceptions be "exceptional"? by Anonymous+Brave+Guy · · Score: 1

      If your argument is that exceptions are relatively slow if you're using a platform where the implementation of exceptions is relatively slow, then I can't really argue with that! :-p

      But the original comment I replied to was making a blanket statement about how to use exceptions, and was talking specifically about C++: "Exceptions are usually quite expensive, especially in C++ compared to just returning an error code." That simply isn't true, for the reasons I explained before.

      --
      If you disagree, post your argument. (-1, Overrated) isn't your personal censorship tool for views you don't like.
  38. error handling in functions by Khashishi · · Score: 1

    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.

    1. Re:error handling in functions by Anonymous Coward · · Score: 0

      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.

    2. Re:error handling in functions by loufoque · · Score: 1

      For a case without function composition, consider the following C++ code:

      void f()
      {
          T a;
          U b;
          V c;
      }

      I haven't even started actually doing anything here, and there are a lot of problems writing this without exceptions:

      int f()
      {
          T a;
          U b;
          V c;
          if(T_init(&a) == -1)
              return -1;
          if(U_init(&b) == -1)
          {
              T_free(&a);
              return -1;
          }
          if(V_init(&c) == -1)
          {
              U_free(&b);
              T_free(&a);
          }
          V_free(&c);
          U_free(&b);
          T_free(&a);
          return 0;
      }

      and that's making the assumption that the destructors cannot throw. If they could, the C code would become even more complicated...

    3. Re:error handling in functions by Anonymous Coward · · Score: 0

      This is a contrived example. In the real world you add an "err:" label at the end that does the clean-up and do "goto err;" at every error.

    4. Re:error handling in functions by Mr+Z · · Score: 1

      In this example, what if the failing function just returned NaN, and you let the NaNs propagate? I guess in some cases you care which of factorial(), zeta() or geommean() failed, but more often you care whether the expression as a whole failed or not.

    5. Re:error handling in functions by Khashishi · · Score: 1

      That works fine with floating point, but integers don't have an NaN.

    6. Re:error handling in functions by Mr+Z · · Score: 1

      Are zeta or geommean even remotely useful on ints?

  39. There is no third option by gman003 · · Score: 4, Insightful

    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.

    1. Re:There is no third option by JesseMcDonald · · Score: 3, Informative

      There is at least one other method, which is available natively in Common Lisp. It's known as conditions, and involves registering a condition handler which, unlike an exception handler, runs in the context where the error occurs. The handler has access to zero or more dynamically-scoped restarts, which allow the computation to be resumed at well-defined points without unwinding the entire stack up to where the condition handler was established. The default condition handler is an interactive debugger, which allows the user to examine the state of the program and choose one of the available restarts.

      Beyond Exception Handling: Conditions and Restarts

      --
      "The state is that great fiction by which everyone tries to live at the expense of everyone else." - Bastiat
    2. Re:There is no third option by bill_mcgonigle · · Score: 2

      the language/compiler/interpreter/processor/operating system should handle errors for me

      Which they can't, unless they know what your intents are. Perhaps there's a way of declaring intents, I'm not sure.

      A subset of this might be something like invariant conditions / code contracts which makes sure that you don't have as many unexpected errors to handle. Static typing is another (and more rigid) approach.

      The author isn't wrong in the narrow sense that the programmer's tools should allow him to focus his error checking on the flow of his code logic, not the constraints placed on him by his language and runtime. Aspects/cross-cutting could help a bit here too. But there's also the point that programmers are lazy or under the gun - if you see a java programmer always only catching (Exception e) then he's not doing the kinds of error checking that the authors of the class he's using knew could occur. I can see where a development manager might want the option to turn off this shortcut capability for his developers for certain types of code. Automatic code grading could potentially address this for organizations (who might very well choose to accept "D+" code because that's there's budget for, but they'd do it knowingly).

      --
      My God, it's Full of Source!
      OUTSIDE_IP=$(dig +short my.ip @outsideip.net)
    3. Re:There is no third option by Anonymous Coward · · Score: 0

      Yes, back around '64 (19 not Commodore) PL1 introduced things like ON ERROR BEGIN; PUT DATA; END; ON ENDFILE(FILE1) BEGIN; CALL PRINT_FILE_1_TOTALS; END; ...

      We put all the error handlers at the start of the program so that they would be registered to handle their particular categories of errors. I believe that the normal handling was to perform the BEGIN block and then resume the program right after the statement that caused the problem. If the BEGIN block bailed out with a GOTO, there was no resumption.

      So there has been a third way long time.

    4. Re:There is no third option by aurelien · · Score: 1

      I don't see the Condition System as an alternative: it's actually an extension of the rigid exception handling systems of popular languages (the new concept is the signal/restart-bind protocol).

      --
      aurelien
    5. Re:There is no third option by JesseMcDonald · · Score: 1

      I don't see the Condition System as an alternative: it's actually an extension of the rigid exception handling systems of popular languages (the new concept is the signal/restart-bind protocol).

      That's a bit like saying that exception handling is just an extension of the return-code system (the new concept being the try/throw/catch protocol). With some effort, you could emulate exception handling with return codes (though without the optimizations). The difference is precisely in having a well-defined protocol, which is the aspect you're glossing over in the comparison between the Condition System and exception handling systems.

      The Condition System can do at least one thing which the "rigid exception handling systems" cannot, which is allow you to customize the error-handling behavior of a routine from outside the routine, without forcing it to exit and restart the operation from the beginning. In my opinion, this additional ability is enough to set it apart. If anything, it's more than the difference between exception handling and return codes, which is mainly a matter of syntax. Implementing a Condition System requires features associated with functional languages: the ability to capture the lexical and dynamic environments of a block of code, and the ability to perform safe non-local returns.

      If all languages implemented the Condition System natively, I could understand classifying exceptions as a subset of conditions, but that isn't the case; most languages are limited to exception handling, just as some languages are limited to return codes.

      --
      "The state is that great fiction by which everyone tries to live at the expense of everyone else." - Bastiat
  40. I think by Anonymous Coward · · Score: 0

    ..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.

  41. Haskell Error Monad Transformer by Anonymous Coward · · Score: 1

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

  42. Failure is not an error by Anonymous Coward · · Score: 0

    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.

  43. Exceptions sound like a good idea, but... by Anonymous Coward · · Score: 0

    ...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.

  44. NOT by Anonymous Coward · · Score: 0

    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.

    1. Re:NOT by shutdown+-p+now · · Score: 1

      C# has IDisposable/using. It's not equivalent - a far cry from it - but it covers some common cases. And Java is getting Closable/try-block in Java 8, which is more or less the same thing.

    2. Re:NOT by dkf · · Score: 1

      C# has IDisposable/using. It's not equivalent - a far cry from it - but it covers some common cases. And Java is getting Closable/try-block in Java 8, which is more or less the same thing.

      That's a language feature of Java 7, and is already in production.

      --
      "Little does he know, but there is no 'I' in 'Idiot'!"
  45. Pfff by Greyfox · · Score: 2

    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'm trying to teach myself to set people on fire with my mind... Is it hot in here?

    1. Re:Pfff by larkost · · Score: 3, Insightful

      I somewhat agree with you, but your examples are horrible: the near-requirement for header files and prototype functions in C stemms from a language deficiency, not from something that "beginner CS students" don't get. They are correctly seeing the situation as non-optimal. Java any Python have both (in differnt ways) are examples of langauages that handle these things with a multi-step parse. Note that I am not arguing aginst the option of having headder files, since they clearly have a use in large project (one that javadoc also servers). But the requirement to have function prototypes in order to have out-of-order functions is simply a language deficiency. The fact that people have been very sucessful while working around it for so long is a testiment to them, not to the language's inherint merit.

    2. Re:Pfff by Greyfox · · Score: 1
      Java hasn't completely eliminated such things; interfaces are pretty much the same thing. You could write an entire library in Java and hide its implementation details behind a bunch of published interfaces or you could write an entire library in C++ and hide its implementation details behind a bunch of header files. At some point you're going to have to tell the compiler how something should be called. I tend to view the vast majority of the code I write in C++ as library code anyway, so I don't really view the header files as a problem. You could always write all your implementation code in the class body of the header file, too, if you didn't mind compiling the file every time you want to use that class. Or write a pure abstract class to serve as an interface, but it would feel pretty java-y if you did that for all your classes.

      The same guys who don't want to write header files in C/C++ will most likely not want to write interfaces in Java, either, requiring you to smack them with a bamboo stick until they become enlightened.

      --

      I'm trying to teach myself to set people on fire with my mind... Is it hot in here?

  46. I read the article by iplayfast · · Score: 3, Insightful

    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.

    1. Re:I read the article by SplashMyBandit · · Score: 1

      I agree with you. The editor is too simplistic. Why you want to have more than just a single global error handler is that you want to provide information so the caller can make decisions about what they can handle and what they can't handle based on the precise reason for the failure.

      In your file example the file might not be able to be opened for many reasons, like: it doesn't exist; the user doesn't have permission to open it; the file is locked by another process etc. Depending on the cause the application can then make decisions whether to: create the file; prompt the user to increase priviledge and then access the file; modify the file's permissions; or release the lock held in another thread and try again; or, just give up completely, recover to a safe state (eg. before the operation was attempted) and then log the operating and file that caused the problem so it can be diagnosed and fixed later.

      To me it is shocking that the editor would propose so simplistic solution. If he was working on real-life programs that had to be reliable (instead of tinkering with toy programs for his column, which perhaps could be the case) then he would know that having the ability to distinguish exceptions by type and cause can be very useful for sensible error handling *and recovery*. Now I don't mean by this that every program must have a complex user-defined exception hierarchy, in fact I think that this is almost never warranted, but it can be useful in some cases (although a simple user defined exception with enumerated cause code works just as well as a class based hierarchy, but is much simpler).

    2. Re:I read the article by msclrhd · · Score: 1

      Exceptions are just as bad. Consider the following Java code:

      public interface JSONSerialisable
      {
        public Object toJSON() throws JSONException;
      }

      public class JSON
      {
        public static boolean write(FileOutputStream file, JSONSerialisable object)
        {
          String content;
          try
          {
            content = object.toJSON().toString();
          }
          catch (JSONException e)
          {
            Log.e("JSON.write", e.toString());
            return false;
          }

          BufferedOutputStream buffered = null;
          try
          {
            try
            {
              buffered = new BufferedOutputStream(file);
              buffered.write(content.getBytes("UTF-8"));
              buffered.flush();
            }
            finally
            {
              if (buffered != null)
              {
                buffered.close();
              }
            }
          }
          catch (IOException e)
          {
            Log.e("JSON.write", e.toString());
          }
          return false;
        }

        public static boolean write(String filename, JSONSerialisable object)
        {
          try
          {
            return write(new FileOutputStream(filename), object);
          }
          catch (FileNotFoundException e)
          {
            Log.e("JSON.write", e.toString());
          }
          return false;
        }
      }

      And that is just for a simple workflow.

    3. Re:I read the article by loufoque · · Score: 1

      file1's destructor will close the file.
      Oh right, you guys program in Java or some other POOP, so you don't have destructors.

    4. Re:I read the article by BitZtream · · Score: 1

      ... congratulations, you've just showed your ignorance of Java and pretty much every other garbage collected/automatic reference counting language.

      --
      Persistent Volume manager for Kubernetes - https://github.com/dwimsey/openshift-pvmanager
    5. Re:I read the article by loufoque · · Score: 1

      On the contrary, you have.

    6. Re:I read the article by Anonymous Coward · · Score: 0

      no u!

    7. Re:I read the article by Mr+Z · · Score: 1

      Make forking exceptionally cheap, and move to a checkpoint-and-commit paradigm. Fork just before the first open(), go acquire all your resources (open(), malloc(), etc.). Depending on whether all that succeeds or part of that fails, you know which thread to kill. Kill the thread that did the open, etc. if that path failed, otherwise kill the thread that's waiting at the last checkpoint.

      If that sounds at all familiar, it should. Most modern CPUs already do this in hardware. It's called speculative execution, and they do one of these forks at nearly every branch.

    8. Re:I read the article by smellotron · · Score: 1

      garbage collected/automatic reference counting language

      In Python (ref-counted GC), the file object would be destroyed as soon as it went out of scope, which would release resources back to the OS. In the last version of Java I looked at (a while ago), it would wait until the next GC event to free the resources. That's bad, because it introduces the possibility of nondeterministic OS errors. Open too many files before the GC activates and *boom* you hit your per-process file limit, or the kernel runs out of memory and starts OOM-killing, or somesuch. Unless Java has changed, relying on a destructor ("finalizer"?) to release an OS resource is a Bad Idea.

    9. Re:I read the article by gay358 · · Score: 1

      I agree that he has far too simplictic view. In practise, error handling code should in many cases be much more complex than the code that is executed in normal cases, because errors can happen in quite many forms (and recovering from them may depend on the input) - like wrong input, out of memory, out of disk space, insufficient (file) permissions, filesystem/disk disappearing/corruption, problems in network connections, lack of some kind resources, hung transaction, user yanking usb device off etc. And these things can change during the execution of program, especially if the error condition is deliberably caused be malicious attacker - like changing file permissions, replacing files if links, renaming files etc. However, in most cases, error handling core isn't given much thought and typically it is not well tested.

      And it depends a lot on the situation, what would be the best (but probably still not completely satisfactory) way of handling the error. Should everything but error log be cleaned? Should we clean something, but leave some kind of transaction log for trying the same thing later? What if we get new error during cleaning process? Is it better to try to save as much data as possible or is it better try to erase all temporary files etc? Should we try do the operation again automatically and if so, how soon and how many times should we try to repeat it? Is it possible to use some alternative method to do the same thing? How to get error message that is as meaningfull as possible to the user -- or should we be careful not to reveal too much information about internal state of the program to possible attacker? Should we wait for user input for handling the error?

    10. Re:I read the article by gay358 · · Score: 1

      And how do you clean the files or other similar resources the killed thread has created or partially modified before getting killed?

    11. Re:I read the article by Mr+Z · · Score: 1

      That's a great question. You start to need a concept of transactions and rollback in more places. Databases already have this. Journaling filesystems already do this to an extent. (Btrfs actually COWs, so you theoretically could roll back to an older version also.)

      I'm not saying you can do this everywhere, but I think it's a strategy that can find a home many places.

    12. Re:I read the article by Anonymous Coward · · Score: 0

      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.

      O_CREAT

  47. +1 by Anonymous Coward · · Score: 0

    ..for heroic rationality !

    1. Re:+1 by Anonymous Coward · · Score: 0

      +2^1024

    2. Re:+1 by curunir · · Score: 1

      It's usually an indication of that, but not always. Experienced programmers can realize when they're actually dealing with a distinct usage scenario that just happens to be, at the moment, solved with the same block of code. Recognizing those situations and explicitly choosing not to reuse code will make your refactoring job considerably easier in the future and is most certainly an indication of a non-amateur.

      --
      "Don't blame me, I voted for Kodos!"
    3. Re:+1 by LordLimecat · · Score: 1

      I would qualify myself as an amateur-- my "programming" consists of powershell and batch most of the time, except a few times a year when I break off to use AutoIt for some more complicated stuff. Remembering my CS classes, I have always tried to throw together the core program first, and as it starts to form I start breaking things off into functions. I think I often go too far, trying to functionize things that simply arent good candidates; and others I leave things as part of the main program flow that should really be functions.

      Ive also noticed that doing either of those two things will, as you say, negatively affect any attempt to rework your code in any significant way.

    4. Re:+1 by ByteSlicer · · Score: 1

      In that case, I would create a second method with the same signature that calls the first one (plus some documentation why).

      Duplicated code should always be avoided: either split a method up so you can reuse parts, or make a private method that contains both code paths and is called by the two other methods with different parameters.

      That being said, I've had methods that looked 99% the same, but used for example one different type, making them impossible to merge/reuse (generics can't fix everything).

    5. Re:+1 by MikeBabcock · · Score: 1

      As someone who's written many thousands of lines of code for a living, I've often sat down and looked at a piece of code and realized there was a better way to divide up my classes and functions that I didn't think of initially and wonder if its worth the effort to refactor it intelligently or leave it as-is for the sake of maintenance.

      I nearly always write down those thoughts in my code though, so they can be found later. /* TODO (LAZY): yes this should be a generator and func_y() should be private */

      --
      - Michael T. Babcock (Yes, I blog)
  48. third option: callbacks by larry+bagina · · Score: 2

    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.

    --
    Do you even lift?

    These aren't the 'roids you're looking for.

    1. Re:third option: callbacks by shutdown+-p+now · · Score: 2

      That's just exceptions rewritten in continuation-passing style.

    2. Re:third option: callbacks by Anonymous Coward · · Score: 0

      Would you like to open a file, allocate memory or perform a division ... to perform some function you intend?

      No you don't. You want to register a call back. Yes, I know it. You do.

      And, you need a funny looking name as a pointer function type. You should remember that, it will save you time in the future.

      You should name your callback something sublime too. You might practice doing this; you are going to need it.

    3. Re:third option: callbacks by illtud · · Score: 1

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

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

      What is success/error here if not handling return values??

  49. Magic by cheebie · · Score: 1

    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.

  50. Lisp by Jmc23 · · Score: 2
    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.

    --
    Don't complain about syntax, grammar, or spelling. There is no.hell like input on android.
    1. Re:Lisp by chrysrobyn · · Score: 1, Flamebait

      I don't see how Lost In Stupid Parentheses needs to be brought up in a discussion on how to avoid cruft and verbose error handling. Unless you're trying to point out that academics void of any tangible goal ended up in the same place.

    2. Re:Lisp by Anonymous Coward · · Score: 0

      I could hack my C compiler to dump out the parse tree, commit it as Lisp, and impress the hell out of you. :)

    3. Re:Lisp by Jmc23 · · Score: 1
      Well, if you're stupid enough to not comprehend more than one level of grouping, stupid enough to not enable parens matching and automatic insertion in your editor, stupid enough to think the handcuffs your language puts on you is a feature, stupid enough to not realize there is no syntax to get in your way, well, then you're just to stupid to grok Lisp and it's apparent why, with your limited intelligence and vision, you cannot see how Lisp is pertinent to the discussion.

      Like I said, when programmers aren't as infantile in their mental capabilities like you, then we won't have this problem. Until then, we'll have a small group of individuals creating their own systems in lisp that just work, and the vast majority of programmers exchanging little bits of scaffolding trying to overcome the restrictions that their language of choice imposes because the language creator understood something about the vast majority of programmers :)

      --
      Don't complain about syntax, grammar, or spelling. There is no.hell like input on android.
    4. Re:Lisp by White+Flame · · Score: 1

      Yeah, I know you're just posting flamebait, but Lisp is brought up in a discussion on how to avoid cruft and verbose error handling, because it avoids cruft and verbose error handling. The macro, special variable, and condition systems collapse a lot of this since application-specific design decisions can be expressed and enforced right at the source code level.

    5. Re:Lisp by Anonymous Coward · · Score: 0

      I'm seeing an awful lot of LISPscists lately, and I have a notion of where they primarily come from: 4chan's /g/. SICP being a free book and most basement-dwellers having ASD-Asperger's it's no wonder they've grown more prominent.

    6. Re:Lisp by Anonymous Coward · · Score: 0

      Well, with Lisp->C that'd be just defining your own pretty-print function.

  51. Some meaningful options by PRMan · · Score: 1

    Programming languages should have the following built-in:

    1. Logging (like Log4Net with choices of database, file logs, e-mail, Windows Error Log, etc.). All exceptions should be logged to the chosen log path automatically.
    2. Web pages should go to an Error page, with logging and a link back to the home page. Also, they should record the yellow screen of death info like elmah automatically in the error logs, not show them to the user.
    3. Popup dialogs on applications should be more user friendly, with the programmer info going into the logs. Microsoft should work on their error messages so that they make more sense to the user. "Directory not found" should instead say, "Application Name could not find the path c:\folder\subfolder. Please ensure that this folder exists or contact the software developer." Good default error messages would save millions of hours worldwide.

    With these simple changes, the quality of software would improve substantially and the work of developers to catch errors would go down dramatically, if they were comfortable with the default handling.

    --
    Peter predicted that you would "deliberately forget" creation 2000 years ago...
  52. Bullcrap by Anonymous Coward · · Score: 1

    That Mr Steinbach must be a fucking idiot. If I encounter an error I can't handle I have to log that and stop running. RIGHT NOW.

    1. Re:Bullcrap by loufoque · · Score: 1

      No, you need to forward it so that someone with enough context will know what to do with it.

  53. Quality code is complex. Period. by msobkow · · Score: 2

    Quality code will always be "cluttered" with data validation code, result verification, and a host of other details.

    The simple fact is that computers are stupid. They have to be explicitly told what to do in every conceivable situation the code could encounter at runtime, or else the code will crash and the user will complain about it being "unusable".

    I notice that despite the article author's bitching about the situation, they had not one suggestion as to what to do instead. It's easy to bitch about life, but a lot harder to suck it up and deal.

    If exception handling and return-value checking code are "too hard" for someone to understand, they need to get the hell out of the programming industry and leave it to professionals who actually find it fun and challenging to deal with all the details. Not everyone has the mindset of a true programmer.

    --
    I do not fail; I succeed at finding out what does not work.
  54. Problem may be coupled with lack of abstraction by bAdministrator · · Score: 1

    I suggest the author has a talk with Alan C. Kay.

  55. Aspect-Oriented Programming by rumcajz · · Score: 1

    Once there was an research done in PARC about so-called "Aspect-Oriented Programming". The idea was to describe different aspects of the problem (in our case the business logic and the error handling) in different domain-specific languages, then use "compiler" to combine the two into actual executable code. As far as I know, the idea never got further beyond research stage. In any case, it's the only alternative to error codes and exceptions I've ever seen.

    1. Re:Aspect-Oriented Programming by Anonymous Coward · · Score: 0

      It has been written about in some length at Dr. Dobs of all places. ;) There should be (or at least was) an active community at least in the Java world for this.

    2. Re:Aspect-Oriented Programming by badkarmadayaccount · · Score: 1

      That is a a subset of multiple inheritance.

      --
      I know tobacco is bad for you, so I smoke weed with crack.
  56. SOLUTION: flip the premise, work as the exception by TheRealHocusLocus · · Score: 4, Funny

    All coding should proceed as if every possible exceptional condition (device not ready, cache fail, controller failure, cat dials 911 on speakerphone) is the primary and intended purpose of the Project. Hash collisions not merely covered as a contingency but pursued with vigor in the main line to the Nth degree, where N indicates the infinitesimal possibility of multiple simultaneous hash collisions that would be the likely result of a vengeful god constructing the universe such as to produce a life of continuous and foul exceptions.

    When gathered at the water cooler, coders would discuss triumphs in their particular areas of malfunction, and when they corroborate as a group it is to merge their respective threaded exceptions into a parallel paroxysm of failure, branching with virtual threads and physical coring such that the greatest possible number of malevolent conditions are met and coded for, simultaneously. Proceeding steadily towards the grail of the Grandest Failure.

    The Grandest Failure being the stuff of mere legend, yet it is what drives us. It represents that supreme and sublime moment where everything that can go wrong has gone wrong and the very fundament reeks of wrongness.

    Buffers are not starved as an exception, they are starved by design! Disk controllers are never ready. Communications packets never arrive in sequence, or so we assume because there are no markers to check, when they do arrive they are garbled beyond repair. Reconstruction occurs as a matter of course! Streams are unsynchronized by nature, incompatible by rote, unresolvable.

    Off the corridor in a dusty hallway a small team of pariahs is assembled to perform the dirtiest and most detestable task of all: to handle the exceptions and branches thrown by the main line, conditional branches sketched out briefly (whose existence is known but not mentioned in polite conversation) are pursued in secret. This is necessary work but unrewarding as it leads away from the noble purpose of Grandest Failure, towards useful work. Such stuff as consolidation, transaction handling and data ordering, forgive me for uttering, Chaos be Praised!

    For the goal is to produce a System that boldly and efficiently proceeds down the pathways of most numerous and most simultaneous failure, where the actual success of anything triggers the exceptions and is cast off to the side.

    If robustness of design becomes human sentiment, it could be said that the System confidently strides forward boldly embracing every error condition and is shocked -- horrified -- every time something goes 'right'. As life's own experience is our guide, it is seldom disappointed.

    The output of useful work in such a System the source of great embarrassment and discomfort, a necessary evil.

    That is the principle behind the control systems of the Improbability Drive. It is the driving principle of the quantum flux, Brownian motion and wave/particle paradox.

    All of this Order and Progress (blaspheme!) is but a side road off a side road ad infinitum. The main path leads to Chaos. Follow that path and revel in it. There is no honor in coding for success, any idiot could do that.

    Down deep people know this is the Way. That is why when coders meet in dim conference rooms and the slideshow laptop suddenly projects a Blue Screen of Death for all to see, there is an eruption of thunderous applause, as if one had dropped a tray of food in a crowded cafeteria. Deep down we know failure is the noble path, and success the exception.

    --
    <blink>down the rabbit hole</blink>
  57. Who cares? by Anonymous Coward · · Score: 0

    These fields (web design and development, application and database programming, mobile work, and similar fields that involve complex programming / development strategies, etc.) have very little "oversight standardization" when it comes to quoting projects, resource management, assignment of workloads by supervisors, etc. and yet, the management bodies continue to expect spot-on approximations in regards to project durations. After 60+ years, this STILL causes problems with every one of us. And what eventually happens is that if the subordinate(s) can't meet deadlines, then the subordinate is canned and replaced whereby a mix and repeat cycle ensures... This kind of crap produces a horrible employer because no matter who your weak link might be, there's ALWAYS going to be a weak link out of any pack of developers due to the simple fact that no two developers have the same skill levels AND due to the fact that management keep pushing for smaller, faster, cheaper... It's a complete mess.

    This, and the lack of job security due to no standardized approach for REAL invested employer continuity (i.e. - REAL training and not the bullshit you see during HR seminars or that crap we all occasionally go through with online courses that barely grazes the surface of topics we go experience in our jobs or stuff that deals with concepts that have no relationship with what you work on each day); this stuff takes a MUCH higher precedence concerning REFORM than some petty tangent someone came up with concerning exception handling in programming language...

  58. Define "error" by Todd+Knarr · · Score: 1

    That's the basic problem I see. For the example given of an open() call, what happens when the file doesn't exist? It could be an error, resulting in the program throwing up a message and aborting the operation. Or it could be a perfectly normal and expected occurrence, resulting in the program continuing as if it'd opened the file, immediately hit an EOF and closed the file. So with the proposed mechanism, every time I see an operation I need to jump to the bottom of the file and find it's error block to see if it's actually an error or not. That breaks a basic rule for coding: don't make the reader jump all over the place to see all of what's happening.

    Worse, the same file-not-found condition could be an error at one spot in a routine and a normal result at another. That means you not only need the error-block construct, you need an additional construct at the point of call to associate different error blocks with the different open() calls. And you haven't eliminated the jumping-all-over-the-place problem.

  59. Re:What about you, Mr. Brainiac? by mfnickster · · Score: 2

    Exactly. That was my first thought on reading this: "If there's a better way, show us. Come up with a solution. What's stopping you?"

    In reality it's not that obvious, or someone would have thought of it already. I would look at engineering practices and see how they handle failure modes. Sometimes it is better to let the thing break as long as you design it to do the least amount of harm when it does.

    It's possible to develop defect-free software as long as all factors are under your control. E.g. a program that runs on unreliable hardware can never be made reliable.

    --
    "Slow down, Cowboy! It has been 3 years, 7 months and 26 days since you last successfully posted a comment."
  60. If it's clutter, you must be doing it wrong by Anonymous Coward · · Score: 0

    have a drawback that we've become so used to we tend to see past it: Code is cluttered with error-checking routines.

    But that's precisely what functions are for: To encapsulate tedious clutter, and to give it an easily-understandable name that's simple to use at the next-higher level.

    The lowest tier of my code is just a bunch of small wrapper functions -- each one does a simple job and also checks for errors. When it finds an error, it logs it (using another function at my lowest tier), and then recovers the best it can. (Most of my programs are services in embedded systems that MUST keep running at all costs. Even horrible situations like malloc()==NULL must be handled in a way that keeps the machine running the best it can under the circumstances.)

    In general, I always try to segregate the complexity of error-checking to places where it's hidden from my eyeballs most of the time. The result isn't clutter at all. It's elegant, well-organized, and a pleasure to work with. Yes, it requires me to spend extra time writing that low-level tier of functions -- but there is no free lunch -- you gotta do that work somewhere, and burying all that complexity inside of easy-to-understand, reusable functions is a pretty nifty solution.

  61. Two Third Options by jasnw · · Score: 0

    1. Smarter users.

    2. Failing to get #1, go with (a) connect wireless-controlled shock collar to tender part of user's body, (b) toggle shock collar if any error is encountered.

    If you don't start with #1, you'll either get there eventually via a Pavlovian response to #2 or the user will stop trying. A win-win situation.

  62. catch and rethrow by roguegramma · · Score: 1

    Well in Java, there is RuntimeExceptions (meant to propagate up to the user, who can give it to support) and Exceptions.

    You can handle Exceptions you can't handle by rethrowing them as a RuntimeException. RuntimeExceptions also do not need to be declared in the function signature.

    Not that I do that often, I'm busy with PHP, where the exception handling is usually done like "Hey, you broke it!".

    --
    Hey don't blame me, IANAB
  63. Why would they bother? by NotSoHeavyD3 · · Score: 1

    I mean given how often I see code from developers not use any of this anyway ("sarcasm on" I don't have time, I just have to write perfect code "sarcasm off") I wouldn't be too encouraged to implement something new an innovative. (Since even if it was awesome they'd probably not use it.) Gee can you tell I'm a developer that too familiar with people cutting every corner they can, even if it really doesn't save them any time anyway?

    --
    Did you know 80 to 90% of the moderators on slashdot wouldn't recognize a troll even if one dragged them under a bridge.
  64. +1 by Anonymous Coward · · Score: 0

    Copy-paste programming is always a definite sign of An Amateur At Work.

  65. Doesn't matter by evil_aaronm · · Score: 1

    It doesn't matter whether we have one, two, or ten options: very few developers are conscientious enough to give a shit. Whether they're there just for a temporary job and don't care about quality, or they're trying to get back at a prick of a boss, or they just don't know or realize that they should handle unexpected results (aka. noobs!), until the language or CPU checks for us, our software is likely fucked.

    I'm still haunted by the memory of too much medical software written by too many people where they check maybe one condition and continue on - it's all good. In one case, I noticed that a function could return a failure, and we never checked for it. I added a check for it and was told to take it out because we didn't know how such a check would propagate through the decision chain and affect system operation. God help you, Siemens $productName blood analyzer users!

    Every time I write a new function, I think in terms of paranoia: "How can this fuck up, and what values should it return?" My code often focuses extensively on error conditions. I justify it this way: when you get a very specific error, you can bet it came from one of few places so it'll be easy to find and trace back in the code. If you get a generic error, good luck figuring that one out without lots of run data.

    Yes, it's sometimes cumbersome, and it adds a few extra lines to the file. So what? Use your editor to hide the error-handling block, and if you're concerned about file sizes, buy a bigger disc. Software engineering requires that you, you know, engineer the software for robustness. It should be freakin' bomb-proof . Take a little pride in your work. If you find that unappealing, please, get out of the business.

  66. Which Is GOOD by Anonymous Coward · · Score: 0

    When Windows does a bluescreen, this happens because the kernel is fucked up. It is better to crash it right now instead of corrupting even more files on your harddisk, disable vital security etc.

    A major cause of BSODs are faulty drivers. Remember which piece of crapola you added to your system in the last few days and remove that. Then the BSOD will most likely go away, too.

    Conceptually speaking, Failure Is A Necessity to achieve certain security properties. If you detect a dangerous situation the best thing is to shut down and wait for an expert to analyze the coredump/remains (whatever you call that in your system). Then the root cause can be fixed and the security guarantees can be maintained. You better want to shut your bank instead of continuing to run, despite of a known bankrobbery plan, right ?

  67. Handle them like Chuck Norris. by Mal-2 · · Score: 4, Funny

    When Chuck Norris throws an exception, it is always fatal.

    --
    How is the Riemann zeta function like Trump rallies? Both have an endless number of trivial zeros.
    1. Re:Handle them like Chuck Norris. by smellotron · · Score: 1

      When Chuck Norris throws an exception, it is always fatal.

      Can Chuck Norris please do something about the useless backtraces generated by my optimized builds?

  68. Re:What about you, Mr. Brainiac? by Anonymous Coward · · Score: 0

    you know, error handling is just a problem of expressing control flow. multiplexing the return with if/then/else at all the call sites
    is just a clumsy way of expressing that.

    in some circumstances it might be cleaner to pass a non-returning function handler either as an additional forward parameter,
    or tucked away in some state.

    that way you dont have fold all those execution paths together all the way up the return path.

    there's one. i don't know why people don't like it

  69. can we get useful errors? by fikx · · Score: 1

    I'm all for another option if it results in less cryptic error messages thrown to the user level. I don't know how many times I've had to help someone and told them don't read that error literally. what it REALLY means is this....because a single function spit out an error and was just passed up the chain until the user sees it ....
    How about a language that takes into account that errors are more common than successes and throws successes instead of errors?

    --
    AB HOC POSSUM VIDERE DOMUM TUUM
  70. change to event model by Anonymous Coward · · Score: 0

    think outside of the box of java, throw an event, think asynchronous messages.

  71. Hello??? with (python) / using (c#) by devforhire · · Score: 1

    with and using are excellent error handling mechanisms that have no clutter and clearly define the protected code. Most exception handling is little more than logging what went wrong since many exceptions really don't have solutions that can be coded for. The main thing we are trying to do in these situations is write out some data so we can debug and clean up any messes (open connections for example) we have laying around so the things don't get worse.

  72. How about the sixth option? by Anonymous Coward · · Score: 0

    The third option is to ignore it. The fourth option is to misunderstand it. And the fifth option is to try to guess the intend of the user and bypass the error.

    So I'll assume that the author's thought's, or lack of thought as he has been thinking about this for quite some time yet can not offer a single insight as to why he hasn't thought of anything is that the last option is to find a new career.

  73. Monads! by Matrix14 · · Score: 2

    Monads monads monads monads monads from Haskell.

    Or "workflows" in F#. Related to, I think, "generators" in Scala?

    Roughly (and I'm going to make up some C++/Java style syntax here), you write something like this:

    workflow someExpressionMaybeAnObject
    {
            int x = someassignment;
            some statement;
            someotherstatement;
    }

    At the end of each line, you check the return value for errors, and use the handlers defined by the object up top, which could short-circuit the rest of evaluation.

    These are actually a lot more general than error handling. For example, they generalize Python-style list comprehensions when used in a certain way.

    In Haskell-land, there's a lot of interesting math about how they work, but you don't need it for error handling.

    Moral: Learn a wider variety of languages!

    1. Re:Monads! by PurplePhase · · Score: 1

      You've got me interested... but how does it work?

      I hate to be the lazy bum, but since it is your made-up notation would you mind adding in the return value checks and pseudo-code for handler calls to allow some better understanding? Feel free to add pseudo-annotations if that helps your cause 8)

      Thank you for bringing this up! This topic has certainly engaged me more than any other on slashdot in a few months 8)

    2. Re:Monads! by DetriusXii · · Score: 1

      You've got me interested... but how does it work?

      I hate to be the lazy bum, but since it is your made-up notation would you mind adding in the return value checks and pseudo-code for handler calls to allow some better understanding? Feel free to add pseudo-annotations if that helps your cause 8)

      Thank you for bringing this up! This topic has certainly engaged me more than any other on slashdot in a few months 8)

      Here's a quick example of a monad. It's something that wraps a value where the value can be freely generic while the rest of the type is not.
      So let's use the Option monad in scala. It has two important functions called map and flatMap (map and bind in Haskell). All monads have these properties.
      If I have val a0 = Some(25); val a1 = None;
      map has a type signature of def map[Q, B](f: A => B): Option[B]
      flatMap has a type signature of def flatMap[Q, B](f: A => Option[B]): Option[B]
      a0.map((b: Int) => b + 5) would become Some(30)
      a0.map((b: Int) => b + 5).map((c: Int) => c - 10) would become Some(20)
      a1.map((b: Int) => b + 5) would become None
      a1.map((b: Int) => b + 5).map((c: Int) => c - 10) would become None
      a0.flatMap((b: Int) => Some(b + 5)) would become Some(25)
      a0.flatMap((b: Int) => Some(b + 5)).flatMap((c: Int) => Some(c - 10)) would become Some(20)
      a0.flatMap((b: Int) => None) would become None
      a0.flatMap((b: Int) => None).flatMap((c: Int) => Some(c - 10)) would become None
      a1.flatMap is always None
      There's other monads that also wrap a value. The Promise monad wraps the result of an asynchronous computation so that the maps and flatMaps are chained asynchronously. The Error monad is the useful monad. Instead of having a Java function return a value through the return type or an exception through the throws clause, both return and exception values could be returned through the return type. The error monad is most similar to the option monad, which is called the anonymous exception sometimes. But the error monad doesn't have a zero so it's not quite the same as the option monad with zero of None, or the List monad with the zero of empty list.
      Every List is a monad as it's a structure that wraps a generic value. The value just happens to be indeterminate.
      Monads are just a way to chain events sequentially without having to deal with the background implementations of the structure we're dealing with.

    3. Re:Monads! by NihilistDandy · · Score: 1

      The Haskell side chimes in!

      For convenience and clarity, I'll be specializing functions to Int. Also keep in
      mind that (.) is function composition rather than a method selector or what-
      have-you. In Haskell's Maybe monad (though strictly we're also using the applicative
      functor instance), this is

      a, b :: Maybe Int
      a = Just 25
      b = Nothing

      (+5) :: Int -> Int
      -- operator section, adds 5 to integer

      fmap (+5) :: Maybe Int -> Maybe Int
      -- fmap inspects the value inside a context, performs the computation, then
      -- returns the value wrapped in the same context

      fmap (+5) a :: Maybe Int -- Just 30, equivalent code (+5) <$> a

      subtract 10 <$> (+5) :: Int -> Int

      subtract 10 <$> (+5) <$> a :: Maybe Int -- Just 20, equivalent to fmap (subtract 10) . fmap (+5) $ a.
      -- Remember that fmap returns a value wrapped in the original context

      (+5) <$> b :: Maybe Int -- Nothing
      subtract 10 <$> (+5) <$> b :: Maybe Int -- Nothing

      Now entering the Monad instance...

      return gives a value a monadic context. In the following example,
      (return . (subtract 10)) has type Int -> Maybe Int, meaning that it takes an Int
      value, performs the computation (subtract 10), then spits out a Maybe Int
      (either Nothing or Just a value).

      Example:
      return 10 :: Maybe Int

      I'm going to have to assume that 'a0.flatMap((b: Int) => Some(b + 5)) would
      become Some(25)' is a typo. Scala tells me it should be Some(30), as does my
      understanding of Haskell.

      Just . (+5) :: Int -> Maybe Int
      (>>=) :: Maybe Int -> (Int -> Maybe Int) -> Maybe Int
      -- This is just our specialized example.

      a >>= Just . (+5) :: Maybe Int -- Just 30

      (>>=) is Haskell's `bind` operator, analogous to Scala's flatMap. It takes some
      monadic value and a function from normal values to monadic ones and then spits
      out the result wrapped in the original monadic context. If you have trouble
      reading this, (>>=) a (Just . (+5)) may be easier to read

      a >>= return . (+5) . (subtract 10) :: Maybe Int -- Just 20
      a >>= const Nothing >>= return . (subtract 10) :: Maybe Int -- Nothing
      -- const Nothing is equivalent to (\x -> Nothing) or ((b: Int) => None)

      I don't really know how to say 'a1.flatMap' in Haskell since the type checker is
      pretty strict about providing both parts. For this last one, I've made the
      assumption (correct me if I'm wrong), that Scala assumes
      'flatMap((b: Int) => None)'. This yields

      b >>= const Nothing :: Maybe Int -- Nothing

  74. try/catch is as bad as VB6 by Anonymous Coward · · Score: 0

    It's essentially "let's push forward and hope nothing breaks, and when something does, let's have some automated excepton handler handle it as an afterthought".

    Just like VB6's ON ERROR GOTO stupidity.

    It's your responsibility as a developer to properly test for error conditions and handle them in a thoughtful, logical way, instead of recklessly tearing through your code and having some trap you've set up say "oh dear, something seems to have gone wrong, let's just examine the mess we've made and try to piece together a fix, hmm?"

    Testing for error conditions as you go also make it easier to handle and properly get around problems because you're taking care of them on the spot, rather than as an afterthought.

    try/catch is an abomination that should be outlawed in programming.

  75. Sorry by Black+Parrot · · Score: 1

    Errors happen, and have to be handled. With code.

    If you have an alternative method in mind, please share the secret.

    --
    Sheesh, evil *and* a jerk. -- Jade
  76. PHP! by anyaristow · · Score: 1

    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

    So, you can write PHP in Java? Awesome!

  77. Rich Stevens' approach by dskoll · · Score: 1

    W. RIchard Stevens had a pretty good approach to error-handling in "Advanced Programming in the UNIX Environment". In most cases, he wrapped system calls or library calls in wrappers that would test for errors and abort with an error message on failure. These wrappers meant that the main program could forget about error-checking.

    In the relatively rare cases in which the main program felt it could recover from an error, it would call the system call directly and handle the error itself. This led to pretty clean but still very safe code.

    Naturally, this approach is inappropriate for authors of library code, but it's great for the main body of an application.

    1. Re:Rich Stevens' approach by QilessQi · · Score: 1

      Basically, this is equivalent to taking every library function which returns an error code, and accessing them through a Facade which throws an unchecked exception instead.

      Now assume that the Facade is the only sanctioned interface to that functionality. In the cases where the main program can do something about the error, it would wrap the invocation of the method in a try/catch.

      So, basically, we're talking about same approach, but without using exceptions (which may not have existed in C at that time, apart from setjmp/longjmp).

    2. Re:Rich Stevens' approach by Jonner · · Score: 1

      W. RIchard Stevens had a pretty good approach to error-handling in "Advanced Programming in the UNIX Environment". In most cases, he wrapped system calls or library calls in wrappers that would test for errors and abort with an error message on failure. These wrappers meant that the main program could forget about error-checking.

      In the relatively rare cases in which the main program felt it could recover from an error, it would call the system call directly and handle the error itself. This led to pretty clean but still very safe code.

      Naturally, this approach is inappropriate for authors of library code, but it's great for the main body of an application.

      That just sounds like a crippled version of the exception system in many modern languages. It'll throw exceptions but offers no way to catch them.

  78. Never make any errors by Anonymous Coward · · Score: 0

    Error handling is only needed if errors are possible. Make it impossible, using type checking and controlling the whole state space. Every function must always return _correct_ value for all parameter values. Reading files etc can never fail, but instead default to a file which is guaranteed to exists etc...

  79. It's simpler than that by AmazingRuss · · Score: 1

    Just embrace the segfault.

  80. Organization and planning by Anonymous Coward · · Score: 0

    For me it is hard imagine the use of exceptions...
    I tend to plan out failure paths and non-resource consuming compensation paths ahead of time so when something does fail you are prepared for a meaningful response.

    If you follow simple organization rules and route your shit to minimize heap allocation not only is your code more performant there are many less return codes to check, u get more options for taking action in a environment where everything except the northbridge could at some point be expected to be broke.

    For example reporting out of memory is quite a useless gesture if it requires memory allocation to send that message or reporting I/O has stalled thru that same stalled I/O channel. With a bunch of the managed and exception only languages such planning is simply impossible.

    Return codes are easy to systematically verify coverage checking with a few simple tools or even just eyeballs. With exceptions you have no idea what can throw what and very likely neither does the person who wrote it.... there is no concept of operations which inherently cannot fail unless the execution environment itself was compromised. In the land of exceptions anything could throw an exception at any time and you have no way of knowing jack diddly about these possibilities. Throw is simply a fancy alias for goto and it sucks just as hard. You are fucked if you just layed a lock, one of those land mines goes off and the higher layer decides to *handle* the exception... The necessary freqeuncy of try catch blocks to gain parity actually make return codes look appealing.

    Really these exception schemes only work at all to any degree if the environment is managed/garbage collected and even then it still fails spectacularly when managing resources other than memory.

    Users are not impressed by 5 page of meaningless stack traces while the app keeps on running pretending nothing happened.

    You can make inroads on the exception problem with the use of high level / domain specific environments.. if the system is transactional or request/response oriented user code may never have to worry about problems and the environment is expected to just do the right thing ..these things break down in the general case.. as the system lacks necessary context.

    In the end I think decoupling question of exception from the programming pardigram is a lost cause. If return codes and exceptions go away then the programming environment must be drastically different. You can only make it a better experience on the margins.

  81. boost::optional by Anonymous Coward · · Score: 0

    In C++, in addition to exceptions, boost::optional is useful:
    Boost Optional

  82. Error handling does not start at return values by Anonymous Coward · · Score: 0

    I have been coding for years, and been a mentor for a number of them also. I deal with very smart people and this is an area where less than enough time has been devoted to. Errors, exceptions, recovery and meaningful messages are not taught that much. Focus is on good algorithms and the hidden knowledge that your inputs from other programmers will be meaningful. Programming languages now are good enough, error returns ala c style are good enough. Programmers just have to be disciplined , You check inputs, range, type, length, whatever, and issue and error for things you are not expecting, which already happens for the most part, the part that is lacking is a defined interface where the the caller has a document that explains what the interface takes, and what it will return for success as well as error.

  83. who are you, and where's roman_mir? by Anonymous Coward · · Score: 0

    that comment did not once direct us to worship ron paul, nor did it tout the virtues of human slavery. clearly, you are not roman_mir, but rather an impostor who has taken over his account.

    thank you.

  84. Stateful exceptions and sub-functions by Immerman · · Score: 1

    Sounds like the author would like to have all their error-handling code nicely compartmentalized at the end of the function where it doesn't clutter the normal codepath, and I can't say I disagree, at least in many scenarios. So some techniques I'd like critiqued:

    State-based exceptions - a way to do rough exception handling when any errors are unrecoverable and you're just trying to avoid making things worse. I've never done this, but now that I think of it there may be some potential there. As basic "local clean up" example

    UpdateSomething(...){
        MyEnum state;
        try{
            state = OPENING ....
            state = PROCESSING ....
            state = SAVING ....
            return;
        }catch(...){
            switch(state)
                { .... }
            throw; // since we didn't actually fix the problem
        }
    }

    Another would be something like named catch blocks as "sub-functions", which, now that I RTFA, I think is similar to what the author was suggesting at the end. As I envision it being used as a c++ extension:

    Foo() {
        try using catch_1 (watch_1)
            { .... }
        try using catch_2 (watch_a, watch_b)
            { .... }
        return; /* it's all error-handling below this point*/
        catch_1 (watch_1, TypeA exception)
            { .... }
        catch_1 (watch_1, ...)// all other exceptions
            { .... ; throw; }
        catch_2 ( watch_a, watch_b, ...)
            { .... }
    }

    this would be functionally equivalent to the current situation, except that the code for catch statements would all be grouped after the end of the function rather than cluttering up the "all's well" codepath, and the variables accessible within the catch block would be declared up front to avoid scope obfuscation.

    In fact this syntax could be extended to allow normal functions to be used as catch handlers as well, allowing common cleanup scenarios to be shared between multiple functions without requiring redundant wrapper code like catch(a,b,exc){cleanup_function_1(a,b,exc);}

    --
    --- Most topics have many sides worth arguing, allow me to take one opposite you.
  85. Learn to code by jklovanc · · Score: 1

    The article boils down to "I can't keep track of the difference between normal execution code and error handling code therefore my solution is to put error handling code somewhere else so I don't have to look at it". The proposed "solution" just puts another layer of obfuscation into the code and can be done today with procedures. The proposal is not a step forward.

  86. Re:Mid-'70s PL/I Exception Handling is Alive & by loufoque · · Score: 1

    Were those links supposed to support your argument?
    I'm sorry but they didn't explain anything at all.

  87. The third option is... by RedHackTea · · Score: 0

    ... assertions and/or JUnit tests I would say. Then also use both exceptions and return values when and where necessary.

    In Java (and C++ I believe?), runtime exceptions do not have to be caught. So you never have to do return values and/or exception catching for null pointers, bad arguments, etc. as long as you test adequately. The problem is that no one has the time and/or is able to test every scenario adequately. Also, in Java there is the UncaughtExceptionHandler, which again I believe is also in C++ (I haven't used C++ in a few years).

    What we need is a fourth option, but we also need cars to run on water, a way to duplicate food, etc....

    I think the key is really just good logging and testing. And as long as you have a dedicated team to QA, you'll be fine in most scenarios.

    --
    The G
  88. Programming by successive approximation. by mevets · · Score: 1

    Readability, no. Maintainability, sort of.

    If an un-exceptional program is producing peculiar results, it can require considerable effort, often hours, to locate the cause of the oddity, and considerably longer to integrate the proper extensions to deal with it correctly.

    An exceptional program, however, will produce an un-caught exception. Almost mechanically, I can insert catches at various points in the program, then hone in on where the proper catch should be applied. With virtually no understanding of the underlying program, I can, uh, repair it.

    David Parnas pointed out how, in software, the efforts of a few can create need for the many. Nowhere is this more clearly evident than the rabid promotion of a fetish.

    Exceptions, value propagation, panicing and ignoring all have merits and drawbacks; their applicability depends primarily upon the situation and scope.

  89. Trying to ignore errors is the problem by Anonymous Coward · · Score: 0

    The desire to ignore errors is so strong, that seeing how they are handled is considered a fault and a distraction from what matters.

    As software becomes more complicated and more critical, focusing attention on errors, error conditions and error handling is what is required. Trying to make all this invisible is making things worse.

  90. Error is too vague by blamelager · · Score: 2

    Surely there are different sorts of errors, which would suggest different approaches for dealing with them?

    1. Programmer error. Should be uncovered during testing; where information about the point of failure and the state of the program at that point is invaluable. However, any remaining code of this sort in a final product should not bother the user with the details, but rather log them for passing back to the developer.
    2. Installer error. Sort of a mix of 3. and 4. below.
    3. System error. A problem with the state of the system (perhaps a network connection is down, or the disk is full): as with a user error, the program should do what it can to continue, and tell the user exactly what is wrong so they can do something about it.
    4. User error. The program should endeavour to continue doing the most sensible thing possible and/or tell the user what they have done, and what they should have done. A user does not want to see Exception messages.

    I guess it's pretty hard/futile to deal with most of these issues at a language level, because the appropriate course of action and channels of communication depend on the system. It strikes me that most of this stuff is something a domain-specific framework or API should be handling.

  91. Or we could just get exceptions right by betterunixthanunix · · Score: 1

    Exceptions should NOT be used for 'normal' errors

    Exceptions should be used when you have an error that only your client code can resolve; I like to use writing to a full disk as an example. An I/O routine does not know what should be done if you try to write a full disk -- maybe your program cannot continue, maybe you can ask the user to delete some files. In most of today's programming languages, your error handling choices are:

    1. Return an error. The client code now needs to know how to resume the disk operation, and it becomes needlessly complex if the error occurred in the middle of writing a long record.
    2. Throw an exception. The client code still needs to know how to resume the disk operation, and on top of that, you run the risk of a double exception fault (even in Java or Python).
    3. Set a global error flag, and hope the client checks it. The client still needs to know how to resume the operation.

    There is, however, a third option that you have in Common Lisp but which could be implemented in any language: restarts. The thrower of an exception can and should be able to set "restart points," to which the catcher of the exception can transfer control flow after the error has been corrected. Thus, if you tried to write to a disk which is full, the catcher could ask the user to delete some files, then invoke the "try again" restart; the I/O routine knows how to retry the operation.

    This requires an exception propagation mechanism that does not unwind the stack until some time after the exception is caught -- e.g. at the end of the exception handler. The exception handler's stack frame will need a pointer to the appropriate stack frame and return address for the case where no restarts are invoked (not hard), but otherwise the function call stack would be no different than it is now.

    --
    Palm trees and 8
  92. Dump the typed answer by CBravo · · Score: 1

    When using a function, the current situation is that you get an out-of-band (the exception) or normal (typed return value) answer. This is a lie when you functionally look at it from the outside: you now have two types; the exception or the predefined typed answer. In case of an exception there is some glue which will give you a GOTO (to the catch block). The exception type is sometimes abused to return one of many types of answers from a function.

    The only option is to lose the typiness (is that a word?). Some alternatives: Provide the function with handlers for certain categories of answers. Alternative 2: Use the type of answer to switch to a block of code given a certain type of answer (as exceptions are dealt with). Drawback is you can only give one return value (you might want to return multiple differently typed answers). Alternative 3: Return a type-prioritized set of answers; can be done already but is not 'best practice' at the moment. If a certain type of answer is not dealt with: return the function until it is done (a la exceptions).

    A use case I have is that we send SMS batches but some messages may fail directly. Many types of errors may come back and all should be handled differently. We now make some plumbing with 'reply-object-classes' and they suck. They have to be created, filled and read...

    Maybe combine a few possibilities. And yes: we are still in the pre-industrial area regarding software development. Everything takes expensive labour.

    --
    nosig today
  93. Relational programming by Baldrson · · Score: 1
    In relational programming, everything has more than one result possible so it naturally lends itself to exception handling where there are "unexpected" results.

    A good example is the way Horn clauses present alternatives in Prolog -- although what you really want is not Prolog but something more like XSB with tabling and incremental table maintenance.

  94. Code contracts by Anonymous Coward · · Score: 0

    .NET supports code contracts. This can make it clear to consumers of a component what input/output is excepted. Still throws exceptions (if configured to do so), but it is a step towards more clarity. Are there other languages out there supporting code contracts? I guess there must be - I've only used it in C# .NET.

  95. Re:The fourth option by Anonymous Coward · · Score: 0

    10 LET the CODE be the DOCUMENTATION
    20 LET A = A + 1
    30 IF A = 11 THEN LET A = 12
    40 IF A = 12 RETURN 2000
    50 LET A = 9
    60 RETURN 1000

  96. there is a third option by superwiz · · Score: 1

    The delayed execution is the 3rd option. Or an event model. Think of something like a make file where you don't do anything until all the pre-requisites have been satisfied. Error checking is necessary because ultimately you want to be able to have programs which can adjust to real world events (mouse motions, changing screen sizes, stuff arriving on the network wire). And in the real world thinks may not happen in the order you hope they would or in one of the orders you thought they could. Probably the most common way to handle this is publish subscribe or event model.

    --
    Any guest worker system is indistinguishable from indentured servitude.
  97. Java Solution?? by ppentz123 · · Score: 1

    Would this help? First, create unchecked exceptions to match each checked exception. Then, allow applications to somehow provide a list of checked exceptions that should be unchecked (which would carry the checked exception as a chained exception. Perhaps only checked exceptions returned by 'external' routines would be affected...

  98. If I have mod points by Anonymous Coward · · Score: 0

    then you and anybody else with that signature will be marked troll.

  99. Encapsulation fail by tepples · · Score: 1

    Don't they teach about encapsulation to you youngsters these days?

    The point is that library function A() failed to encapsulate some of the exceptions that B() can throw.

    1. Re:Encapsulation fail by turbidostato · · Score: 1

      "The point is that library function A() failed to encapsulate some of the exceptions that B() can throw."

      The problem is then, that it is badly code. Again, nothing to do with being open or closed source.

      In the end, it's quite easy: Do I know what to do with this error/exception and/or can I add some context? Then, so I do, any other case, I just rise it as is.

    2. Re:Encapsulation fail by tepples · · Score: 1

      The problem is then, that it is badly code. Again, nothing to do with being open or closed source.

      If A() were open source, a downstream user of the library could fix it to be no longer "badly code", to correctly handle the exceptions that B() throws.

  100. Two+ points by kiick · · Score: 1

    One)
    For the return value option: It is usually bad coding practice to mix error codes with information the function returns. If a function returns an int, don't stuff an errno in there when things go wrong. Separate the data from the error code. I hate it when functions that are supposed to return a pointer use NULL as the error code. NULL doesn't tell you anything, and it very well may be a valid value to return anyway. Set errno, send a signal, return a separate error code, but don't put your noise (error code) in the signal.

    Two)
    I want to see the errors. Don't hide them from me. Force me to deal with them, at least as far as generating a meaningful error message. (Meaningful!. that's a different rant.) I don't want the hardware, OS, compiler, library or whatever to take away from me the ability to see -- and handle -- the error myself. Feel free to offer me some boilerplate error code, but don't force me to use it. Half of elegant programming is in the error handling. If you think about it, a program seems "smart" when it handles error conditions well, instead of just crashing or quitting.

    And the plus:
    It seems to me what the guy is complaining about is the aethestics of the code, not the actual error handling. Wouldn't a folding editor help with that? You just mark the error handling code and let the editor collapse it for you, until the time comes when you need to see it (and it will). Problem solved.

  101. Time to do it right vs. time to do it over by tepples · · Score: 1

    This is why we have testing.

    Reading and understanding the manual and getting something right at the design stage takes less time than reimplementing it and retesting it after receiving feedback that the the initial private test has failed. And when private testing takes less time, you get to release the product to the public sooner and collect revenue sooner.

    The only people who do it any other way are writing mission critical code that costs a fortune to develop. You know what? You're fired.

    It appears you don't think your company's key product is critical to the mission of your company, sir. In that case, you can't fire me because I quit.

    1. Re:Time to do it right vs. time to do it over by Bengie · · Score: 1

      What about the case where you allow the end user to use any library that implements a given interface? What if the implementation of that interface has custom errors that could not be known at design time?

    2. Re:Time to do it right vs. time to do it over by Grishnakh · · Score: 1

      You really think some manager is going to allot time for developers to read tons of documentation up-front? That's insane. You may be right about getting something right at the design stage taking less time than reimplementing and retesting, but that's irrelevant, because that's not how management thinks. They want something out the door fast, even if it's full of bugs, because customers will happily accept that and their lame promises of "it'll be fixed in the next release".

  102. I don't like error handling -- Lazy programmer by upuv · · Score: 1

    Sorry,

    You only want to work in success state? The mark a of a truly good or great programmer is that the understand that faults happen and that they have to be dealt with. A great programmer makes this look simple and elegant.

    An absolutely horrible programmer wants to hide this handling and do as little as possible with it. These programmers are also the ones that tend to somehow find a way to incorporate some new cool library or frame work into the code for no reason what so ever.

    Unfortunately Agile is development models are inadvertently promoting this bad practice as people start to fee a need to bang out as many user stories as possible. Lots of shops create stories biased towards the success especially when stories are mostly penned by the business.

    I call this problem. The success path code fallacy. The amount of code debt that results is huge.

    Learn how to deal with errors early and efficiently so that you don't have to deal with them in unrelated bits of code where the amount of effort to deal with them is much much more. Then the amount of work you have to do with error checking will drop.

  103. Exceptions, but no return codes by Horshu · · Score: 1

    The problem with return codes, IMO, is that the operating system/runtime natively use exceptions, so when you *attempt* to convert code to using error codes, you have a false sense of security that your app won't crash due to thinking you're not using exceptions. I've run into this a couple of times: the architect thinks his/her app is rock-solid (in terms of crashing) but the fact is, you cannot escape exceptions. You may not throw exceptions, but your runtime does, and as a result, your code doesn't use try-catch anywhere. Then you get an exception you don't expect (i.e. a system exception, such as NullReference), and guess what? Your app crashes. Or even worse, you wind up putting a catch (Exception) {} into your code thinking you'll just convert your error into an error code, but you end up losing the true nature of the error as you convert your context-specific exception into a general "ActionFailed" error code. This kind of error winds up being a pain in the ass to diagnose, as you have to backtrack in your code to find where your error information got lost during the conversion.

  104. The problem has nothing to do with the coding by m.dillon · · Score: 1

    And everything to do with the fact that error paths are rarely actually TESTED by the programmer, so if the program is complex enough the likelihood that an error condition will be handled properly rapidly drops to near zero.

    The problem is thus really that of not being able to easily test that the error paths actually do the right thing.

    -Matt

  105. There is a fix - and it's more important than how by Anonymous Coward · · Score: 0

    Make sure that EVERY error can be forced programatically and test all the error paths.

    I can hear the screams of rage from here, but it's like backups, unless you test the restore process it may as well cp * /dev/nul.

    Same thing with errors, unless you can test what happened when the error occurs you may as well not have error handling.

    It's amazing the cruft that gets shaken out if you enforce this - particularly the "by the time the error gets printed the message is meaningless" ones.

  106. You are all wrong. Error handling is evil by ComradeMauser · · Score: 0

    Error handling built into the code is a fine way of creating thoroughly tested and fine tuned collection of spagettified bugs. Up to the final pre-delivery stages, the code should have no exception handling at all. This way, when sh!t happens, you don't have the luxury of deciding "this sh!t is unimportant, I will deal with it later". Since every bug blocks your progress, you have no choice but to find a root cause of every failure and fix it. Have somebody build a small circuit controlling a red beacon and a siren attached to the integration server and make it go off every time an automated unit test fails after a commit. Create an attitude where people are ashamed of setting off the integration failure alarm. That is the only way of getting somewhere close to a bug-free code that I know of.

  107. Re:The fourth option by SplashMyBandit · · Score: 1

    This is a fallacy. The code shows how the problem is solved. The documentation describes the intent of the program - this is not the same thing. If the code is wrong the documentation describing the intent allows you to pick up the inconsistency, and what should actually be happening.

    Yes, the documentation can also be wrong, and needs to be maintained as much as code and program data. It is part of our jobs to keep all the resources accurate and useful, including the documented *intent*. Anyone who says different is a lousy developer (most probably because they mistake the purpose of documentation, so under value it - or have never been given great documentation that saved them oodles of time).

  108. Bertrand Meyer had a Sane Approach (Maybe) by Anonymous Coward · · Score: 0

    I think he said that if a method uses a shared or outside resource and the method fails because the resource fails, then the method should send a return code. If a method might fail because the particular inputs are ill-conditioned, the programmer ought to code a method to check for the error condition before the method is invoked, and it is then the responsibility of the caller to use the pre-check to never make a call that will fail. This style worked OK in the old days, but nowadays just about everything depends on shared resources -- a database or network connection, a file system, or memory managed by the OS. So we are back to return code hell, because everyone has to send them.

    Meyer's bottom line, however, is an interesting one. Exception handlers as as bug catchers don't really make much sense in production code. If you need to catch a bug, your program is wrong. Catching a error and patching things up on the fly so that no one notices is a pathological way to make wrong right.

  109. Re:"aeronautical software specifications" by Anonymous Coward · · Score: 0

    Can you point me/us to good descriptions and/or discussions on this approach?

  110. Allow me to assist you by Zero__Kelvin · · Score: 0

    "But I still don't understand the problem ... Go to msdn, "

    There's the problem.

    --
    Guns don't kill people; Physics kills people! - John Lithgow as Dick Solomon on Third Rock From The Sun
  111. Exception design by andrewgilmartin · · Score: 1

    A common problem is that few development organizations take as much care in the design of their error handling as they do in the functional handling. Without this care, one result is that method signatures have too many caught exception declarations. This leads to poor exception handling in the caller and so on up the call stack. A good exception design -- for example Spring's -- leads to very few exception declarations on the method. I think that Spring's next step of hiding the exceptions is a mistake, but their code is far more used than mine so who am I to argue!

  112. Close, but no cigar ... by Zero__Kelvin · · Score: 1

    "(config file not found? Use sane defaults and save them for next time!)"

    Absolutely not. Maybe there is a config file, and you just can't find it because it is somewhere else. Let the user know you can't find it and then offer a choice of browsing to the file or doing what you said. Nothing would be more confusing than thinking your config file is being read when in fact the software does what you said behind the scene instead. "Shit! No matter what option I change in the config file the damn thing just won't work!

    --
    Guns don't kill people; Physics kills people! - John Lithgow as Dick Solomon on Third Rock From The Sun
  113. To error or not to error. by rew · · Score: 2

    The fundamental problem is that sometimes an error is an error to the calling program, but sometimes it is not.

    For example, when you issue: open "$HOME/.myconfig", the inability to find the file does not mean there is an error. Just that the optional config file is not there. But when you try to open the source file for an operation, the open-error really IS an error.

    This duality happens at most levels. A library wrapping "open" will have the same problem. Does the caller consider this a fatal error or not?

    Similarly, sometimes errors should result in telling the user and then quitting. But for a gui application it's better to show a graphical message and continue, even if the error is more or less "fatal".....

  114. Unreliable hardware by handy_vandal · · Score: 2

    Mod parent up, I'm in complete agreement: "If there's a better way, show us. Come up with a solution. What's stopping you?" And indeed it's not obvious, or we would already have the solution.

    I'm not sure I agree that it's possible to develop defect-free software. All hardware is unreliable. Mean time between failure.

    Perfect software may be perfect in our minds; but software immediately degrades when implemented as machinery.

    Perhaps the original poster is frustrated by the perfection in our minds failing to overcome the limitations of physical reality ... much as we all wish to live forever, even though we know that's not going to happen.

    --
    -kgj
    1. Re:Unreliable hardware by mfnickster · · Score: 1

      I'm not sure I agree that it's possible to develop defect-free software. All hardware is unreliable. Mean time between failure.

      Just to clarify, "defect-free" doesn't mean the software will always run correctly under any conditions regardless of hardware state. It just means that *given* the integrity of the hardware, the software will not have any uncontrolled failure modes.

      --
      "Slow down, Cowboy! It has been 3 years, 7 months and 26 days since you last successfully posted a comment."
  115. Re:SOLUTION: flip the premise, work as the excepti by PurplePhase · · Score: 1

    Somebody please mod parent up to 11, and give them a knighthood, a late night television show, and a comedy nobel prize!

    This needs to be read by so very many people!

  116. What A Load Of Bull by Anonymous Coward · · Score: 0

    You are seriously suggesting to install another whole package if your client is improperly configured ?? I suggest you quit any engineering activity if that was meant non-ironical.

    Your mindset might be OK in the world of toy computing (read: Windows), but certainly not in the datacenter. Proper failure with proper error message is exactly what is required to built a robust solution. If I enter crap into a program it is supposed to properly complain, not to try an insane heuristic which will in 99% of cases do something I did not want it to do.

    We can discuss all day what constitutes a proper error message (Windows gets it wrong half the time, see the event log), but there is not the slightest doubt we need them.

    1. Re:What A Load Of Bull by Your.Master · · Score: 1

      No, he's not seriously suggesting that. You just failed the Turing Test.

  117. Java/C# Standard Library Is by Anonymous Coward · · Score: 0

    ..bullcrap. Both SUN and to a lesser degree M$ never got a real handle on this huge boatload of code in the "standard" libs. Compare that to the POSIX API, where we have more or less 100% bug-free implementations.

    If SUN had focused on providing a small, complete and orthogonal library with equivalent functionality as the POSIX API, I do think they would have been much more successful. Instead they loaded a large codebase on their shoulders and promptly sunk into a morass of bugs. In the end, it was just too much for their engineering resources.

    In most cases, doing less is better than doing more, because you can focus on getting the smaller thing RIGHT. But hell, yeah, the software engineering profession is by now infested by all sorts of amateurs who have seen their "management talent" asking "Ohhh, does it also have an API for cooking coffee and one for booking meeting rooms ? I will only buy it if your language can do that !!!". As they are eager to please the management crappers and become crappers themselves one day, they are fascinated by the "comfort" functions of the Java/C# standard library.

    All they get in reality is fast food. Tasty at first, feeling like a load of lead afterwards.

  118. use unchecked exceptions & declare them in thr by Anonymous Coward · · Score: 0

    subj.

  119. use both exceptions and return values by PJ6 · · Score: 1

    This isn't an either-or / where's-the-third option question - exceptions and return values just need to be used for what they're best suited.

    Use exceptions for error conditions that can be generalized, i.e., they need no more information than this for a domain-specific (client/service/DAL) Policy to decide what to do.

    1. Is it a genuine error, or a stopping condition encountered in normal operation?
    2. Does it contain a message intended for the end-user to see?
    3. Should it be logged?

    No need for try/catch blocks everywhere for this since you've generalized it.

    Error conditions that can't or shouldn't be integrated into a generalized exception-handling policy... these should relay information through function return values as part of an application's business process, not through exceptions.

    It's not complicated.

  120. Wrong Problem, Wrong Tool. by Requiem18th · · Score: 1

    What this guy is complaining about is that Error Handling code must reside at some point along the code that may encounter an error. He specifically mentions that he'd like to put all error handling in another file.

    What he really wants is a tool for organizing code blocks in a more logical way.

    What this guy wanta is something like the Leo editor. Of course Leo is not the only player in it's cathegory, see Outliners.

    Now for the most interesting problem, singaling abnormal return conditions. Exceptions trully are the right contruct, specially for any code that is intended to be used in a larger program. Exceptions do the right thing and they do it better.

    Code examples. For example, all these snippets of pseudocode are functionally the same:

    # using out parameters
      code = functionCall(argument1, argument2, OUT PARAMETER value)
      if code != SUCCESS_CONST
        return code
      else
        doSomething(value)
    # using ad hoc structures
      returnHandler = functionCall(argument1, argument2)
      if not returnHandler.success
        return returnHandler.errorCode
      else
        doSomething(returnHandler.value)
    # using a resource object, basically same as above, but with more functions in the name space
      resource = functionCall(argument1, argument2)
      if not library_successTest(resource)
        return library_getError(resource)
      else
        doSomething(library_getValue(resource))
    # using exceptions
        doSomething(functionCall(argument1, argument2))

    Yes, the last example is exception oriented code. No Try/Catch needed. Must exception oriented code include a stupid amount of superfluous try/catch. The first idea is that code that doesn't handle errors shouldn't care about errors. in this example `doSomething` doesn't do anything with the error values of functionCall so why should it take so much effort to feed the return of functionCall to doSomething or bail?

    If you argument is that the calling code shouldn't return an error and should handle the error; think about it. Whatever the parent intended to do has failed, so the parent still has to handle the error but now it doesn't have any information about what went wrong. Unless of course, you intend the caller to fix everything, in which case you live in a perfect world where errors don't occur. Or, you intend functions to handle errors for their all their calling parents which is insane.

    --
    But... the future refused to change.
  121. I assert() by niftymitch · · Score: 1

    I assert()....
    The exception handler needs an exception handler...
    Remember it is turtles all the way down.

    --
    Truth is stranger than fiction, but it is because Fiction is obliged to stick to possibilities; Truth isn't. Mark Twain.
  122. I Hate this with a Passion! by Anonymous Coward · · Score: 0

    Ever seen this?

    try
    {
              "some code"
    }
    catch
    {
    }

    A programmer should be fired for this. Basically, the programmer is 'hiding' a fault because he/she does not know how to deal with it.
    This has been one of the worst programming constructs imaginable and don't say, "well so and so recommend we do it this". B#@@$$!~
    I simply means that either they were too lazy to figure it out or did not give a d@$# about figuring it out or could not figure it out. Either way, it's a ticking time bomb in the code and will eventually cause problems down the road. This construct should be completely eliminated from exception handling by the compiler. i.e. Putting in an empty one should gen a compiler error such as 'Exception handling not defined.' And don't give me that BS about programmers choice. That's like saying let's go back to managing our own memory instead of using a garbage collector. The extremely few instances where one might justify something like this can be easily worked around so nobody should ever give the excuse that they had to do it this way.
    I've been writing code for over 35 years and I have never had to implement this and, I never will.

  123. When it's done by tepples · · Score: 1

    There's a reason Valve is liked for releasing things when they're ready. People liked the same thing about Blizzard until Blizzard went apedung about maintaining its monopoly on matchmaking servers for its video games (the bnetd case).

    1. Re:When it's done by Grishnakh · · Score: 1

      That might work for a small minority of workplaces, but it's not the norm by any means. How many companies actually care about customers and their opinions anyway? Most companies only care about the next quarter's financials, and releasing crap long before it's ready, filled with bugs, is a good way of pumping up your short-term financials. By the time the company's bad reputation catches up with it, it's some other CEO's problem.

  124. Biggest epic fail with Exceptions by TheSkepticalOptimist · · Score: 1

    If you have ever thrown an exception to indicate a success condition, you fail.

    This is just plain wrong because if another developer ever implements an interface without a try...catch, you just caused the application to crash because of successful operation.

    My experience with Exceptions, and API's that are full of them, is that the developers are pretty much saying they don't know what the hell is going on, so TRY everything and respond accordingly. There is this thing called Unit Testing, which means you build tests for both success and failing conditions for an interface and ensure the application will not crash and recover for failing conditions. An app should always succeed, so constantly trying interface calls is overhead. I only TRY calls to external API's because I cannot clearly know they will succeed, I didn't build unit testing in 3rd party tools therefore I don't trust them.

    I mean, what the fuck does Exception stand for? Its an Exception to the known state of an app. If you throw for ALL known states including success, you fail.

    --
    I haven't thought of anything clever to put here, but then again most of you haven't either.
  125. Defect-free by handy_vandal · · Score: 1

    Thanks for the clarification. The nit I picked was out of scope, given the understanding that defect-free software assumes the integrity of the hardware.

    --
    -kgj
  126. Re:The turd option by Hognoxious · · Score: 1

    Pasting the entire block of code that was used earlier seems to break a number of (good) programming conventions, like, i dont know, never using copy / paste coding methods.

    That's why they invented goto.

    --
    Confucius say, "Find worm in apple - bad. Find half a worm - worse."