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

#1361 Add eo-runtime dependency even if foreign dependencies are absent #1357

Merged
merged 19 commits into from
Nov 1, 2022

Conversation

volodya-lombrozo
Copy link
Member

@volodya-lombrozo volodya-lombrozo commented Oct 20, 2022

Closes: #1361

I've added one more step in ResolveMojo. It adds runtime dependency if it is absent.
That solution allows build EO programs without foreing objects.

@volodya-lombrozo
Copy link
Member Author

@mximp @yegor256 pls, take a look

@mximp
Copy link
Contributor

mximp commented Oct 21, 2022

@volodya-lombrozo can we squash commits?

@mximp
Copy link
Contributor

mximp commented Oct 21, 2022

@volodya-lombrozo please run the build with Qulice locally.

@volodya-lombrozo
Copy link
Member Author

volodya-lombrozo commented Oct 21, 2022

@volodya-lombrozo please run the build with Qulice locally.

[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------

/**
* Check if runtime dependency is absent.
* @param deps Dependencies
* fixme: We are using hardcoded version of RuntimeDependency.
Copy link
Contributor

Choose a reason for hiding this comment

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

@volodya-lombrozo I suppose this needs to be a puzzle?

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've tried to create a puzzle, but it complains that I have to link to some issue. As far as I know, I have to put current issue #35, but we are not in eoc repository. eo repository has it's own #35 issue.

Copy link
Contributor

@mximp mximp Oct 21, 2022

Choose a reason for hiding this comment

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

I've tried to create a puzzle, but it complains that I have to link to some issue. As far as I know, I have to put current issue #35, but we are not in eoc repository. eo repository has it's own #35 issue.

In this case we must create new issue within eo repository since it is a fix for EO. And link this PR to EO issue.

Copy link
Member Author

@volodya-lombrozo volodya-lombrozo Oct 21, 2022

Choose a reason for hiding this comment

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

New issue #1361 in eo repo

Copy link
Member Author

Choose a reason for hiding this comment

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

Fixed

@@ -194,6 +194,7 @@ private Collection<Dependency> deps() throws IOException {
tojo.set(AssembleMojo.ATTR_JAR, coords);
}
this.checkConflicts(deps);
addRuntimeDependency(deps);
Copy link
Contributor

Choose a reason for hiding this comment

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

@volodya-lombrozo wrong style - should be called via class name.

Copy link
Member Author

Choose a reason for hiding this comment

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

Fixed

*
* @since 0.28.11
*/
final class RuntimeDependency {
Copy link
Contributor

Choose a reason for hiding this comment

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

@volodya-lombrozo Since it's specific to EO runtime - I would call it EoRuntime

Copy link
Member Author

Choose a reason for hiding this comment

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

Renamed to EoRuntimeDependency

* @param other Other dependency
* @return True if other dependency is the eo-runtime dependency
*/
boolean theSameAs(final Dependency other) {
Copy link
Contributor

Choose a reason for hiding this comment

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

@volodya-lombrozo Could be simplified to same

Copy link
Member Author

Choose a reason for hiding this comment

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

Renamed

*
* @return Maven Dependency
*/
Dependency toDependency() {
Copy link
Contributor

Choose a reason for hiding this comment

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

@volodya-lombrozo Could be simplified to dependency

Copy link
Member Author

Choose a reason for hiding this comment

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

Renamed

fix(objectionary#35): add RuntimeDependency to classpath if it's absent

fix(objectionary#35): add test for empty dependencies situation

fix(objectionary#35): make all tests pass

fix(objectionary#35): add todo mark for hardcoded version of RuntimeLibrary

fix(objectionary#35): move all binary expressions to start of a line

fix(objectionary#35): don't align chained method calls

fix(objectionary#35): fix all linter mistakes in ResolveMojoTest

fix(objectionary#35): fix some linter mistakes in MockMavenCentral

fix(objectionary#35): fix all linter mistakes in MockMavenCentral

fix(objectionary#35): fix all linter mistakes in ResolveMojo

fix(objectionary#35): fix all linter mistakes in RuntimeDependency

fix(objectionary#35): correct todo for pdd

feat(objectionary#35): fix linter problems in comments

feat(objectionary#35): fix all codacy complains
@volodya-lombrozo
Copy link
Member Author

@volodya-lombrozo can we squash commits?

Done

toDependency -> dependency

theSameAs -> same

RuntimeDependency -> EoRuntimeDependency

RuntimeDependency -> EoRuntimeDependency

use classname for static function call
@volodya-lombrozo volodya-lombrozo changed the title #35 Add eo-runtime dependency even if foreign dependencies are absent #1361 Add eo-runtime dependency even if foreign dependencies are absent Oct 21, 2022
* @param dependency Dependency
* @return True if dependency is runtime dependency
*/
private static boolean isRuntimeDependency(final Dependency dependency) {
Copy link
Contributor

Choose a reason for hiding this comment

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

@volodya-lombrozo This can be inlined. I believe no need in separate static method.

Copy link
Member Author

Choose a reason for hiding this comment

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

Done

* @return True if dependency is runtime dependency
*/
private static boolean isRuntimeDependency(final Dependency dependency) {
return new EoRuntimeDependency().same(dependency);
Copy link
Contributor

Choose a reason for hiding this comment

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

@volodya-lombrozo May we create only one instance of EoRuntimeDependency and reuse it?

Copy link
Member Author

Choose a reason for hiding this comment

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

Done

@mximp
Copy link
Contributor

mximp commented Oct 21, 2022

@volodya-lombrozo looks good to me.
@yegor256 please merge (if no comments from your side).

@yegor256
Copy link
Member

yegor256 commented Oct 22, 2022

@volod looks very good, but I have a few questions. First, why do we need to create a new class EoRuntimeDependency if we already have Dependency class form Maven? In general, keep a simple rule in mind: if your class doesn't implement any interfaces -- you most probably are doing something wrong. It seems that you only need equals from this new class. Make this equals a new class, or just a new method. But EoRuntimeDependency seems to be a pretty procedural bag of data.

Second, MockMavenCentral has two public methods, while it implements an interface. This is again a mistake in OOP. If you implement a type/interface, you DON'T add anything new to the surface of the object. The method assertLastDownloadedDependencyAndPathEquals (aside from the fact that the name is super ugly :) must be taken away from this class and be implemented as a new Hamcrest assertion (instance of Assertion), I believe.

@volodya-lombrozo
Copy link
Member Author

@yegor256 pls, take a loot at the last changes. I’ve change MockMavenCentral class as you suggested and removed the EoRuntimeDependency.

As for EoRuntimeDependency, It definitely looks like a “bag with data” for now, I agree. But in the future I think we will Implement something like HttpEoRuntimeDependency or ConstantEoRuntimeDependency or ConfigEoRuntimeDependency - all of them will implement their own way of retrieving a eo runtime dependency from different sources. All of that classes will have one public interface method toMavenDependency and a common interface of cource.

Also, it’s a quite dangerous to use Dependency class directly, because it has a bad architecture (not an OOP style at all) which influences a lot on overall program design (please, take a look on that code). Moreover, we can’t change that class. I think it’s better to encapsulate it and to use something our own with a better design.

@@ -194,6 +194,7 @@ private Collection<Dependency> deps() throws IOException {
tojo.set(AssembleMojo.ATTR_JAR, coords);
}
this.checkConflicts(deps);
ResolveMojo.addRuntimeDependency(deps);
Copy link
Member

Choose a reason for hiding this comment

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

Copy link
Member Author

Choose a reason for hiding this comment

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

In order to obrain the issue I had to add a few private static classes. Please, take a look at AllDependencies and UniqueDependencies classes.

* or from config files.
*/
private static void addRuntimeDependency(final Collection<Dependency> deps) {
final RuntimeDependencyEquality runtime = new RuntimeDependencyEquality();
Copy link
Member

Choose a reason for hiding this comment

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

Copy link
Member Author

Choose a reason for hiding this comment

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

Fixed

@yegor256
Copy link
Member

yegor256 commented Oct 23, 2022

@volodya-lombrozo please, forgive me for being picky. I think that MockMavenCentral is over-design in this case. Here is why: The live class Central goes to Maven Central, finds the necessary .jar file, downloads it and unpacks into a given directory. You want to check that your class, that is using Central, is asking it to download and unpack the right .jar. The best and and simplest approach would be to create DummyCentral class, which only creates an empty directory in the required path. Then, you just check the presence of such directory in your tests and that's it.

What you are doing now with encapsulating mutable structures in MockMavenCentral and then checking their content afterwards is "asserting on side-effect" -- not a perfect object design.

@volodya-lombrozo
Copy link
Member Author

@volodya-lombrozo please, forgive me for being picky. I think that MockMavenCentral is over-design in this case. Here is why: The live class Central goes to Maven Central, finds the necessary .jar file, downloads it and unpacks into a given directory. You want to check that your class, that is using Central, is asking it to download and unpack the right .jar. The best and and simplest approach would be to create DummyCentral class, which only creates an empty directory in the required path. Then, you just check the presence of such directory in your tests and that's it.

What you are doing now with encapsulating mutable structures in MockMavenCentral and then checking their content afterwards is "asserting on side-effect" -- not a perfect object design.

I've removed MockMavenCentral and added DummyCenral as you suggested. Please, check.

*
* @since 0.28.11
*/
final class LastPathSame extends TypeSafeMatcher<Path> {
Copy link
Member

Choose a reason for hiding this comment

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

@volodya-lombrozo this class is redundant now, right?

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes, I've just forgot to remove the class. Done.

*
* @since 0.28.11
*/
final class LastDependencySame extends TypeSafeMatcher<Dependency> {
Copy link
Member

Choose a reason for hiding this comment

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

@volodya-lombrozo this class is not needed anymore, right?

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes, I've just forgot to remove the class. Done.

@yegor256
Copy link
Member

@volodya-lombrozo check again, please. Looks like these two matchers are not needed anymore.

@volodya-lombrozo
Copy link
Member Author

@yegor256 can you merge the PR, please? If everything is fine, of course.

volodya-lombrozo and others added 5 commits October 31, 2022 11:54
# Conflicts:
#	eo-maven-plugin/src/test/java/org/eolang/maven/ResolveMojoTest.java
# Conflicts:
#	eo-maven-plugin/src/main/java/org/eolang/maven/ResolveMojo.java
prepare for refactoring

add DcsNoOneTransitive

make all tests pass

clean ResolveMojo

add puzzle for tests for DcsNoOneHasTransitive

refactor DcsNoOneHasTransitive

fix some linter mistakes

fix some linter mistakes

fix some linter mistakes

fix some linter mistakes
@volodya-lombrozo
Copy link
Member Author

Updates for that PR

Sine we implemented Dependencies interface in that PR. It’s convenient for that task to use the same approach with new classes:

DcsWithRuntime - adds Runtime dependency if it absents

DcsWithoutConflicts - checks conflicts (previously that class was a static method in ResolveMojo)

DcsNoOneHasTransitive - decorator to check all dependencies for transitive dependencies (previously it was a static method in ResolveMojo)

@mximp @yegor256 please, check and merge if you don't have any objections.

final Dependencies delegate,
final Func<Dependency, Dependencies> transitive
) {
this.ignore = ignore;
Copy link
Member

Choose a reason for hiding this comment

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

Copy link
Member Author

Choose a reason for hiding this comment

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

@yegor256 fixed.

*
* @since 0.28.11
*/
final class DcsOf implements Dependencies {
Copy link
Member

Choose a reason for hiding this comment

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

@volodya-lombrozo what this class is for? Where and why Collection<Dependency> is not good enough?

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 wanted to make it more obvious. We can't use it directly in the next construction:

           new DcsNoOneHasTransitive(
                        this.ignoreTransitive,
                        dcs,
                        ....
           )

because Collection<org.apache.maven.model.Dependency> != Dependencies. But, of course, we can use it this way:

           new DcsNoOneHasTransitive(
                        this.ignoreTransitive,
                        dcs::iterator,
                        ....
           )

I will fix it. Thank you.

Copy link
Member Author

Choose a reason for hiding this comment

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

@yegor256 fixed.

import org.apache.maven.model.Dependency;

/**
* RuntimeDependencyEquality is a class for checking if dependency is a runtime dependency.
Copy link
Member

Choose a reason for hiding this comment

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

@volodya-lombrozo are you sure this is an accurate description of functionality here? It looks wrong to me.

Copy link
Member Author

Choose a reason for hiding this comment

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

@yegor256 fixed.

);
} catch (final IOException ex) {
throw new IllegalStateException(
String.format("DummyCentral can't save dependency %s by path %s", dependency, path),
Copy link
Member

Choose a reason for hiding this comment

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

@volodya-lombrozo the information about the originator of the exception is in stacktrace. No need to add this noise. Just say "Can't save '%s' to '%s'". In general, the shorter your messages, the better. They must be short, but contain maximum information.

Copy link
Member

Choose a reason for hiding this comment

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

@volodya-lombrozo moreover, if I remove this class tomorrow, I most probably will forget to rename it in the text

Copy link
Member Author

Choose a reason for hiding this comment

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

@yegor256 fixed

make exception description shorter

change the description of RuntimeDependencyEquality

remove redundant class

don't use configurable objects

fix all linter mistakes
@SuppressWarnings("PMD.AvoidCatchingGenericException")
private boolean hasTransitive(final Dependency dep) {
try {
return new LengthOf(
Copy link
Member

Choose a reason for hiding this comment

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

@volodya-lombrozo use Unchecked from Cactoos, to avoid exception catching

Copy link
Member Author

Choose a reason for hiding this comment

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

@yegor256 fixed.

)
);
if (!conflicts.isEmpty()) {
final String msg = String.format(
Copy link
Member

Choose a reason for hiding this comment

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

@volodya-lombrozo this is a bad practice: to do both logging and throwing. Pick one.

Copy link
Member Author

Choose a reason for hiding this comment

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

@yegor256 I've chosen the exception. Done.

private Dependencies dependenciesOf(final Collection<Dependency> all) {
final Dependencies dependencies;
if (this.ignoreTransitive && this.ignoreVersionConflicts) {
dependencies = new DcsWithRuntime(all::iterator);
Copy link
Member

Choose a reason for hiding this comment

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

@volodya-lombrozo looks like code duplication to me. You use DcsWithRuntime everywhere in each if. Maybe it's better to make dependencies mutable?

Copy link
Member Author

Choose a reason for hiding this comment

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

@yegor256 done.

Files.createDirectories(path);
Files.createFile(
path.resolve(
String.format("%s-%s.jar", dependency.getArtifactId(), dependency.getVersion())
Copy link
Member

Choose a reason for hiding this comment

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

@volodya-lombrozo you ignore dependency.getClassifier(), why? maybe it's better to use it too?

Copy link
Member Author

Choose a reason for hiding this comment

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

@yegor256 added.

@yegor256
Copy link
Member

yegor256 commented Nov 1, 2022

@volodya-lombrozo a few more comments from me, see above

use unchecked classes inside DcsNoOneHashTransitive

use unchecked classes inside DcsNoOneHashTransitive

remove duplicated logging

remove code duplication inside ResolveMojo

use classifier for jar name in DummyCentral
@volodya-lombrozo
Copy link
Member Author

@yegor256 I've applied all your suggestions above. Please, merge if you don't have any objections.

@yegor256
Copy link
Member

yegor256 commented Nov 1, 2022

@rultor merge

@rultor
Copy link
Contributor

rultor commented Nov 1, 2022

@rultor merge

@yegor256 OK, I'll try to merge now. You can check the progress of the merge here

@rultor rultor merged commit a2a898d into objectionary:master Nov 1, 2022
@rultor
Copy link
Contributor

rultor commented Nov 1, 2022

@rultor merge

@yegor256 Done! FYI, the full log is here (took me 8min)

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.

Add eo-runtime dependency for all eo programs
4 participants