Live data from Hacker News

Retrofitting null-safety onto Java at Meta

engineering.fb.com

61–70 of 230 posts

Re: Retrofitting null-safety onto Java at Meta

#61

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?"

It's sad because while I don't think the second concern is so big, the first half of your comment is deceptively important, but this is a conversation that really difficult to have.

I've brought it up when using Swift and Kotlin and it takes so much energy for people to realize that safety operators, which feel really really good to use, accidentally sweep up major issues

People assume you're missing something when you explain that they need to get more comfortable with force unwrapping (which is intentionally introducing a NPE)

-

But for example, if you have getAccount().getContract().getPhoneNumber() so you can show it in a settings page, you should not throw an NPE. You can easily correct the issue in a non-invariant breaking way by say defaulting to "" in the UI.

But if you have getAccount().getContract().setSomeFieldWithRealWorldImportance(true), you should either be force unwrapping or returning a Result type, and ensuring someone is actually handling it with a hard stop on the user.

The problem is reality is often much more subtle than "doSomethingImportant()".

For example, I worked on an iOS app that was used for medical work, and one habit iOS devs had was wrapping access to weak references to objects with a null safety:

So they were super comfortable writing things equivalent to viewController?.showSomeDialog()

because in most situations crashing over lifecycle issues is a bad idea... but here we could be creating incorrect output in a highly sensitive situation.

"someDialog" could be "Drug interaction between X and Y detected" for example, but the mental patterns wouldn't detect that a safety operator was hiding that.

It was better for the app to crash than silently hide that information, since at least then it'd be known the app was in an invalid state.

-

Now the problem is here devs start to think "well I'm not making medical apps" or "well I wouldn't make that mistake"...

But go through any moderately large codebase and you will find important user actions that silently fail where a crash would actually serve the user better.

It's how to convince people that a hard crash can ever be good though.

Re: Retrofitting null-safety onto Java at Meta

#62
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
    }

Re: Retrofitting null-safety onto Java at Meta

#63
post #43

Java has so many deficiencies in its design that so many frameworks are invented to cover its flaws. Just give a real Optional type at a language level. It’s clearly possible in other JVM languages.

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.

Re: Retrofitting null-safety onto Java at Meta

#66
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; }

I wonder if the plan is to add syntactic sugar for Optional in a future version.

It wouldn’t be compatible with regular nullable references.

Re: Retrofitting null-safety onto Java at Meta

#67
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?

Re: Retrofitting null-safety onto Java at Meta

#68

Earlier quoted context omitted.

> 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…

Surprised that guard clauses weren't mentioned here yet, you could also write ``` if (account == null) { throw NoAccountException } if (account.contact == null) { throw AccountWithoutContactException } if (account.contact.phoneNumber == null) { throw ContactWithoutPhoneNumberException } // do stuff here ```

That would be way better, but I've never seen it.

Re: Retrofitting null-safety onto Java at Meta

#69
I have been writing Java for money for more than ten years and never ever have I had non-trivial problems with null. Less than one percent of the bugs I fixed were caused by nullpointers, less than one percent of write-deploy-test loops were caused by it.

I either have code that can't be null (e.g. getters of lists that create a list if the field is null, outright validation before usage), code where null has a desired meaning that must be handled (new JPA entity with no key yet) or code where the Nullpointer will lead to a client/user/implementor caused bad request style response.

What the hell are you guys doing for you to spend significant amounts of time on NullpointerExceptions?

On the same note, I didn't understand the inclusion of Optional in Java. Always felt like some annoying special flavor type of custom Java nuisace like vavr or jooq.

Re: Retrofitting null-safety onto Java at Meta

#70
post #31
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; }

What do you mean by had a chance? That chance isn't gone. This area is under investigation, and when we have a solution we like, we'll implement it. We can't address all issues at once. Optional isn't half-assed because it was never envisioned as a general solution to the null problem. It's simply an interface that's useful in streams and other similar cases for method return values, and it does the job it was intend…

So then there is language-level Optional and library-level Optional?
Post reply on HN