Hacker News new | ask | show | jobs
by joshka 568 days ago
> Basically what you're saying is

> "If you never have an accident you don't need seat belts in the car, and since we test drove the vehicle in the factory parking lot and didn't have an accident we decided not to have the seat belts".

Would you trust a manufacturer that added seat belts, but never tested they worked? That's what a runtime assertion is. If it can never fail unless there's a bug, then they can never be tested...

Assertion failure modes are also problematic. Their entire mechanism is blow up and stop running the program. Would you trust a car which crashed if a seatbelt was unplugged?

The test of my assertion is: show me some real-ish code where you think runtime assertions are useful (preferably in backend / web code not a kernel or such).

1 comments

Who says they can't be tested? Of course they can be tested, that's just a question of the testing tools being able run the process and trigger the assert and then realize that the process has in fact asserted and exited. If you think this can't be done then you really need to look for better tools. As an example if you program in C++ with boost.test you can even test that your code doesn't compile (can be useful for templates occasionally). That being said I find that at least my asserts are most of the time rather self explanatory such as checking against array/vector size and they don't really require specific 'testing'.

(example here: https://github.com/ensisoft/detonator/blob/master/game/tilem...)

"The test of my assertion is: show me some real-ish code where you think runtime assertions are useful (preferably in backend / web code not a kernel or such)."

That's simple, in C++ (that I program mostly in) any time letting the code execute would lead to undefined behavior, 10 times out 10 I prefer a controlled abort (an assert) with a core dump. For example going out of bounds on an array, what are your options? Pretend nothing is wrong, return a default value, throw an exception? All you can do with any of these options is to mask the actual BUG and cause Nth degree bugs down the road where the caller does something wrong since it it already went completely off track already. When 1+1=2 no longer holds it's best to stop.

"Would you trust a car which crashed if a seatbelt was unplugged?"

Assuming that by "crash" you really mean "controlled abort" (which is what an assert is, a controlled abort) yes, I would prefer my car would tell me in some controlled way when the seat belts no longer work rather than silently let me continue.

But that's not the same thing, seat belt not being unplugged isn't a BUG, it's a condition that the car software needs to be able to handle. You might be confused here because many people mix up logical error handling with BUGS.

"Would you trust a manufacturer that added seat belts, but never tested they worked? That's what a runtime assertion is. If it can never fail unless there's a bug, then they can never be tested..."

Yes who knows, any individual seat belt may malfunction but still the concept is much better than not having any. We don't go and say "oh, because any single seat belt might be broken it's pointless to have them at all". The same way we don't say "oh because some assert can be wrong (check the wrong thing or the wrong condition etc) it's pointless to have/use them at all". That would be just absurd.

I think we're really talking past each other at this point, so I'm probably not going to respond more on this. Maybe in C++ where you don't have better techniques available, then assertions *are* the best tool you can reach for for this sort of thing. In many other languages however we do have better options. These should chosen over using assertions when possible as the outcome is significantly better.

> For example going out of bounds on an array, what are your options? Pretend nothing is wrong, return a default value, throw an exception?

The article is talking about assertions in rust. The answer to that question in rust is to use `.get()` which returns `Option<T>`. This moves the condition where the array index is outside the bounds into a structured result rather than causing an application crash. An assertion that crashes the program would be useless there, as the language makes the type of error one that is idiomatically avoided. This (in addition to testing) is part of my point. Dig deep into the implementation of this in the std lib and there's no assertion, just a bounds check which either returns `Some(value)` or `None`.

The part I'm saying is problematic is not the check part of the assertion, it's the crashing part. Write software that avoids needing to crash by proving that the scenarios where invariants not invalid don't exist. When you do that any assertions which you include are code paths which are impossible to ever hit. This is by definition.

Expanding on the article example, it requires that the `youngest` variable is always >= 0. Just define that as `u8` and let the compiler be your check. You never need an assertion to test a tautology.