9 ms·
My opinion is the exact opposite see https://debugagent.com/everything-bad-in-java-is-good-for-you https://debugagent.com/everything-bad-in-java-is-good-for-yo.
by invalidname 3y ago
My opinion is the exact opposite see https://debugagent.com/everything-bad-in-java-is-good-for-you https://debugagent.com/everything-bad-in-java-is-good-for-yo...
Checked exceptions are unpopular since no one likes responsibility. But they are great when used right. Calls that must have proper cleanup after them e.g. SQL, IO are checked. The fact that this must be communicated via interfaces is hugely important.
There are "weird" problems such as stream close() throwing a checked exception. That's an API misbehavior that has a workaround thanks to try-with-resources.
- throwawaymaths 3y agoNot exceptions, but zig has explicit error return types, and it works great. Especially since you can also just "tell the compiler to figure it out". There are a few cases where the compiler can't figure it out, but in those cases you grudgingly annotate the error types and it's done.
- scarface_74 3y ago> Calls that must have proper cleanup after them e.g. SQL, IO are checked. Why? In C# you use a “using” block and whether your code exits the using block successfully or with an exception, the cleanup is automatic. RAII has been around at least since the 80s with C++.
- invalidname 3y agoWe have it in Java too. For us it's try-with-resources and has nothing to do with checked exceptions. Checked exceptions remind you that you need to wrap the code and need to take that into account. They also force you to declare that an exception is thrown if you don't want to handle it in the current method. That's important as the signature of the method carries an important failure that can't be dismissed and is enforced by the compiler.
- scarface_74 3y agoWhat “reminder” do you need to wrap your code? I can’t think of an instance that you wouldn’t wrap your code in a try/catch block around your code and either log and crash, log and continue, or for a specific exception that you know about, do “something”. But most of the time it’s the first two if you’re using RAII.
- invalidname 3y agoLet's say I write an API for handling IO. DB or File or networking or anything really. I get a failure, what do I do? I can throw an exception, but this is important how do I know the user of my API will actually do the cleanup after me. I can't do the cleanup since this is a part of an API not the actual usage of the API. How can I give the user of this API the right set of hint that "you need to pay attention to this" without worrying too much. Checked exceptions are that. A large part of the problem is when people use them for things that aren't important, but when they are important I can just declare a "throws" and know that someone will handle the exception along the chain. With runtime exceptions I have no guarantee.
- funnymony 3y agoAny chance you have a code/pseudo code example of this? My naive take on this would be “just use raii/closable”. (But easily and likely, I misunderstood)
- invalidname 3y agoLet's say Java had no checked exceptions. I could just write IO code without doing a try since no one is forcing me to check anything. But let's go further. Let's say I have an API x(). This API accesses my database as part of a larger transaction. I invoke x() and it fails with an SQLException which is declared. I can revert the transaction or I can choose to retry x(). The checked exception notifies me that there's an important decision I need to make at this point, cleanup is one option but in some cases there are more. Furthermore, cleanup isn't always enough. In a case of an IOException I'd often want to notify the user e.g. if the disk is out of space I want to show an error message somewhere...
- funnymony 3y ago> important failure that can't be dismissed But importance of the failure is determined completely by the program, not the library. Grep fails to open a file for reading -> message the user and exit Nuclear reactor controller fails to read important a file -> initiate reactor shutdown or something. If file read is critical, you have to handle failure no matter what the interface is. Because you know that disk can fail.
- tremon 3y agoGrep fails to open a file for reading -> message the user and exit That should be: message the user and process the next file
- funnymony 3y ago:)
- MrJohz 3y agoBut the point is that in both cases the failure needs to be handled somewhere and somehow. Surfacing the error might be a valid option, but to make the decision you need to know that the error is there in the first place. This can be solved with good documentation, but it can also be solved in the type system. Typically, if I can get my computer to do work for me (e.g. make sure that I've handled all possible error cases) then I'm much more confident in my code, hence why I see a lot of value in a well-designed checked exceptions system.
- tadfisher 3y agoExceptions aren't normal parts of the type system though, they're a way to enforce control flow to deal with them. Another way to do this is with a Result type, which would actually be part of the same type system that you use in the rest of the language.
- MrJohz 3y agoWhy can't they be part of the type system? Rust is a good example of a case where they are part of the type system (albeit in a more monadic form). You've also got typed effects, where effects are essentially a generalised form of exception.
- equalsione 3y agoThis is what try-with-resource does in Java. Introduced in Java 8 I think so better late than never
- scarface_74 3y agoAnytime I see “something was added to Java” late in the game, it’s usually an ugly hack. But I have to admit that the syntax for it is actually sensible.
- specialist 3y agoFrom your OC: > Null is fast. Super fast. Literally free. Yes and: The JIT will optimize away Null Object method invocations. All my composable classes have a Null Object. No null checks means concise iteration (eg graph traversal). Eliminates NPEs. Just as fast. Win / win / win. Optionals (classes and operators) continue to be turrible mistakes. So much unnecessary effort, so little benefit. Ditto @Nullable and @Nonnull. Someday, maybe, I'll make a javac compiler plugin which autogenerates Null Object implementations and converts "Node abc = null" to "Node abc = Node.DEFAULT_NULL_OBJECT_INSTANCE". https://en.wikipedia.org/wiki/Null_object_pattern https://en.wikipedia.org/wiki/Null_object_pattern
- anonymoushn 3y agoIt seems like when one is implementing Null Objects and making incomplete attempts to prevent values from ever being null it is not really an argument in favor of nullable values being good and the only type of values that should be present in a language.
- specialist 3y agoI'm not smart enough to parse this. Try again?
- anonymoushn 3y ago"All non-primitive values are nullable references" is a feature of the language. You posted that you are trying to avoid using that feature (instead using non-null references to a special Null value?) and trying to avoid having null references for the types you create. It seems like you do not actually think the feature is a good feature.
- specialist 3y ago> Ditto @Nullable and @Nonnull. I was referring to the annotations. My proposal moots them. References would still be nullable.
- anonymoushn 3y agoIt's weird to argue that null is how the hardware works. Many structs contain only bytes that are allowed to take on any value, so making them nullable takes extra space.
- invalidname 3y agoThis is mentioned in the memory layout section in the post.
- anonymoushn 3y agoI'm not sure what "a marker" is and how to make it take 0 bits of storage.
- invalidname 3y agoThis is an upcoming behavior in Valhalla which isn't yet a part of Java so there's nothing final. Currently Valhalla has primitive and value object types that determine identity behavior.
- anonymoushn 3y agoYou mean non-nullable object types then. Which are faster and take up less space because that's how the hardware works :)
- invalidname 3y agoThey're not faster for all cases. Near memory works great for some edge cases such as looping on an array of data in a block. This is very much a special edge case. For many other non-benchmark situations this isn't so simple. If you add the overhead of memory copying and lack of identity things are more complex.
- crabbone 3y agoThis comes from a misunderstanding of the reason why exceptions where designed they way they were. The whole point of exceptions bubbling up w/o having to write support code to deal with passing exceptions further is to make it so that the purpose of the function is clear to the reader. Go's exceptions have the same unfortunate property as Java's checked exception. And that's what makes Go's code atrocious. Every other line you see something like: if x, e := f(); e != nil { ... } else { return y, e } It makes it very easy to make mistakes when you have to write a lot of repetitive code. You make typos, and because they often land on the "bad" path, they aren't immediately discovered. You have to memorize the state of your function wrt' variable initialization, because now you cannot automatically initialize and destroy them all together. You need to create a lot of helper variables whose purpose is only to transfer return value from one function to another... If you think that you want checked exceptions, then you don't want exceptions at all. You are denying them the very purpose they were created for. But there are alternative ways to deal with unexpected events in program execution. Monads would be one of those. So... maybe just don't use exceptions?
- invalidname 3y agoNo. This comes from a misunderstanding of checked exceptions. Checked exceptions don't mean I need to handle the exception right now. They mean I need to either do that or declare throws. Declaring throws is fine it implicitly documents the code and enforces a similar requirement up the chain. Checked exceptions aren't the default and shouldn't be.
- naasking 3y agoChecked exceptions should be the default, exceptions should just be rare. They are overused in almost all languages.
- invalidname 3y agoWhat about: NullPointerException? ArrayIndexOutOfBoundsException? IllegalArgumentException? UnsupportedEncodingException?