Live data from Hacker News

You’re better off using Exceptions

eiriktsarpalis.wordpress.com

221–230 of 242 posts

Re: You’re better off using Exceptions

#221

Earlier quoted context omitted.

Technically in Java it is possible to create an exception object once, and throw it multiple times, making throws much cheaper as the stack trace is filled during the object's construction only.

Does this actually save much time? I thought it was the throw mechanic that was slow, rather than just creating the exception?

According my unscientific tests, it is about over 100 times faster. On my laptop I can throw one million exceptions in 15ms millisecond, when reusing the same exception objects, compared to 2 seconds when creating a new exception object every time with a quite shallow stack.

When a new exception object is created, the slowest operation is filling information about the stack trace. It is possible to override Exception's fillInStackTrace() with an empty implementation. In this case throwing exceptions with new exception objects, is only slightly slower than using one exception object (17ms vs 15ms for 1M throws).

Deeper stacks make difference even bigger. Adding 100 nested invocations to the stack slow downs the classic approach (a new exception object created just before invocation) to 9 seconds, while alternative approaches are not affected.

Re: You’re better off using Exceptions

#222
post #70

Earlier quoted context omitted.

The problem is that these systems are built in a way in which the data access latter is throwing the exception even though it can’t reasonably know if the record is expected to exist or not. It can’t or shouldn’t know that this is an invalid program state. Specifically, if exceptions are being used properly, you should almost never need to use try/catch.

Those are poorly designed APIs then. That is like having a dictionary that throws when a key isn't found but doesn't have an API for determining if a key exists or not.

It’s a poorly designed API, full stop. It doesn’t matter whether or not it has an API to check existence, it’s not the dictionary’s job to know whether or not a missing key is a valid state in the broader program, and most often it is. Moreover, it’s insane to do a separate “if exists” check every time you need some resource. And the world is littered with these poorly designed APIs, as they are idiomatic in Python, JS, C#, and Java.

Re: You’re better off using Exceptions

#223
post #43

Earlier quoted context omitted.

> That just depends on the paradigms of the language you use, anyone can add sugar to make either easier/harder to read. The questionmark operator, in particular, is what sold me on the possibility that this type of programming can be concise and ergonomic. https://doc.rust-lang.org/edition-guide/rust-2018/error-hand...

I've not used Rust before, but this looks a lot like monads! Can I map/flatmap over these or do I have to unpack them later? If you _can_ operate on those like collections, Rust is a much more fun language than I initially gave it credit for!

Yes, you can map over them, and it's great! I think they satisfy all of the monad rules, but I'm forgetting what they all are at the moment.

Re: You’re better off using Exceptions

#224
post #206

Earlier quoted context omitted.

Not twice as slow. But you are forgetting the case where you know the element is already in the map, and you want to call map.get() without wrapping it in an option.

C# does this fairly nicely with an "out" parameter: https://docs.microsoft.com/en-us/dotnet/api/system.collectio... Or if you "know" it's there call the version that throws an exception if it isn't.

I haven't used that aspect of the Dictionary API at all in the 9 years programming C#, it is just too unwieldy to have to define a separate local variable to hold the result of the get. It also doesn't scope the out assignment (if the get fails, you can still read the out variable bound). I'm rarely in the case where I don't expect something to be in a map anyways, and when I do, I have an extension method with a default value returned if the key doesn't exist (or in some cases populate). Keeping expressions clean is important.

Re: You’re better off using Exceptions

#225

Earlier quoted context omitted.

Yes, poorly designed API, but we still have to handle them and the world is filled with them. So you can have a structure that works for the real world, or you can have an ideological structure the stubbornly insists that you should know better. "bad programmer! you should know if the key exists or fail".

Poorly designed APIs provide little evidence on exceptions being bad or not since the APIs themselves have big problems.

This thread is discussing whether exceptions are bad for handling unexceptional events. We are arguing that APIs that throw exceptions for valid program states, such as a missing key for some user input, is an abuse of exceptions. There are lots of these APIs in the world and we find that objectionable. You seem to agree with all of that, but you also present yourself as disagreeing with us, and it’s not at all clear what you’re disagreeing with specifically? Are you just being contrarian for its own sake or are we misunderstanding each other?

Re: You’re better off using Exceptions

#226
post #80

Earlier quoted context omitted.

"Check before" is a race condition nightmare - for anything where you care about concurrency, you must do the thing and then see whether it succeeded or not, assuming that the underlying layer is basically sound in this regard. The world is full of bugs of the form "does this file exist? no? OK, open it for writing", which is exploitable by dropping a symlink in there between the check and the open. The classic primi…

That case is even much more exceptional: where the record existed when you checked but didn't in the millisecond afterwards when you actually opened it. But if that is common, then I would guess a concurrent check for existence and open if it is might be necessary.

Exceptional doesn’t mean uncommon, it means your program is in an invalid state. Your programming style is inherently unsafe, and you are derelict of your most basic responsibility as a software professional if you apply it on any software of consequence. This is why we can’t have nice things.

Re: You’re better off using Exceptions

#227
post #209

Earlier quoted context omitted.

> But C++ does not provide a stack trace Which makes exception in C++ a very, very bad idea! My reaction to 'the test fails because map::at threw an exception': stupid STL!! A core dump would be so much easier to analyze.. Gdb's 'catch thow' is wonderful (well, it is after I fixed the part of our codebase which use exceptions as a control flow mechanism)

> My reaction to 'the test fails because map::at threw an exception': stupid STL!! > A core dump would be so much easier to analyze.. Uncaught exceptions call terminate(), which by default calls abort(), which generates a core dump. So if you want a core dump, just avoid catching the exception.

Except that I didn't put all these "catch".. But you're right, that's what should be done (or at least, rethrowing the exception from the catch block).

Re: You’re better off using Exceptions

#228

I completely disagree with this article, as it makes a lot of claims which are not true, uneducated or intentionally misrepresented to make a case for exceptions: > Because runtime errors are difficult to anticipate, I claim that using result types as a holistic replacement for error handling in an application is a leaky abstraction. Yes this is true, but it's not a leaky abstraction. There's always the posibillity t…

>Return errors which are meaningful and where the calling code can deal with it immediately, otherwise don't bother.

Don't bother and do what?

And how do you know what the calling code can and cannot do?

Re: You’re better off using Exceptions

#229
post #19

Earlier quoted context omitted.

I don't know Rust at all but what you're talking about sounds equivalent to (much maligned) Java's checked exceptions system? I never understood the hatred checked exceptions received especially from the younger crowd. I still write Java at work and I still use checked exceptions whenever they indicate an error condition that must not be ignored by the client code. Many new to the project developers hate me for it in…

I haven't written very much Java, but here are some differences between Java checked exceptions and Rust errors as I understand them: In Java, a function may throw a long list of checked exceptions, and these lists tend to grow to inconvenient sizes in larger programs. For example, if foo() calls bar() and baz(), which each throw 3 different exception types, then now foo() might throw 6 different exception types. In…

> For example, if foo() calls bar() and baz(), which each throw 3 different exception types, then now foo() might throw 6 different exception types.

> I think it's fairly common to bulldoze all that complexity by declaring a function that just "throws Exception".

These are both solved by the same approach: foo should be wrapping those underlying exceptions under its own domain, not just passing them along. This has the added bonus that the further up the call stack you go, generally the more context you have about the operation. So you also get to set a new message that explains that context. So foo should only throw FooException, which might be wrapping an underlying BarException, which might be wrapping an underlying BazException. You get a full accounting of what happened, and how each layer interpreted it.

For example: I invoke the user preferences subsystem to give me the user's foo setting. User preferences can be in a flat file or an embedded database. If I don't wrap exceptions, now my user preference system has to expose that implementation detail by exposing both file and database exception types. Instead I should wrap both of them in a UserPreferenceLoadingException type or whatever makes sense.

Re: You’re better off using Exceptions

#230

Earlier quoted context omitted.

Does this actually save much time? I thought it was the throw mechanic that was slow, rather than just creating the exception?

According my unscientific tests, it is about over 100 times faster. On my laptop I can throw one million exceptions in 15ms millisecond, when reusing the same exception objects, compared to 2 seconds when creating a new exception object every time with a quite shallow stack. When a new exception object is created, the slowest operation is filling information about the stack trace. It is possible to override Exception…

http://normanmaurer.me/blog/2013/11/09/The-hidden-performanc...
Post reply on HN