6 ms·
An adjacent point is to use checked exceptions and to handle them appropriate to their type. I don't get why Java checked exceptions were so maligned. They save
by abraxas 1y ago
An adjacent point is to use checked exceptions and to handle them appropriate to their type. I don't get why Java checked exceptions were so maligned. They saved me so many headaches on a project where I forced their use as I was the tech lead for it.
Everyone hated me for a while because it forced them to deal with more than just the happy path but they loved it once they got in the rhythm of thinking about all the exceptional cases in the code flow. And the project was extremely robustness even though we were not particularly disciplined about unit testing
- dherls 1y agoWith Java, there are a lot of usability issues with checked types. For example streams to process data really don't play nicely if your map or filter function throws a checked exception. Also if you are calling a number of different services that each have their own checked exception, either you resort to just catching generic Exception or you end up with a comically large list of exceptions
- Jtsummers 1y agoSetting aside the objections some have to exceptions generally: Checked exceptions, in contrast to unchecked, means that if a function/method deep in your call stack is changed to throw an exception, you may have to change many function (to at least denote that they will throw that exception or some exception) between the handler and the thrower. It's an objection to the ergonomics around modifying systems. Think of the complaints around function coloring with async, how it's "contagious". Checked exceptions have the same function color problem. You either call the potential thrower from inside a try/catch or you declare that the caller will throw an exception.
- abraxas 1y agoThat's a valid point but it's somewhere on a spectrum of "quick to write/change" vs "safe and validated" debate of strictly vs loosely typed systems. Strictly typed systems are almost by definition much more "brittle" when it comes to code editing. But the strictness also ensures that refactoring is usually less perilous than in loosely typed code.
- gpderetta 1y agoAnd as with async, the issue is a) the lack of the ability to write generic code that can abstract over the async-ness or throw signature of a function and b) the ability to type erase asyncness (by wrapping with stackful coroutines) or throw signature (by converting to unchecked exceptions). Incidentally, for exceptions, Java had (b), but for a long time didn't have (a) (although I think this changed?), leading to (b) being abused.
- someone_19 1y agoUnhappy way is a part of contract. So yes, that is what I want. If a function couldn't fail before but can after the update - I want to know about it. In fact, at each layer, if you want to propagate an error, you have to convert it to one specific to that layer.
- bigstrat2003 1y ago> Checked exceptions, in contrast to unchecked, means that if a function/method deep in your call stack is changed to throw an exception, you may have to change many function (to at least denote that they will throw that exception or some exception) between the handler and the thrower. That's the point! The whole reason for checked exceptions is to gain the benefit of knowing if a function starts throwing an exception that it didn't before, so you can decide how to handle it. It's a good thing, not a bad thing! It's no different from having a type system which can tell you if the arguments to a function change, or if its return type does.
- Jtsummers 1y agoWhy are you screaming? All those wasted exclamation marks, you could have written something I didn't know. I didn't say it wasn't the point or that it was a bad thing.
- ragnese 1y ago> Setting aside the objections some have to exceptions generally: Checked exceptions, in contrast to unchecked, means that if a function/method deep in your call stack is changed to throw an exception, you may have to change many function (to at least denote that they will throw that exception or some exception) between the handler and the thrower. It's an objection to the ergonomics around modifying systems. And if you change a function deep in the call stack to return a different type on the happy path? Same thing. Yet, people don't complain about that and give up on statically type checking return values. I honestly think the main reason that some people will simultaneously enjoy using Result/Try/Either types in languages like Rust while also maligning checked exceptions is because of the mental model and semantics around the terminology. I.e., "checked exception" and "unchecked exception" are both "exceptions", so our brains lumped those two concepts together; whereas returning a union type that has a success variant and a failure variant means that our brains are more willing lump the failure return and the successful return together. To be fair, I do think it's a genuine design flaw to have checked and unchecked exceptions both named and syntactically handled similarly. The return type approach is a better semantic model for modelling expected business logic "failure" modes.
- default-kramer 1y agoI think checked exceptions were maligned because they were overused. I like that Java supports both checked and unchecked exceptions. But IMO checked exceptions should only be used for what Eric Lippert calls "exogenous" exceptions [1]; and even then most of them should probably be converted to an unchecked exception once they leave the library code that throws them. For example, it's always possible that your DB could go offline at any time, but you probably don't want "throws SQLException" polluting the type signature all the way up the call stack. You'd rather have code assuming all SQL statements are going to succeed, and if they don't your top-level catch-all can log it and return HTTP 500. [1] https://ericlippert.com/2008/09/10/vexing-exceptions/ https://ericlippert.com/2008/09/10/vexing-exceptions/
- deleted 1y ago[deleted]
- codr7 1y agoSometimes I feel like I actually wouldn't mind having any function touching the database tagged as such. But checked exceptions are such a pita to deal with that I tend to not bother.
- abraxas 1y agoIt's fine to let exceptions percolate to the top of the call stack but even then you likely want to inform the user or at least log it in your backend why the request was unsuccessful. Checked exceptions force both the handling of exceptions and the type checking if they are used as intended. It's not a problem if somewhere along the call chain an SQLException gets converted to "user not permitted to insert this data" exception. This is how it was always meant to work. What I don't recommend is defaulting to RuntimeException and derivatives for those business level exceptions. They should still be checked and have their own types which at least encourages some discipline when handling and logging them up the call stack.
- yardstick 1y agoIn my experience, the top level exception handler will catch all incl Throwable, and then inspect the exception class and any nested exception classes for things like SQL error or MyPermissionsException etc and return the politically correct error to the end user. And if the exception isn’t in a whitelist of ones we don’t need to log, we log it to our application log.
- bcrosby95 1y agoI think most complaints about checked exceptions in Java ultimately boil down to how verbose handling exceptions in Java is. Everytime the language forces you to handle an exception when you don't really need to makes you hate it a bit more. First, the library author cannot reasonably define what is and isn't a checked exception in their public API. That really is up to the decision of the client. This wouldn't be such a big deal if it weren't so verbose to handle exceptions though: if you could trivially convert an exception to another type, or even declare it as runtime, maybe at the module or application level, you wouldn't be forced to handle them in these ways. Second, to signature brittleness, standard advice is to create domain specific exceptions anyways. Your code probably shouldn't be throwing IOExceptions. But Java makes converting exceptions unnecessarily verbose... see above. Ultimately, I love checked exceptions. I just hate the ergonomics around exceptions in Java. I wish designers focused more on fixing that than throwing the baby out with the bathwater.
- lock1 1y agoIf only Java also provided Either<L,R>-like in the standard library... Personally I use checked exceptions whenever I can't use Either<> and avoid unchecked like a plague. Yeah, it's pretty sad Java language designer just completely deserted exception handling. I don't think there's any kind of improvement related to exceptions between Java 8 and 24.
- alex_smart 1y agoOk please help me understand, what is the difference between - R method() throws L, and - Either<L, R> method() To me they seem completely isomorphic?
- worldsayshi 1y agoDon't you mean "isosemantic"? Since the same concept is represented with different syntax.
- alex_smart 1y ago
- hiddew 1y agoThat is why I am happy that rich errors (https://xuanlocle.medium.com/kotlin-2-4-introduces-rich-errors-a-game-changer-for-error-handling-413d281e4a05 https://xuanlocle.medium.com/kotlin-2-4-introduces-rich-erro...) are coming to Kotlin. This expresses the possible error states very well, while programming for the happy path and with some syntactic sugar for destucturing the errors.
- Hackbraten 1y agoFor anyone who dislikes checked exceptions due to how clunky they feel: modern Java allows you to construct custom Result-like types using sealed interfaces.
- wvenable 1y agoI rarely have more than handful of try..catch blocks in any application. These either wrap around an operation that can be retried in the case of temporary failure or abort the current operation with a logged error message. Checked exceptions feel like a bad mix of error returns and colored functions to me.
- jayd16 1y agoC# went with properly typed but unchecked exceptions. IMO it gives you a clean error stacks without too much of an issue. I also think its a bit cleaner to have a nicely pattern matched handler blocks than bespoke handling at every level. That said, if unwrapped error results have a robust layout then its probably pretty equivalent.
- pjmlp 1y agoUntil routinely prod goes down with that exception that no one cared to handle, been there done that.
- jayd16 1y agoFor something like a web request, all the frameworks catch the exception at the request level. Prod should not be going down. Maybe you mean requests are failing on uncaught exceptions, in which case I'd say it's working well.
- pjmlp 1y agoFor the customer there is hardly any difference that the server keeps running if a critical workflow, especially with a payment in flight, crashes and burns. Or if they are unable to work, because they keep getting a maintenance page, as the load balancer redirects them after several HTTP 500 responses.
- jayd16 1y agoThere're a huge different between a broken feature and the whole server crashing every time that feature is attempted. Anyway, you prefer critical workflow like payment to show a success but actually be an unhandled error?
- pjmlp 1y agoFor the customer the difference hardly matters, they cannot fulfill what they intended to do, because someone somewhere forgot to catch an exception, going all the way out of the MVC controller, providing a very bad UI/UX, and from security point of view, a possible DOS attack vector. I prefer an happy customer, and not having to deal with support calls.
- paulddraper 1y agoThere are lots of reasons. But for one, Java checked exceptions don't work with generics.
- twhitmore 1y agoChecked exceptions were a reasonable idea, but the Java library implementation & use of these was totally wrong. Checked exceptions work well for occasional major "expectable" failures -- opening a file, making a network connection. They work extremely poorly when required for ongoing access or use of IO/ network resources, since this forces failures which are rare & impossible to usefully recover from to be explicitly declared/ caught/ rethrown with great verbosity and negative value added. All non-trivial software is composition, so the idea of calling code "recovering" from a failure is at odds with encapsulation. What we end up with is business logic which can fail anywhere, can't recover anything, yet all middle layers -- not just the outer transaction boundary -- are forced to catch or declare these exceptions. Requiring these "technical exceptions" to be pervasively handled is thus not just substantially invalid & pointless, but actually leads to serious rates of faulty error-handling. Measured experience in at least a couple of large codebases is that about 5-10% of catch clauses have fucked implementations either losing the cause or (worse) continue execution with null or erroneous results. https://literatejava.com/exceptions/checked-exceptions-javas-biggest-mistake/ https://literatejava.com/exceptions/checked-exceptions-javas...