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

387 of 536 comments (clear)

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

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

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

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

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

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

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

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

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

    13. 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
    14. 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
    15. 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)

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

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

    19. 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
    20. 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.
    21. 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.

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

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

    25. 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.
    26. Re:The third option by Nerdfest · · Score: 1

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

    27. 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.
    28. 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.
    29. 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.
    30. 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.
    31. 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.
    32. 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.
    33. 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.

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

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

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

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

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

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

    43. 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
    44. 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
    45. Re:The third option by SuperTechnoNerd · · Score: 1

      Panic and catch fire.

    46. 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.
    47. Re:The third option by loufoque · · Score: 1

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

    48. 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()

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

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

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

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

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

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

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

    59. 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!
    60. 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
    61. 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.

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

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

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

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

    68. 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.
    69. 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?

    70. 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.
    71. 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.
    72. 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]
    73. 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

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

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

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

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

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

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

      Of course - Java isn't perfect either.

      You don't say!

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

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

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

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

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

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

    87. 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 :)

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

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

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

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

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

    93. 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) :)

    94. 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?).

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

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

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

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

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

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

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

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

    102. 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)
    103. 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)
    104. 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)
    105. 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)
    106. 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!
    107. 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."
    108. 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."
    109. 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. 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 Osgeld · · Score: 2

      then usually fails

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

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

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

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

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

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

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

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

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

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

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

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

    13. 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 :(

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

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

    16. 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.
    17. 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.
    18. 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.
    19. Re:People just doesn't get it by loufoque · · Score: 1

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

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

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

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

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

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

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

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

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

    29. 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
    30. 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 ).

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    47. 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)
    48. 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)
    49. 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)
    50. 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!
  5. 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 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.
    5. 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
    6. 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.

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

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

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

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

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

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

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

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

    5. 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)
  7. 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+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.
    3. 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.

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

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

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

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

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

    3. 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
    4. 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'!"
  10. 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 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.)

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

  12. 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
  13. 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 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) {

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

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

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

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

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

  18. 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'!"
  19. 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.

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

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

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

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

  25. 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.
  26. 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".'
  27. 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.
  28. 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".

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

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

    3. Re:error handling in functions by Khashishi · · Score: 1

      That works fine with floating point, but integers don't have an NaN.

    4. Re:error handling in functions by Mr+Z · · Score: 1

      Are zeta or geommean even remotely useful on ints?

  31. 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 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
    4. 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
  32. Haskell Error Monad Transformer by Anonymous Coward · · Score: 1

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

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

  34. Re:Errors by Smallpond · · Score: 1, Insightful

    All code is just assembly language in other clothing.

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

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

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

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

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

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

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

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

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

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

  42. 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.
  43. Re:Try-Catch blocks should not exist... by Waffle+Iron · · Score: 1

    Yoda agrees: "Do or do not. There is no try."

  44. Problem may be coupled with lack of abstraction by bAdministrator · · Score: 1

    I suggest the author has a talk with Alan C. Kay.

  45. 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 badkarmadayaccount · · Score: 1

      That is a a subset of multiple inheritance.

      --
      I know tobacco is bad for you, so I smoke weed with crack.
  46. 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>
  47. 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.

  48. 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."
  49. 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.

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

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

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

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

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

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

  59. 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
  60. 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!

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

  62. It's simpler than that by AmazingRuss · · Score: 1

    Just embrace the segfault.

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

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

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

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

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

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

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

  71. 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
  72. 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
  73. 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.

  74. 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.
  75. 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
  76. 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...

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

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

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

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

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

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

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

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

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

  87. 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!"
  88. 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.

  89. 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'!"
  90. 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!

  91. 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
  92. 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".....

  93. 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."
  94. 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!

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

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

  97. 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.
  98. 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.
  99. 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.

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

  101. 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.
  102. Re:What A Load Of Bull by Your.Master · · Score: 1

    No, he's not seriously suggesting that. You just failed the Turing Test.

  103. 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)
  104. 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
  105. 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."