Le lun. 5 août 2024 à 14:07, Martin Desruisseaux
<martin.desruisse...@geomatys.com> a écrit :
>
> Maven 4 has two very similar public interfaces for dependencies:
>
>   * Dependency
>   * DependencyCoordinate
>
> They both have groupId, artifactId, classifier, version, extension, type
> and scope. Differences that I observed are:
>
>   * Spelling: `Dependency.isOptional()` versus
>     `DependencyCoordinate.getOptional()`.

Right, though `Dependency.isOptional()` is of type `boolean`, while
`DependencyCoordinate.getOptional()` is of type `Boolean` (it is
nullable).

>   * Return type of the `getVersion()` method: `Version` versus
>     `VersionConstraint`.

Yes, that's expected.

>   * Methods present only in `DependencyCoordinate`:
>       o getExclusions()
>   * Methods present only in `Dependency`:
>       o getBaseVersion()
>       o isSnapshot()
>       o toCoordinate()
>
> The Javadoc does not explain those differences, neither why they exist.
> I suspect that `DependencyCoordinate` is the dependency has declared in
> the POM, while `Dependency` is the dependency effectively used after
> resolution. For example, with the range of versions
> (`VersionConstraint`) resolved to a single version (`Version`). Is that
> right? If so, would it make sense to add a `getPath()` method in
> `Dependency` since it has been resolved? I think it would make the API
> easier to understand compared to the current approach of using
> `Map<Dependency, Path>` returned by `DependencyResolverResult`.

We have ArtifactCoordinate, Artifact, DependencyCoordinate and
Dependency in the main API. We also have the
org.apache.maven.api.model.Dependency which is the object deserialised
from the POM.  That one is used to create DependencyCoordinate so that
they can be resolved.
Back to the 4 objects:
  - ArtifactCoordinate are used to locate artifacts in a repository,
it's basically a pointer to a file in maven repository
  - Artifact is the pointed artifact in the repository.  They are
created when *resolving* an ArtifactCoordinate which basically
download the artifact in the local repository
  - DependencyCoordinate is used to express a dependency
  - Node is the main output of the *dependency collection* process,
it's the graph of dependencies
  - Dependency is the output of the *collection* process, part of the
graph computed from one or more DependencyCoordinate, it's an artifact
+ type + scope

The main reason was to remove some ambiguities between the various
states that we have in the resolver API for Artifact and Dependency.
They may or may not have a resolved version (i.e. be an actual
pointer), may or may not be present in the local repository.  You
can't really use a non resolved Artifact for a resolved one, but the
resolver api does not provide any difference between those.

So, ArtifactCoordinate and DependencyCoordinate have a VersionRange,
while Artifact and Dependency have their version resolved.

> The reason why I ask is because there is path-derived information that
> need to be associated to a dependency, in particular `ModuleDescriptor`.
> With the current design, those information are provided by
> `DependencyResolverResult`. It would be more natural to have them in
> `Dependency`. I.e., instead of:
>
>   * DependencyResolverResult
>       o Map<Dependency, Path> getDependencies()
>       o Optional<ModuleDescriptor> getModuleModuleDescriptor(Path)
>       o Optional<String> getModuleName(Path)
>
> We could have:
>
>   * DependencyResolverResult
>       o Set<Dependency> getDependencies()
>   * Dependency
>       o Path getPath()
>       o Optional<ModuleDescriptor> getModuleModuleDescriptor()
>       o Optional<String> Dependency.getModuleName()
>
> The choice would determine the form of pull request #1625, which is
> needed for the new compiler plugin and will also be needed by at least
> javadoc, surefire and exec plugins.

The Path for a given Artifact can be retrieved using the
`ArtifactManager`, that was done to be similar to the
`ProjectManager`.

So the main problem is that one of the core design decision of the API
was to have immutable objects.  We could have a `ResolvedDependency`
which would inherit from `Dependency` and provide a `getPath()`
method.    Same for `Artifact`, where we could define a
`ResolvedArtifact`.  Or maybe add a `Resolved` interface with the
`getPath` method, which could be implemented by both ResolvedArtifact
and ResolvedDependency.  The `collect`

The collected graph contains Node and Dependency, while the resolved
dependencies are... resolved.  Which means that when building the
collected graph, the artifacts are not downloaded, only the POMs are
needed to build the graph.  When will those getModuleDescriptor() and
getModuleName() methods be made available ?

I'd like to keep the objects immutable though.

> As a side note, do we really need those interfaces to be independent?
> Couldn't we define Dependency as a subtype of DependencyCoordinate
> together with Artifact as a subtype of ArtifactCoordinate? It would
> remove the need for `toCoordinate()` methods and reduce a little bit the
> amount of wrappings between different kinds of objects in Maven core,
> which cost me hours of debugging (pull request #1621 is small, but was
> hard to find).

I find the outcome much less clear.  The same kind of objects are used
for multiple things, and it's very confusing.

>
>      Martin
>


-- 
------------------------
Guillaume Nodet

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscr...@maven.apache.org
For additional commands, e-mail: dev-h...@maven.apache.org

Reply via email to