Hacker News new | ask | show | jobs
by trav4225 1441 days ago
I've seen a lot of new developers shocked by this approach, which surprises me a little. They seem to think that it's up to the application to handle all errors, even those of the programmer(s). This, of course, is unreasonable since it would essentially require knowing all the bugs in advance. :-)
4 comments

I'm a big fan of the "crash early" strategy. I write in Swift primarily, and if I suspect a state is impossible to reach, I'll add a fatalError() so that in development, if it turns out I'm wrong, I spot it right away. (Something I learned from another dev I worked with, who was very productive.)

Unfortunately, a lot of other devs hate to see that your code may actually crash and start asking questions about what scenario could cause it and asking if maybe there's a more gentle way to get out of the error. So, I'll often back down and start having softer error-handling, but on the whole it does complicate things further as the errors cascade and now you have to reason about handling combination of errors that have low likelihood of happening. So, to me, just having an early crash is way better.

Yeah. My pet peeve is `guard let … else { return }` instead of force-unwrapping. Like, why do people think that silently swallowing an error is better than crashing loudly and clearly?
Same here.. esp. in server based code it makes no sense to not fail early, even on the slightest issues. If you have proper logging / notifications, you'll code be more robust.

Had to deal with the same issue as you.. other devs and managers don't like those errors.. but it makes things fragile and more difficult to troubleshoot.

> if I suspect a state is impossible to reach, I'll add a fatalError()

Does Swift have assert statements? If so, is there a reason you chose this method instead?

Yes, Swift has assert statements. I tend to use them a lot as well, but in shipping code, they don't terminate the app. There are still some places where I'd prefer to terminate the app early rather than continue on.

To be clear, I tend to use assert statements more than fatalErrors.

It's a common mistake in code written by junior developers to only code the happy path. It leads to a very brittle system. A good example is a web application that needs a websocket open. What happens if you run such an application on a mobile phone and you temporarily lose connectivity and this happens multiple times as people walk around town because real world connectivity just isn't perfect? And also, they put their phone in their pocket and it goes to sleep. These are not user errors but expected, normal behavior.

Basically the happy path is that this simply never happens. You open a websocket and listen for incoming messages and process them. The actual situation is that you open a websocket and some time later it dies and then you simply attempt to reopen it until it succeeds and resume processing messages. The app has several states: connected, connecting, and not connected and should transition from one to the other depending on what happens.

Our frontend people struggled a lot with this exact issue. They only thought of the happy path and simply ignored any form of expected failure. So the first version of the app worked great for a while until it just stopped working. The fix: "just reload the app" was of course not really acceptable. All that was needed was a little defensive coding: assume this call will sometimes fail and simply try again when that happens. Then also handle the case where retrying will also fail because actually the request is wrong (input validation) and the error is the system telling you that it is wrong. If you don't have any code that handles that, you are going to have a very flaky UX.

I was on a team for a short while (Java programmers) and their frontend code was really overly "careful". For example, they would always check if a method existed, before calling it.

    var o = new SomeObject();

    if (o.computeSomething != null && o.computeSomething != undefined) {
       o.computeSomething(...);
    }
Their reasoning was that in JavaScript (with the old syntax) you just add functions to the prototype, so you could forget to do it or mistype it.

    SomeObject.prototype.computeSomethinnn = function () ...
I was sort of tripping over myself in objections to what they were doing:

* you shouldn't check for null or undefined, but rather do `o.computeSomething instanceof Function`

* there's no need to do `!= null` and `!= undefined` because `!=` (as opposed to `!==`) actually checks for both

* you shouldn't do the check at all because if you actually mistype the function name all you're doing is hiding the error. Failing sooner is better.

* a missing method should be picked up in the unit tests (but they didn't have any tests at all because "our system is too complex to be tested automatically")

* probably some others...

That team really hated JavaScript and their code showed it.

BTW, the indentation above is not wrong... they did indent by 3 spaces. I read a story about 3 space indents on thedailywtf.com and thought that it was clearly made up... after this team I believe it.

I set tabwidth to 3 in my editor. I like the way it looks. But of course the whole point of tabs is that nobody else has to suffer for my esoteric choice.

It also helped when tutoring new python students -- when they mixed space-indented code they copied from the internet with tab-indented code they copied from the internet, they'd get all sorts of fun errors. Setting the tabwidth to an even number sometimes allows them to hide. 3, though, really makes them stick out.

Sounds like hilarious passive aggressive behavior from java developers forced to interact with that devil's language JavaScript against their will.
It sounds like a pretty Java thing to do considering the prevalence of `null` and null-checks in the language. It's always interesting to see the habits that programmers bring from their main language(s) to ones they're picking up, especially when they're under pressure to deliver so they can't learn to program idiomatically.
Picked up by unit tests? How about some kind of system which can tell you if the method exists or not, and even possibly correct your typos, before you run the code!
Completely fair, but that's often not built into dynamic languages. My main criticism is with their nonsensical approach to dealing with the limitations of JavaScript.

As far a I know, ESlint can't detect missing methods, and they weren't even using a linter. TypeScript can, but they weren't using that.

they did indent by 3 spaces

Probably a compromise between 2 and 4?

I suggested exactly that as a joke over a decade ago, then decided to try it out. Ended up I really liked it, and still use it for all my personal code.

I do stick to 4 spaces at work though.

Well, there's software that can cause some degree of harm. For example through servos controlling something physical. While you still probably can't catch all of the issues, you damn better try as hard as you can within reason.

I'd also wish for similar rigor from people developing whatever filesystens my data is on. :-)

Fail fast is generally a good idea, if you can do it safely.

If you can't fail safely, you better review your entire architecture.

Software fails, you can make failures rarer, but you can't make they go away. You have to deal with it, it's not an option.

It's all really about risk management. Things can (and will) go wrong, and it doesn't only apply to software.

This involves a lot of thinking and collecting information about potential risks and evaluating their probability and severity.

Then you just mitigate the worst risks, probability times severity (other factors are also possible). Some residual risk always remains.

I think the idea is that there are error recovery semantics that:

1. Determine the last sane state of the system, and work forward from there. (Read the servo position and try to go from there)

2. Have a the "recovery" routine to reset the system. (Take all positions to "zero")

3. Just stop. (Yes, I know this can be bad). And ask a human for help.

If feasible, electromechanical methods are good.
> I'd also wish for similar rigor from people developing whatever filesystens my data is on. :-)

Stable storage is a key factor in making this philosophy work. [1]

[1] https://qconlondon.com/london-2012/qconlondon.com/dl/qcon-lo...

"Litter the code with aborts and test the ever-loving hell out of it" is more or less the strategy we use with flight software.