5 ms·
> when we had to check the return/value and or the error code after every function call... if we wanted error handling to work. Errors as return values force y
by gizmo 15y ago
> when we had to check the return/value and or the error code after every function call... if we wanted error handling to work.
Errors as return values force you to think about every possible error, which is a good thing for code quality. Look at how much rock stable C software we have out there. Software that can be compiled on many different architectures, run in many different environments, and it all just works, even 20 years later.
Writing code with try/catch is much less work. Not because you have to do less typing, but because you simply think less about how errors should be handled.
- PaulHoule 15y agoIn a modern programming environment you can't think about every possible error. In particular, code often migrates into distributed systems where a whole new range of problems can happen. For instance, a system might have plug-ins that get data from a CSV file, a relational database and a web service. One day somebody comes along and adds a plug-in that gets data from a noSQL database. Add a new component to the system and you introduce not only new failure modes but new ways failure impacts the "system a s a whole." The more decisions you make, the more you will make wrong decisions. Exceptions provide a reasonable default behavior that is "decision free" and reasonable ways to upgrade it. 20 year old C software lived in a simpler world; only specialized network utilities like telnet and tcpwrappers would have to face the consequences of a failing DNS lookup or the temporarily failure of a network switch in Toledo.
- sparky 15y agoIt is a more complex world, but I think that's orthogonal to whether you prefer return codes or exceptions. In fact, I think you can argue that keeping error-handling local to the call site (return codes) encapsulates and abstracts the errors better than letting an exception propagate arbitrarily far up the stack. Exceptions are decision-free, but not making a decision (propagating an exception without handling it) doesn't make you any more robust to the vagaries of the modern world, it just moves the problem somewhere else. Now, if multiple children in a call graph can experience the same error, and should be dealt with in exactly the same way, then propagating an exception up to a common ancestor in the call graph makes your code simpler. The fact that the compiler writes that dumb plumbing code for you is a great argument for exceptions, but not all applications fit the use case of: * Same error can manifest itself in many places * Each instance of the error can be dealt with in a similar-enough way to make a common exception handler simpler than handling errors at each call site. Edit: Oh, did you mean that if you don't intend to handle an error, exceptions crash your program (good) rather than let it continue silently and do something you don't expect (bad)? If so, good point, and my apologies for the misunderstanding :)
- ufo 15y agoAt least in languages like Haskell you can use things like Monads that allow you to write the high level code and do the error routing for you behind the scenes. In C manually writing the error handling is a painful and error prone process.
- eftpotrm 15y agoAnd you know what? In my experience it's not less robust. So my code hasn't had every possible failure case thought through and explicitly handled in advance. That's good. Firstly some of those errors are so rare they'll almost certainly never occur in my program's lifetime; by not having to handle them explicitly and individually I save time and money. Secondly I can guarantee that, no matter how good I think I am, the program will eventually find a way of crashing I'd not considered; this approach gives me a clean means of handling unforeseen errors as well. A bad programmer can write bad code in any pattern and with any tools. A bad C programmer using return values can create so many different standards for how to handle errors that you might as well get out the divining rods to read the code. Personally, done right (as with anything) I happen to like try...catch.
- dasil003 15y agoJust because you think a certain error will never happen for the lifetime of a program doesn't mean that not explicitly handling it is equally robust.
- eftpotrm 15y agoNo, I agree, but there's a cost/benefit calculation to be done. Plus it's not like the try...catch solution that doesn't explicitly handle the error will blow up and destroy everything; if the program is properly designed it should merely degrade onto the path of general handling, log the failure and halt whatever was being done.
- TylerE 15y ago> Look at how much rock stable C software we have out there. Which would be what exactly. The work of Knuth and djb I'll grant you, but the rest?
- vog 15y ago*BSD kernels, GCC, tar, gzip, ...
- TylerE 15y agoBSD kernels have had numerous exploits over the years. GCC is a massive hairball. gzip has had exploits (http://www.kb.cert.org/vuls/id/381508 http://www.kb.cert.org/vuls/id/381508 for one). Care to try again?
- andrewflnr 15y agoWithout defending any given piece of software, the job of the exception advocate is not to prove that return values suck, but that using exceptions produces more stable software as fast or faster. This question cannot be resolved by examples/anecdotes alone.
- william42 15y agoDidn't Knuth write TeX in a variant of Pascal?
- viraptor 15y agoI'm sorry, but this is a very bad example. iptables had an issue for a long time where error code is not carefully preserved in many situations and you end up with messages like: iptables: Unknown error 4294967295 This wouldn't happen with exceptions - even if not handled properly, you'd see where is it originating and what's the most probable cause of the issue. And it's not necessarily iptable's fault - in some cases you have to really bend some rules to get the error you want. Also you cannot stack them so if you fail to cleanup after the original error, what do you return? The first or the second error? One has to be ignored.
- angelbob 15y agoReturn the first one. You always care more about the original error than an explanation of why you failed in cleaning up after it.
- viraptor 15y agoCounterexample: you failed parsing some number correctly, but the backend where you log broken transactions is corrupted and cannot be written to. You'd rather drop the second information?
- angelbob 15y agoAh, so you're saying that failing to parse the number breaks the transaction. Fair enough, you'd rather (as a human being) have the second one. As a matter of building the system, I would still return the first one. Basically, the second information is important in the sense that you really want an audit trail, but unimportant in that it doesn't tell you why your call failed. Returning it to the caller is useless compared to returning the first error. But yes, it should certainly be logged and potentially acted on. An application can't do anything useful with the information, but an ops guy can. So return the first one.
- lemming 15y agoThis is not my experience at all. Return codes are far too easy to ignore. I would argue that the fact that C software works after 20 years is because it's been debugged for 20 years, everything that can possibly happen to it has probably happened and been handled. It's not because error return codes are a fundamentally better way to do this. I know it's kind of unhip right now, but I would argue that what you're asking for is better handled using checked exceptions. That really forces you to think about error conditions, and it's enforced by the language. I'm continuously baffled by the argument that this is a bad idea.