4 ms·
> The compiler should force you to handle every exception in some way, or to check for it. This is the single most unproductive mis-feature a language could ha
by hypertele-Xii 5y ago
> The compiler should force you to handle every exception in some way, or to check for it.
This is the single most unproductive mis-feature a language could have for me. Programming is already a tedious excercise of wrangling your thoughts into an alien form the computer can understand. You want, on top of everything else, the computer to refuse to run your program at all, unless you explicitly handle every possible edge case?
I get that some people are engineers with rigid requirements. I'm an artist - I sculpt the program to produce output I'm not entirely clear on. I'm trying to make the computer to interesting, unexpected things.
Say I'm making a game. I wanna load a character sprite from an image file and draw it on the screen. Do I really need to handle all the possible ways that file could fail to load right now, before even seeing a preview of what it should look like? Hell no!
It's like having an assistant who refuses to do anything unless you specify everything! Hey assistant, get me a coffee. "I refuse to get you a coffee because you didn't specify what I should do in case the coffee machine is broken." Aargh!
- dthul 5y agoI don't quite follow. You always have to somehow handle the case the file does not load successfully. In exception languages that handling might be implicit (raise an exception and crash your program) and in "errors as values" languages you at least have to acknowledge that it could go wrong with something like `image.unwrap()` (which turns it into a program aborting panic).
- hypertele-Xii 5y ago> You always have to somehow handle the case the file does not load successfully. In exception languages that handling might be implicit I.e. you don't have to handle it. Until you're polishing the program for a stable release, that is.
- dthul 5y agoRight, in both approaches you can choose to handle the error by ignoring it and crashing. In "errors as values" languages you have to make that choice explicit by marking the line with `unwrap`. Saying that this requirement is "the single most unproductive mis-feature a language could have" is extreme hyperbole, no? Adding `unwrap`s during development to imitate implicit exceptions for fast prototyping takes no time or thought at all. On the contrary, when you later want to polish your program for release these explicit markings make it very easy to find the points in your code where errors can occur and which you don't properly handle yet.
- hypertele-Xii 5y agoOkay, if there's a simple way to mark some code as "compile this even if it's wrong", it's only a minor annoyance. But the commenter I responded to seemed to me to be wishing for a language that explicitly disallows that. Maybe I misunderstood?
- wvenable 5y agoOne of my personal favorite examples of exception handling was a small GUI app with a single top-level exception handler at the event loop that displayed an error message and continued. That application was extremely robust. You try and save a file and 100 different things could go wrong (network drive unavailable, file is read-only, etc) but it nicely recovered and you could see what the problem was, correct it, and re-save. One single exception handler for the whole app.
- KronisLV 5y ago> You want, on top of everything else, the computer to refuse to run your program at all, unless you explicitly handle every possible edge case? Precisely! Even better - let the IDE suggest to you all of the possible exceptions and when you're feeling lazy or are hacking away at a prototype, either let it add a "throws SomeException" to the method signature and make it someone else's problem up the call chain, or just add a catch all after you've handled the ones that you did want to handle! After all, none of us can recall the hundreds of ways network calls can get screwed up, but we're pretty sure what to do at least in a subset of those, but we'd also forget about those without these reminders. Not only that, but when you're writing financial code or running your own SaaS, you'll at the very least will want your error handling code to be as bulletproof as the guarantees offered to you by your language's rigid type systems. Then, when you've finished hacking together your logic, your instance of SonarQube or another tool could just tell you: "Hey, there are 43 places in your code where you have used logic to catch multiple exceptions" and then you could review those to decide whether further work is necessary, or whether you can add a linter ignore comment to the code explaining why you don't want to handle the edge cases, or just do so in the static code analysis tool, so all of your team members know what's up. Alternatively, if you're just writing something for yourself, just leave it as it is, knowing that if you'll ever need to publish your code for thousands of others to use, then you probably should go back to those now very visible places and review it. So essentially: /** * Attempts to load a Sprite from a file. You can then use the instance to display it on screen. * @param file This is the file that we want to load the image from. Use relative path to "res" directory. * Our engine loads PNG files and technically can also load GIF files because someone hacked that functionality together in an evening. * That's kind of slow though, so we should use PNGs whenever possible. See ENGINE-33452 for more details. * @return A Sprite instance that you can pass to the rendering logic to put it on the screen, or alternatively process the loaded image in memory. */ public Sprite loadSprite(@NotNull File file) throws SpriteGenericException, FileSystemGenericException { try { return FileSystemSpriteLoader.loadPNG(file); } catch (ImageWrongFormatException e) { wrongImageFormatLogger.warn("We found a " + e.getActualFormat() + " format file: " + file.getPath(), e); // the art team should have a look at this if (e.getActualFormat().equals(ImageFormats.GIF)) { return FileSystemSpriteLoader.loadGIF(file); // TODO unoptimized call because we needed GIFs for ENGINE-33452, remove later } else { throw SpriteGenericException("We failed to load sprite from file: " + file.getPath() + " because of wrong format: " + e.getActualFormat(), e); } } catch (SpriteCorruptedException e) { brokenImageLogger.warn("We found a corrupted sprite in file: " + file.getPath(), e); // maybe the pipeline is broken again? throw SpriteGenericException("We failed to load sprite from file: " + file.getPath() + " because of image corruption", e); } catch (Exception e) { // TODO ENGINE-44551 handle the file system access cases later once the API is stable and we know how it'll work on Android throw FileSystemGenericException("We failed to load sprite from file: " + file.getPath(), e); } } I prefer software blowing up in predictable ways as opposed to doing so unexpectedly. Even Java is vaguely close to being what i'm looking for, however unchecked exceptions simply isn't acceptable from where i stand.