Live data from Hacker News

Retrofitting null-safety onto Java at Meta

engineering.fb.com

71–80 of 230 posts

Re: Retrofitting null-safety onto Java at Meta

#71

This is just covering up design problems. NPEs show you were you have design deficiencies. If you have getAccount().getContact().getPhoneNumber() and contact is null, you'll get an NPE. The question shouldn't be: "How do I shove the NPE under the rug for the next 1337 coder to deal with?", the question should be: "How did I initialize an Account without a Contact?"

Thank you for stating this. I been pulling my hair out trying to comprehend how more focus is not put on that fact. Whether your language is null-safe or not, you have to deal with this. Like for example, if I have a type that is serialized from JSON to Kotlin type and one of the fields is not-nullable but the JSON does not have that field, you still going to get an error, right? With Java, at least you'll be able to do something about it and not just fail the request at the these null-safe touchpoints.

Re: Retrofitting null-safety onto Java at Meta

#72
post #21

It's so sad that Java 8 had the chance to really fix the null problem, but gave us only the half-assed `java.util.Optional `. Rather than implementing optional values at the language level, it's just another class tossed into the JRE. This is perfectly legal code, where the optional wrapper itself is null: Optional getMiddleName() { return null; }

imo it seemed like there was this phase of "if we pretend null doesn't exist maybe it will go away" that resulted in a bunch of design issues. Beyond Optional, the other big one to me is Map.compute/Map.merge, which subtly breaks the previous interface contract for Map. As annoying as null is, I'd rather have null than have broken apis.

Re: Retrofitting null-safety onto Java at Meta

#73
post #21

It's so sad that Java 8 had the chance to really fix the null problem, but gave us only the half-assed `java.util.Optional `. Rather than implementing optional values at the language level, it's just another class tossed into the JRE. This is perfectly legal code, where the optional wrapper itself is null: Optional getMiddleName() { return null; }

Do you feel that a language has to have something at the language level to prevent NPEs? In my experience, Scala does pretty well without it. I guess is your point that the language should make it impossible to write bad code, not just make it easy to write good code?

Just a heads up, Scala 3 actually has a compile flag that will make types exclude ‘null’ as a valid subtype, so every nullable variable will have to have type signatures like String | Null.

Re: Retrofitting null-safety onto Java at Meta

#74
post #4

Related work: https://devblogs.microsoft.com/dotnet/nullable-reference-typ... C# has made it possible to gradually roll out stricter nullability checking as well. The static analysis gets integrated into the regular language analyzers. Incremental migration is the only way to go.

C# have taking it further. New projects give errors if you don't declare vars as nullable when they may be null in some context. It will help for static analyzers to find these cases. I see a big risk in it. That people will just init nonsense objects to get around the warnings.

> That people will just init nonsense objects to get around the warnings.

You technically can do "= null!", which means assign null by default, but assume it is not null. This is currently the recommended way to do deserialization, where you know the value is not null, but you have not explicitly filled it.

Re: Retrofitting null-safety onto Java at Meta

#75
post #21

It's so sad that Java 8 had the chance to really fix the null problem, but gave us only the half-assed `java.util.Optional `. Rather than implementing optional values at the language level, it's just another class tossed into the JRE. This is perfectly legal code, where the optional wrapper itself is null: Optional getMiddleName() { return null; }

@NonNull Optional getMiddleName() { return null; // error }

Or even just setting the default to non-nullable with any static analysis checker.

Re: Retrofitting null-safety onto Java at Meta

#76

Earlier quoted context omitted.

Well, C and Scala are some counter examples that immediately come to mind. Kotlin is probably more similar to Java than any other mainstream language. There’s almost no learning curve there, while going from Java to other “easy” languages like Python requires significantly more time to get used to.

Scala it depends how you want to use it. If you're going for full FP then sure it can take a little bit longer, but you can also just use it like Java+ if you really want...

I think there's a difference here between getting acclimated to scala (for new code, presumably), which is reasonably easy, and getting acclimated to a scala codebase that was already written by someone else.

You can do the first one basically the same way you'd do kotlin, the second one can get pretty hairy if someone decided to bring in a bunch of macro heavy DSLs and syntax extensions.

Re: Retrofitting null-safety onto Java at Meta

#77

The null problem has been around a very long time. It's been a huge source of errors in programming. I'm glad to see it actively being worked on, even if it is awkwardly being retrofitted on an old language. I can only look on with disappointment when new (or newish) languages include null as part of the language instead of doing something more sensible like having an Option/Either type. Of course, I won't name names…

It's okay for null to be a part of the language as long as the type system can reason about it (via nullable-types, sum types, etc). Dart, TypeScript, Kotlin are examples. But yeah, Go is the problem-child that doesn't have any way of statically reasoning about nulls

Yes, it's OK to have null in the language in limited cases. I'm fine with null so long as the language enforces checking for null when it could cause a NullPointerException (or that language's equivalent).

Java's biggest failure in null handling was allowing EVERY reference type to be null without a way of specifying that it could be non-null. This basically ensured that null could creep in almost anywhere.

Allowing a type to be null should always be opt-in. It still bothers me that I have to put NOT NULL in almost every SQL column definition because the SQL spec has columns default to being nullable. Ugh. At least SQL does allow me to choose nullable vs non-nullable, unlike Java.

Re: Retrofitting null-safety onto Java at Meta

#78
post #28
post #21

It's so sad that Java 8 had the chance to really fix the null problem, but gave us only the half-assed `java.util.Optional `. Rather than implementing optional values at the language level, it's just another class tossed into the JRE. This is perfectly legal code, where the optional wrapper itself is null: Optional getMiddleName() { return null; }

It may have been hoped for, but it was an unrealistic hope. They couldn't have fixed it while retaining backward compatibility.

> They couldn't have fixed it while retaining backward compatibility.

Opt-ins exist. That's what .net ended up doing: by default the language uses "ubiquitous" nullability, but you can enable reference nullability support at the project or file level.

If you do that, references become non-nullable, and have to be explicitly marked as nullable when applicable.

Re: Retrofitting null-safety onto Java at Meta

#79
post #63

Earlier quoted context omitted.

Other jvm languages compile to the byte code and fix this by inlining the optional transparently. What you mean by “at a language level” would break the byte code for jars compiled with older jdks.

Breaking backward compatibility is not the end of the world.

It might not be, but is damn close to it.

Re: Retrofitting null-safety onto Java at Meta

#80

This is just covering up design problems. NPEs show you were you have design deficiencies. If you have getAccount().getContact().getPhoneNumber() and contact is null, you'll get an NPE. The question shouldn't be: "How do I shove the NPE under the rug for the next 1337 coder to deal with?", the question should be: "How did I initialize an Account without a Contact?"

> getAccount().getContact().getPhoneNumber() Every time I see people "deal" with this problem, it looks like this: if (getAccount() != null && getAccount().getContact() != null && getAccount().getContact.getPhoneNumber() != null) { // do something } // don't put an else condition in, just keep going and let the program // produce the wrong result in a confusing way when it happens in production I actually blame rampa…

You mention code generation as a problem, but it is actually a solution as well for this particular problem, I have really grown on mapstruct, where you create an interface declaratively specifying what field maps to what, and it will generate at compile time fast, efficient, correct code you might write by hand.
Post reply on HN