> I want errors as values, *without* having to check the result of every function call.
I have found that in practice the moment one wants to add more context to errors the good old return flags to indicate unexpected return status results in least cluttered code.
For example, in Java stack traces in log files by themselves can be rather useless for problem diagnostics. To facilitate the analyzes it is often necessary to log state information from quite a few call sites. But in Java that results is rather ugly
With return error codes the extra clutter is minimal - one just needs to add log_extra_error_state(); on the error path.
Now, I presume in Haskell such annotated error reports should be rather simple to implement using Either. But even in Haskell checking for errors after return is inevitable if one wants to add the context information only on error paths.
Posted Oct 27, 2012 6:42 UTC (Sat) by Cyberax (✭ supporter ✭, #52523)
[Link]
Yeah, sure. So with error code you basically get:
> 42. Program failed. Now try to find out why, mwahahah!
In Java you can _rethrow_ exceptions, without losing the cause. I.e.:
> catch(SomeException ex)
> {
> throw new MyException(log_state(), ex); //We DO NOT lose the cause
> }
No thanks.
Posted Oct 27, 2012 8:30 UTC (Sat) by ibukanov (subscriber, #3942)
[Link]
> Yeah, sure. So with error code you basically get:
> 42. Program failed. Now try to find out why, mwahahah!
No - with consistent error logging one gets in C very useful stack-like information about the error state without the noise of deep Java stack trace.
Clearly in Java one can do the same and have a stack trace in addition, but even in C it is possible to get the stack trace. Yet the C solution brings less clutter to the server code where it is desirable to log on errors (and only on errors) the maximum information about the state.
RuntimeException ftw
Posted Oct 27, 2012 10:41 UTC (Sat) by man_ls (subscriber, #15091)
[Link]
With well coded programs a stack trace is all that is needed 99% of the time, or at least that is my experience. You can save the bit about "consistent error logging" and still spot errors.
There are weird occasions where e.g. the Android platform eats up your stack trace and generates its own, but that is not usually the case.
As to checked exceptions, they look good but in practice lead to byzantine exception hierarchies and hyper-delicate error handling, not well suited for humans (or for teams). Unchecked exceptions are good in that you don't need to handle all possible situations. In a web application you can just catch them at the root level, log them and print an HTTP 500 page; the user is not going to care at the moment as to why you are not showing the info they want, and the admins get a nice stack trace -- see above.
RuntimeException ftw
Posted Oct 28, 2012 0:09 UTC (Sun) by cmccabe (guest, #60281)
[Link]
Go has exceptions, it just calls them "panics" and doesn't make an attempt to give them elaborate type hierarchies. So if your program does something _really_ bad, it will abort with a stack trace.
As far as spewing stack traces for normal errors-- people who want this are not thinking clearly. Unless you are a developer, you shouldn't need to read stack traces.
It's really nice to have stack traces in the language-- lack of them in the language is awkward in C/C++, although there are libraries that can help a lot.
RuntimeException ftw
Posted Oct 28, 2012 8:48 UTC (Sun) by man_ls (subscriber, #15091)
[Link]
Unless you are a developer, you shouldn't need to read stack traces.
Absolutely true, I did not want to imply that the stack trace is shown to the user. The server displays a regular, nice 500 page (with no mention of "HTTP 500" either); but the stack trace is stored in the logs for further analysis.
Exceptions are good also to return from APIs, as long as they are documented: they come out in tests, are easy to spot and understand, and easy to deal with.
RuntimeException ftw
Posted Oct 29, 2012 18:31 UTC (Mon) by cmccabe (guest, #60281)
[Link]
I disagree that exceptions should be returned from APIs (shouldn't that be "thrown"?) The caller shouldn't have to understand the internal implementation of your library to use it. A null pointer exception 10 levels deep in library code is not a friendly API, even for programmers.
If you can fail, document how you can fail, and come up with return codes or another API to handle it cleanly. If you can't fail, then return void and be done with it.
Checked exceptions were an attempt to make exceptions "work like return codes." But it failed. Every method in the world ends up throwing IOException, and it basically functions exactly like unchecked exceptions.
RuntimeException ftw
Posted Oct 29, 2012 18:50 UTC (Mon) by man_ls (subscriber, #15091)
[Link]
Sorry, I meant "Exceptions are good also to throw from APIs, as long as they are documented".
But throwing a NullPointerException is not what I said; that is obviously a bad idea in any case. Just declare an unchecked exception for every failure condition (with an umbrella super-exception) and document them. That way you can throw them from any point in your code. This is not different from your description: "document how you can fail, and come up with return codes or another API to handle it cleanly". Unchecked exceptions are a wonderful way to handle failures cleanly; in effect these exceptions become another part of your API.
IMHO, avoid checked exceptions like the plague because they become, without exception, a mess. In a recent Android app I thought I could get off with a checked exception for offline mode to force implementors to deal with it, but in the end I had to change it back to unchecked.
No thanks.
Posted Oct 27, 2012 17:37 UTC (Sat) by Cyberax (✭ supporter ✭, #52523)
[Link]
Yeah, sure. So now you're proposing to do LOGGING from basically every level of stack. And where are you going to log things? If you say 'stderr' then I'm going to come and burn down your house.