Live data from Hacker News

Retrofitting null-safety onto Java at Meta

engineering.fb.com

81–90 of 230 posts

Re: Retrofitting null-safety onto Java at Meta

#81

Or use Kotlin, it's near perfectly interoperable with Java and the acclamation period is measured in weeks if you're a Java dev

I tried Kotlin, and while I liked it, iterop was still somewhat annoying, Java's lambdas are better, using the Java 8 stream API is ugly, and the code ends up being similar enough that I'd rather use Java and avoid tooling hassles.

Re: Retrofitting null-safety onto Java at Meta

#82
post #32

Earlier quoted context omitted.

Don't people use @NonNull everywhere now? It's been a few years since I've programmed in Java but even then I feel like that was common practice.

Yes, it's always been possible to check for nulls at runtime. Personally I use notNull(..) over @NonNull since it actually fires when you expect it to (as opposed to whether your framework dispatcher interceptor trigger decided to invoke it)

isn't @NonNull just a syntactic sugar for adding checkNonNull() call as first statement to the function declaration in compile time, or am I mistaken? Just like lombok, it is supposed to generate code that checks null arguments, from what I know.

Re: Retrofitting null-safety onto Java at Meta

#83
post #31

Earlier quoted context omitted.

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?

If that happens, there would be language level nullability types that may supersede Optional if they indeed end up solving a strictly more general problem. It's not unheard of to have more general solutions supersede older, more specific ones. For example, the newly added pattern-matching features largely obviate the need for visitors, which are a pretty common pattern in libraries; or virtual threads, which largely obviate the need for many asynchronous APIs (and there are opposite examples, such as j.u.c locks, which followed the language's locks). That's the nature of evolution: sometimes there are surviving vestiges of the past.

Re: Retrofitting null-safety onto Java at Meta

#84
At a former workplace, someone had a great idea to collect and aggregate the logs of our software from across our test labs. At the time, the idea was a bit novel for a bunch of programmers and testers who shipped and didn't run their own software. The plan was to drive elimination of commonly logged errors through bug fixes or reducing the severity of the messages.

I was a lowly programmer, invited to a meeting of distinguished engineers and senior staff to review some of the findings from the log collections. When NPEs came up, their comment was that 'there should be zero NPEs' and that they would handle them punitively through reports to managers. So, I asked, "What's your recommendation to the developers to prevent the NPEs?". Silence, nothing. Findbugs existed at the time, and I believe JSR303 was in draft. Happy to report they decided to treat it the same as any other error or bug.

Re: Retrofitting null-safety onto Java at Meta

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

Don't people use @NonNull everywhere now? It's been a few years since I've programmed in Java but even then I feel like that was common practice.

Which @NonNull are you referring to, Lombok's? Or javax.annotation.NonNull, or something else?

Re: Retrofitting null-safety onto Java at Meta

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

Isn't Object itself (and any class) already an optional at the language level?

Either it's null, so has no value, or it's not null so has a value, and you can check for null-ness. What more is needed?

Seems like the opposite, a guaranteed non-null value at core language level, would be novel instead...

Re: Retrofitting null-safety onto Java at Meta

#89
post #45

We've been using `@Nullable` as Meta does in our code base for many years now (everything else is assumed to be non-null). Initially, we had CheckerFramework actually doing the checks at compile time... but eventually had to remove it because it's unstable, slow, has not kept up with Java evolution (we're on JDK 17, I think Checker still barely works on JDK 11) and also, because our IDE can be configured to flag erro…

> At the same time, we have adopted Kotlin as well. Interestingly, most of our developers prefer to stay on Java... not because they love Java, but because of familiarity and that they seem to think it's "good enough".

I have been using Kotlin on Android for a few years now, and really enjoy the extra expressiveness and conciseness that the language offers ... but have come to the conclusion its much easier to write unreadable kotlin code than java code.

One of the things I think makes Kotlin hard to read is scoping functions (apply/also/let/run/with). Based on their names alone, the newcomer can't tell what they do (I had to consult a table for weeks on whether they returned the original object, last expression, and whether they passed it, this, etc).

I do love these when used at the right place, right time, and "just enough" but I keep coming into contact with code that nests these 4-5 levels deep:

  aaa?.run {
    bbb?.run run2@ {
      ccc?.run {
        ddd?.run {
          this@run2.foo()
         // whats in scope here urgh
        }
      }
    }
  }
Other pathologies I see are making any method (foo), that operates on X, as an extension method X?.foo(). Then the namespace for X gets polluted with all these things.

One of the great things about Kotlin's nullability in the type system is the operators like ?. and ?: ... but often see code like this:

  aaa?.bbb?.ccc?.ddd()
Is it safe, yes, yes it is. It won't crash, but what happens if one of these is null, and should not be? There is nothing in Kotlin forcing people to write this way, but find Java's explicit checking of null made people think more of the "negative case" (throw an exception? etc)

Like anything else, I guess we could use linting rules, it comes to having good taste ... which is not in abundance.

What worries me the most though, is that in the beginning, Kotlin was mostly additive on Java. I read, in biological systems, adding is easier that changing or removing. It seemed like Effective Java + Typed Groovy. Now as Java has "last mover" advantage, and adopts the good parts of Kotlin, I am worried its not just additive, they need interop between different implementations (records vs data classes).

Re: Retrofitting null-safety onto Java at Meta

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

[deleted]
Post reply on HN