11 ms·
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
by trav4225 4y 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. :-)
- allenu 4y agoI'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.
- uoaei 4y ago> 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?
- allenu 4y agoYes, 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.
- aaaaaaaaaaab 4y agoYeah. 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?
- jbverschoor 4y agoSame 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.
- vardump 4y agoWell, 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.
- sargun 4y agoI 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.
- vardump 4y agoIf feasible, electromechanical methods are good.
- marcosdumay 4y agoIf 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.
- vardump 4y agoIt'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.
- _moof 4y ago"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.
- xdennis 4y agoI 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.
- shepherdjerred 4y agoIt 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.
- bigDinosaur 4y agoPicked 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!
- xdennis 4y agoCompletely 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.
- jillesvangurp 4y agoIt'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.