Skip to content

Conversation

@gnodet
Copy link
Contributor

@gnodet gnodet commented Oct 9, 2022

Adds ToolchainsBuilder and SettingsBuilder services.

@michael-o
Copy link
Member

Can you elaborate on the change? When was it broken?

@michael-o michael-o self-requested a review October 9, 2022 18:37
@gnodet
Copy link
Contributor Author

gnodet commented Oct 9, 2022

Can you elaborate on the change? When was it broken?

When the v4 api was merged, a few services were migrated to the new API, but that was a mistake because they are in use by plugins. This is the case for the ToolchainsBuilder and the MojoDescriptorCreator as reported on https://lists.apache.org/list.html?dev@maven.apache.org. Whether those are considered internal or part of the real api could be discussed, but they were broken, and now is not the time to break compatibility.
This PR then restores those services and add 2 new services to the new API to build settings and toolchains.

I need to investigate why the IT is failing.

@gnodet gnodet changed the title Restore compatibility on SettingsBuilder, ToolchainsBuilder and MojoDescriptorCreator [MNG-7553] Restore compatibility on SettingsBuilder, ToolchainsBuilder and MojoDescriptorCreator Oct 10, 2022
Copy link
Member

@michael-o michael-o left a comment

Choose a reason for hiding this comment

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

I see two general issues/questions here:

*/
@Nonnull
Collection<ProjectBuilderProblem> getProblems();
Collection<BuilderProblem> getProblems();
Copy link
Member

Choose a reason for hiding this comment

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

Stupid question: Is it really a problem with the builder or a problem with the build?

* @throws SettingsBuilderException If the effective settings could not be built.
*/
@Nonnull
SettingsBuilderResult build( @Nonnull SettingsBuilderRequest request );
Copy link
Member

Choose a reason for hiding this comment

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

Same question here.

* @return The global settings path or {@code null} if none.
*/
@Nonnull
Optional<Path> getGlobalSettingsPath();
Copy link
Member

Choose a reason for hiding this comment

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

Javadoc does not match code

* @return The global settings source or {@code null} if none.
*/
@Nonnull
Optional<Source> getGlobalSettingsSource();
Copy link
Member

Choose a reason for hiding this comment

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

Javadoc does not match code

* @return The user settings path or {@code null} if none.
*/
@Nonnull
Optional<Path> getUserSettingsPath();
Copy link
Member

Choose a reason for hiding this comment

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

Javadoc does not match code

* @return The user Toolchains path or {@code null} if none.
*/
@Nonnull
Optional<Path> getUserToolchainsPath();
Copy link
Member

Choose a reason for hiding this comment

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

Javadoc does not match code

* @return The user Toolchains source or {@code null} if none.
*/
@Nonnull
Optional<Source> getUserToolchainsSource();
Copy link
Member

Choose a reason for hiding this comment

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

Javadoc does not match code

.globalToolchainsSource( nonNull( globalToolchainsSource, "globalToolchainsSource can not be null" ) )
.userToolchainsSource( nonNull( userToolchainsSource, "userToolchainsSource can not be null" ) )
.build();
}
Copy link
Member

Choose a reason for hiding this comment

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

cannot

.globalToolchainsPath( nonNull( globalToolchainsPath, "globalToolchainsPath can not be null" ) )
.userToolchainsPath( nonNull( userToolchainsPath, "userToolchainsPath can not be null" ) )
.build();
}
Copy link
Member

Choose a reason for hiding this comment

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

cannot


@Override
public ProjectBuilderProblemSeverity getSeverity()
public BuilderProblemSeverity getSeverity()
Copy link
Member

Choose a reason for hiding this comment

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

Why isn't it BuilderProblem.Severity?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

No reason, I'll move it as an inner enum.

Copy link
Contributor

@elharo elharo left a comment

Choose a reason for hiding this comment

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

I haven't read the whole thin yet, but I tend to agree that Optional is at best as bad as null, and sometimes worse.


/**
* Gets the user properties to use for interpolation. The user properties have been configured directly by the user
* on his discretion, e.g. via the {@code -Dkey=value} parameter on the command line.
Copy link
Contributor

Choose a reason for hiding this comment

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

delete "on his discretion"
, --> ;


/**
* Gets the system properties to use for interpolation. The system properties are collected from the runtime
* environment like {@link System#getProperties()} and environment variables.
Copy link
Contributor

Choose a reason for hiding this comment

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

like --> such as

@Nonnull
SessionData getData();

/**
Copy link
Contributor

Choose a reason for hiding this comment

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

Javadoc additions to existing API are useful but can be included in a separate PR that is easier to approve.

*/
@Experimental
public enum ProjectBuilderProblemSeverity
public enum BuilderProblemSeverity
Copy link
Contributor

Choose a reason for hiding this comment

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

rename seems unnecessary

* @param session The {@link Session}, must not be {@code null}.
* @param source The {@link ProjectBuilderSource}, must not be {@code null}.
* @throws ProjectBuilderException if the project cannot be created
* @param source The {@link Source}, must not be {@code null}.
Copy link
Contributor

Choose a reason for hiding this comment

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

The --> the

* @param source The {@link ProjectBuilderSource}, must not be {@code null}.
* @throws ProjectBuilderException if the project cannot be created
* @param source The {@link Source}, must not be {@code null}.
* @throws ProjectBuilderException if the project can not be created
Copy link
Contributor

Choose a reason for hiding this comment

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

revert, cannot is one word

import org.apache.maven.api.annotations.Nonnull;

/**
* Builds the effective settings from a user settings file and/or a global settings file.
Copy link
Contributor

Choose a reason for hiding this comment

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

what is "effective settings"? How does that differ from other settings?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think "effective" here means an aggregation/merge of the global and user settings.

what is "effective settings"? How does that differ from other settings?

Copy link
Contributor

Choose a reason for hiding this comment

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

You need to put this in the docs, perhaps rewriting without the word effective

*
* @param request The settings building request that holds the parameters, must not be {@code null}.
* @return The result of the settings building, never {@code null}.
* @throws SettingsBuilderException If the effective settings could not be built.
Copy link
Contributor

Choose a reason for hiding this comment

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

if the effective settings could not be built

/**
* Builds the effective settings of the specified settings files.
*
* @param request The settings building request that holds the parameters, must not be {@code null}.
Copy link
Contributor

Choose a reason for hiding this comment

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

The --> the (per Oracle, API doc params do not begin with a capital letter

{
/**
* @param message The message to give.
* @param e The {@link Exception}.
Copy link
Contributor

Choose a reason for hiding this comment

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

don't repeat type information in doc comments. It's redundant. Instead explain what this exception is

@gnodet
Copy link
Contributor Author

gnodet commented Oct 11, 2022

I'm going to split that PR in 2. This one will be kept for the modifications on the v4 api : the new services and the related discussions.
I'll create a separate PR for the restoration of the compatibility.

@gnodet gnodet changed the title [MNG-7553] Restore compatibility on SettingsBuilder, ToolchainsBuilder and MojoDescriptorCreator [MNG-7553] Introduce SettingsBuilder and ToolchainsBuilder services Oct 11, 2022
Copy link
Member

@michael-o michael-o left a comment

Choose a reason for hiding this comment

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

Clean and simple, except for the comments of @elharo

@gnodet
Copy link
Contributor Author

gnodet commented Oct 11, 2022

I see two general issues/questions here:
I would rather have had those discussions when I asked for feedback on the API, but I suppose it's not too late ;-)
See my answers / reasoning below.

  • We have already briefly discussed the benefit/overrating of Optional. Can you explain why it makes sense here? I mean X != null is as good as here.

I slightly disagree. The main differences are that when using an Optional, the code carries the semantics and actually forces the caller to deal with it, whereas just if you simply return a value (the optionals are only used as return values), you have to get to the definition, read the javadoc, so that you can know if you need to deal with a possible null value. There are very often places in our code where you see both null checks and not and people end up adding null checks, just in case.

This also hurts code concision. A simple example found in the code:

        if ( getBaseVersionInternal() != null )
        {
            sb.append( getBaseVersionInternal() );
        }
        else
        {
            sb.append( versionRange.toString() );
        }

This could be rewritten as:

       sb.append( getBaseVersionInternal().orElse( versionRange.toString() ) );

This is actually related to the fact that the maven coding style is very sparse. I actually find that quite difficult to work with (even if I'm getting used to it). That may be due to the fact I'm working almost exclusively on a laptop, so the height of it is limited, and only seing 30-40 lines of code at the same time becomes a problem when nearly 50% of those don't really convey any semantic (being blank lines or braces usually). It means more time to scroll through the code back and forth to understand it. I don't like that. Streams are another way to get around empty lines, just because often, you simply don't need braces when using them, so you have 1 line instead of 3.

So generally speaking, the more semantic carried by the code, the better. I agree to not overuse Optional, I just don't think they are at this point. That said, the use of Nullable / NonNull annotations does help with semantics already, and I would not be opposed to removing them on requests / results objects.

I'm actually seeing the terms as a request to the X builder, the result returned by X builder, the exception thrown by X builder. We can't use quotes, but think about those as XBuilder's request, XBuilder's result, XBuilder's exception. I actually think those make more sense than what we have in other places. It's also easier to see the relationship between the service and its related request/result/exception.
Also, if you think each service usually throws its own exception. If we move the semantic to what action is performed instead of who does the action, the exceptions would have to be more shared between services. However (and that's still missing on some right now), a bunch of exception are used to carry the context in which the exception was thrown.

Another point that just came to my mind is that wording like DependencyCollectionRequest is not intuitive either: the term Collection in java is immediately associated to a... java.util.Collection, and not to the act of collecting...

@michael-o
Copy link
Member

I see two general issues/questions here:
I would rather have had those discussions when I asked for feedback on the API, but I suppose it's not too late ;-)
See my answers / reasoning below.

  • We have already briefly discussed the benefit/overrating of Optional. Can you explain why it makes sense here? I mean X != null is as good as here.

I slightly disagree. The main differences are that when using an Optional, the code carries the semantics and actually forces the caller to deal with it, whereas just if you simply return a value (the optionals are only used as return values), you have to get to the definition, read the javadoc, so that you can know if you need to deal with a possible null value. There are very often places in our code where you see both null checks and not and people end up adding null checks, just in case.

This also hurts code concision. A simple example found in the code:

        if ( getBaseVersionInternal() != null )
        {
            sb.append( getBaseVersionInternal() );
        }
        else
        {
            sb.append( versionRange.toString() );
        }

This could be rewritten as:

       sb.append( getBaseVersionInternal().orElse( versionRange.toString() ) );

This is actually related to the fact that the maven coding style is very sparse. I actually find that quite difficult to work with (even if I'm getting used to it). That may be due to the fact I'm working almost exclusively on a laptop, so the height of it is limited, and only seing 30-40 lines of code at the same time becomes a problem when nearly 50% of those don't really convey any semantic (being blank lines or braces usually). It means more time to scroll through the code back and forth to understand it. I don't like that. Streams are another way to get around empty lines, just because often, you simply don't need braces when using them, so you have 1 line instead of 3.

So generally speaking, the more semantic carried by the code, the better. I agree to not overuse Optional, I just don't think they are at this point. That said, the use of Nullable / NonNull annotations does help with semantics already, and I would not be opposed to removing them on requests / results objects.

This reasoning I can follow where Optional adds value. I don't like like to proclaim Optional to be the new null which is non sense. No objections here.

I'm actually seeing the terms as a request to the X builder, the result returned by X builder, the exception thrown by X builder. We can't use quotes, but think about those as XBuilder's request, XBuilder's result, XBuilder's exception. I actually think those make more sense than what we have in other places. It's also easier to see the relationship between the service and its related request/result/exception. Also, if you think each service usually throws its own exception. If we move the semantic to what action is performed instead of who does the action, the exceptions would have to be more shared between services. However (and that's still missing on some right now), a bunch of exception are used to carry the context in which the exception was thrown.

Another point that just came to my mind is that wording like DependencyCollectionRequest is not intuitive either: the term Collection in java is immediately associated to a... java.util.Collection, and not to the act of collecting...

Let me crunch on this. @elharo What is your opinion on the style here?

@michael-o michael-o self-requested a review October 13, 2022 11:56
@gnodet
Copy link
Contributor Author

gnodet commented Oct 25, 2022

This PR has been split with #820, #852, #853, #854 for ease of review.

@gnodet gnodet closed this Oct 25, 2022
@jira-importer
Copy link

Resolve #8332

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants