Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove redundant requireNonNull when using config objects #13940

Conversation

findepi
Copy link
Member

@findepi findepi commented Aug 31, 2022

Config objects are mutable, therefore they are always unpacked in a
constructor. Thus, they do not require requireNonNull, as since Java's
implicit NullPointerException message will be as good.

@cla-bot cla-bot bot added the cla-signed label Aug 31, 2022
@findepi findepi force-pushed the findepi/remove-redundant-requirenonnull-when-using-config-objects-b71471 branch from ca8ddcd to c620a6f Compare August 31, 2022 12:02
@github-actions github-actions bot added jdbc Relates to Trino JDBC driver tests:hive labels Aug 31, 2022
@findepi findepi force-pushed the findepi/remove-redundant-requirenonnull-when-using-config-objects-b71471 branch from c620a6f to a7a6186 Compare September 5, 2022 14:21
@findepi findepi requested review from losipiuk and hashhar September 5, 2022 14:21
@@ -27,7 +26,7 @@

public CompositeRedirectHandler(List<ExternalRedirectStrategy> strategies)
{
this.handlers = requireNonNull(strategies, "strategies is null")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a bit controversial as with this change you can remove explicit requireNotNull because there is a.call(). But if later on a.call() is removed and a is used below, being passed somewhere, it is hard to notice that requireNotNull should be
reintroduced. Sth like in this snippet

{
  requireNotNull(a, "as is null).someCall();
....
  doSomething(a);
}

I am not saying that this is showstopper for this PR. Just sth to think about.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's a good point & something I was also concerned about.

Now it's a question to Maintainers for how we review new code

If we don't require technically redundant requireNonNull in new code, we should be OK removing it from existing code. @losipiuk would you agree with this one?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd personally argue to keep it - our goal is to make code more readable and maintainable even if there is some marginal additional cost when writing the code.

Code can change in future and what fails with a nice NPE message today may fail in not so nice ways in future. The current "rule" of always use rnn in constructors is simple and easy to follow for both authors and reviewers IMO.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know whether we have universal broad agreement, but I think we should be OK removing requireNonNull for config objects. That's because config objects are not supposed to be assigned to a field, so a code that takes a config, but doesn't read from it (yet), is usually a wrong code.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

our goal is to make code more readable

As readability goes I actually think that code without explicit rnn is more readable. After all, this is just a boilerplate. There is a general rule that objects passed as arguments are expected to be not null unless explicitly marked as @Nullable.
I think that for common cases like wrapping collection passed via argument using Immutable*.copyOf or Optional.map we can live without rnn.
For less obvious cases (multiple uses of object where some of those are calls of the method on object) I would keep explicit rnn.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(quality of error message depends on validation withing someMethod, but I think we should not assume this is good).

The calling code and doSomething are equally matured code bases. It's not parent-child relationship, we shouldn't feel overly responsible for other methods.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(quality of error message depends on validation withing someMethod, but I think we should not assume this is good).

The calling code and doSomething are equally matured code bases. It's not parent-child relationship, we shouldn't feel overly responsible for other methods.

I tend to disagree. Often we have little control over the doSomething. It may be an external library we just have to use. An extra check before the call may make debugging significantly easier if all we end up with is logged exception stacktrace (which may be useful or not).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't pass config objects to external libraries.

i agree that in some cases we may get a somewhat worse message
i think that overall the increased readability is worth it.
these rnn's were kind of necessity, but they don't help read the code

Copy link
Member

@hashhar hashhar Sep 10, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think as long as we only avoid rnn for config objects it is safer. But while reviewing let's make sure others don't copy the missing rnn to other types of objects (since there's no way for the code to indicate to future writer why rnn was ok to skip). Feel free to merge this - I don't feel very strongly about this but will keep eye open for future PRs.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think as long as we only avoid rnn for config objects it is safer. But while reviewing let's make sure others don't copy the missing rnn to other types of objects

i admit i removed more rrn than just config objects (hence two separate commits, something i forgot about).
but those other removals are safe too.

I am quite convinced that we are not going to require rnn around resourceProviderConstructorArg in new code like

this.resouce = resourceProviderConstructorArg.newResource()

and therefore i am convinced this is a fine change.

let me merge as is and see how it goes.

i am absolutely fine restoring some rnn whenever we find that some exc messages aren't informative enough.

Config objects are mutable, therefore they are always unpacked in a
constructor. Thus, they do not require `requireNonNull`, as since Java's
implicit NullPointerException message will be as good.
The `requireNonNull` call did not allow the tools to report an unused
argument, but these were actually unused.
`requireNonNull(var, "var is null").foo()` is the classical case where
Java's current implicit NullPointerException message is equally good.
@findepi findepi force-pushed the findepi/remove-redundant-requirenonnull-when-using-config-objects-b71471 branch from a7a6186 to 64c40b1 Compare September 9, 2022 14:33
@findepi
Copy link
Member Author

findepi commented Sep 9, 2022

(just rebased to resolve a conflict)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
cla-signed jdbc Relates to Trino JDBC driver
Development

Successfully merging this pull request may close these issues.

3 participants