What Is Wrong with a Transitive Dependency

What is wrong with a transitive dependency?

I'll explain by an example:

-------------------------------------------------------------------
| Course | Field | Instructor | Instructor Phone |
-------------------------------------------------------------------
| English | Languages | John Doe | 0123456789 |
| French | Languages | John Doe | 0123456789 |
| Drawing | Art | Alan Smith | 9856321158 |
| PHP | Programming | Camella Ford | 2225558887 |
| C++ | Programming | Camella Ford | 2225558887 |
-------------------------------------------------------------------
  • If you have a Course you can easily get its Instructor so Course->Instructor.
  • If you have an Instructor you can't get his Course as he might be teaching different courses.
  • If you have an Instructor you can easily get his Phone so Instructor->Phone.

That means the if you have a Course then you can get the Instructor Phone which means Course->Instructor Phone (i.e. Transitive dependency)

Now for the problems:

  1. If you delete both the French and English courses then you will delete their instructor John Doe as well and his phone number will be lost forever.
  2. There is no way to add a new Instructor to your database unless you add a Course for him first, or you can duplicate the data in an Instructors table which is even worse.
  3. If Instructor John Doe changes his phone number then you will have to update all Courses that he teaches with the new info which can be very prone to mistakes.
  4. You can't delete an Instructor from your database unless you delete all the courses he teaches or set all his fields to null.
  5. What if you decide to keep the birth date of your instructors? You will have to add a Birth Date field to the Courses table. Does this even sound logical? Why keep an instructor information in the courses table in the first place?

Maven: Incorrect (and flaky) transitive dependency version

The v22 is three level deep and the v20 is two level deep. The Maven's dependency mediation choose the "nearest definition" which is the v20.

Dependency mediation - this determines what version of a dependency will be used when multiple versions of an artifact are encountered. Currently, Maven 2.0 only supports using the "nearest definition" which means that it will use the version of the closest dependency to your project in the tree of dependencies. You can always guarantee a version by declaring it explicitly in your project's POM. Note that if two dependency versions are at the same depth in the dependency tree, until Maven 2.0.8 it was not defined which one would win, but since Maven 2.0.9 it's the order in the declaration that counts: the first declaration wins.

"nearest definition" means that the version used will be the closest one to your project in the tree of dependencies, eg. if dependencies for A, B, and C are defined as A -> B -> C -> D 2.0 and A -> E -> D 1.0, then D 1.0 will be used when building A because the path from A to D through E is shorter. You could explicitly add a dependency to D 2.0 in A to force the use of D 2.0

Source: https://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html#Transitive_Dependencies

This SO answer can give you more detailed explanation about the reason behind the dependency mediation strategy: https://stackoverflow.com/a/43165652

You have two simple options:

  1. add the guava v22 to your pom to make it the nearest.
  2. add exclusion to the google truth dependency. There is an example here: https://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html#Dependency_Management

Not sure if this consistitues a transitive dependency

Transitive dependency occurs only if you have indirect relationship between more than 2 attributes that are not part of they key.

In your example, as you explained, the StaffID is part of your dependency, which is fine because it's the primary key.

Also you can look at this question that shows what is wrong with a transitive dependency. It could help put things into perspective.

In your table, if you delete staff member, you delete all the information (rightly so because you don't need it). If you leave phone number in a different table and, for instance, delete entry only in Staff, you're left with a wild phone number. But if your Staff table allowed multiple entries for the same person (but different departments) then the situation would be different.

Other sites that helped me in the past:

https://www.thoughtco.com/transitive-dependency-1019760
https://beginnersbook.com/2015/04/transitive-dependency-in-dbms/

Funnily they always follow the book example : )

How Java 9 modules solve problems associated with transitive dependencies?

When searching a module path for a module of a particular name, the module system takes the first definition of a module of that name. Version strings, if present, are ignored; if an element of a module path contains definitions of multiple modules with the same name then resolution fails and the compiler, linker, or virtual machine will report an error and exit. It is the responsibility of build tools and container applications to configure module paths so as to avoid version conflicts; it is not a goal of the module system to address the version-selection problem.

http://openjdk.java.net/jeps/261

In short, you can name your modules to have version specific strings as part of their names, but that's roughly it.

Maven transitive dependency problem

If the JUnit dependency in Project B has scope 'test' then I don't believe it will be visibile as a transitive dependency in Project A. See the table in Maven Introduction to the Dependency Mechanism: Dependency Scope.

Are conflicting transitive dependencies a serious issue in Maven?

Yes, such conflicts can be serious.

You don't know if there is an incompatible change in a dependency when comparing versions one with another (There shouldn't be when comparing minor versions, but who knows exactly?). Or maybe some dependency depends on a buggy behavior of another dependency. What if this bug has been fixed? That one module depending on the bug will fail to execute properly.

You should exclude conflicting dependencies (more likely excluding lower versions). For each exclusion you enter, you have to check, if there are incompatible changes between the excluded version and the version that is now in use. If that is the case you have to check dependencies that depend on that module, if they are affected by such changes.



Related Topics



Leave a reply



Submit