Стоит ли полагаться на транзитивные зависимости в Maven, если они происходят из другого подмодуля моего родителя?
Предположим, что мы работаем над субмодулем ипотеки, и мы напрямую используем Google Guava
классы в коде модуля, но зависимость для guava
определяется в другом подмодуле того же родителя, и у нас есть доступ к классам Guava только с помощью транзитивной зависимости от "инвестиционного" модуля:
banking-system (parent pom.xml)
|
|-- investment (pom.xml defines <dependency>guava</dependency>)
|
|-- mortgage (pom.xml defiens <dependency>investment</dependency>)
Должны ли мы еще положить <dependency>
гуаве в ипотеку в pom.xml?
Минусы выглядят как дублирование в нашем pom.xml, плюсы: если кто-то, разрабатывающий "инвестиции", откажется от гуавы, то это не остановит успешную сборку нашего ипотечного подмодуля.
Если да, то что <version>
мы должны указать? (нет + <dependencyManagement>
в родительском пом?)
Если да, следует ли нам использовать <provided>
сфера в каком-то модуле тогда?
Примечание: имейте в виду, что я спрашиваю в конкретной ситуации, когда модули имеют общий родительский pom (например, будучи приложением в целом).
Может быть, эта структура была не лучшим примером, представьте:
banking-app
banking-core (dep.on: guava, commons, spring)
investment (dep.on: banking-core)
mortgage (dep.on: banking-core)
Должен еще Investment
явно объявить Spring, когда он использует @Component
и объявить Guava, если он использует гуавы LoadedCache
?
3 ответа
мы напрямую используем классы гуавы Google в коде модуля, но зависимость для гуавы определяется в другом подмодуле того же родителя, и у нас есть доступ к классам гуавы только с помощью транзитивной зависимости от модуля "инвестиции" [...] Должны ли мы по-прежнему помещать Гуава в ипотечный кредит pom.xml?
Да, вы должны объявить зависимость Google Guava в вашем модуле и не ожидать, что она будет доступна как транзитивная зависимость. Даже если это работает с текущей версией, это может не иметь места в более поздних версиях прямых зависимостей.
Если ваш код зависит от модуля, ваш код должен зависеть только напрямую от классов этого модуля, а не от транзитивной зависимости этого модуля. Как вы упомянули, нет никаких гарантий, что инвестиционный модуль будет по-прежнему зависеть от Guava в будущем. Вам необходимо указать эту зависимость либо в родительском файле pom.xml, либо в самом модуле, чтобы обеспечить его доступность без использования транзитивных зависимостей. Это не дублирование как таковое, как еще вы можете сказать Maven, что ваш модуль зависит от Guava?
Я не вижу ситуации, в которой соблюдаются минимальные передовые практики, если бы вам пришлось поступить иначе.
Если да, то что
<version>
мы должны указать? (нет +<dependencyManagement>
в родительском пом?)
Да, используя <dependencyManagement>
в родительском и используя <dependency>
в вашем дочернем модуле без версии лучше всего: вы убедитесь, что все ваши модули используют одну и ту же версию вашей зависимости. Поскольку ваши модули являются приложением в целом, это, вероятно, лучше, так как это позволит избежать различных проблем, таких как наличие разных версий одной и той же зависимости на пути к классам, что приведет к хаосу.
Даже если по какой-то причине один из ваших модулей, использующий одного и того же родителя, требует другой версии нашей зависимости, все равно можно будет переопределить версию для этого конкретного модуля, используя <version>
,
Если да, то должны ли мы использовать область действия в каком-то модуле?
Вероятно, нет, имея зависимость с compile
сфера - лучший выбор для большинства методов упаковки.
Однако у вас могут возникнуть ситуации, когда вам это нужно или вы предпочитаете делать это, например, если указанные модули требуют использовать версию, специфичную для среды выполнения, или если ваша модель развертывания или упаковки разработана так, как этого требует. Учитывая ситуацию, которую вы выставляете, оба варианта возможны, хотя в большинстве случаев в этом нет необходимости.
Да, объявить деп. Это не дублирование!!! То, что зависимости компиляции являются транзитивными, не предназначено разработчиком maven, это вызвано языком java. Потому что такие функции, как наследование классов, вызывают такое поведение. Ваше уже упомянутое "профи" является важным фактом. Смотрите примечание (*) в таблице переходных областей
Да, всегда объявляйте необходимые сторонние lib-версии в вашем родительском реакторе с зависимостью. Трудно находить ошибки из разных версий lib во время выполнения. Избегайте объявления версий сторонних библиотек в подмодулях больших реакторов, всегда используйте depMngs в родительском.
Нет, я бы использовал "предоставленный" только для зависимостей, предоставленных во время выполнения, в вашем примере tomcat/jboss/wildfly/.. для таких вещей, как servlet-api/cdi-api/. Но не для сторонних библиотек. Объявите "предоставленную" область действия как можно позже (т. Е. Войну / ухо вашего модуля развертывания), не входящую в ваши бизнес-модули. Это облегчает написание тестов. Например:
- инвестиции (зависит от объема гуавы := предоставляется)
- ипотека (зависит от инвестиций, но сам гуава не нужен)
-> ипотечный classpath не содержит гуавы. Если вы напишите модульный тест для ипотеки, в котором классы, участвующие в инвестициях, не будут работать -> вам нужно объявить как минимум guava с scope=test/runtime для запуска этих тестов...
Когда модуль использует стороннюю библиотеку, модуль также должен явно зависеть от этой библиотеки в своем файле pom.xml. Представьте, что другой проект должен использовать модуль "ипотека" и уже не зависит от Guava, он потерпит неудачу, например, когда юнит-тест натолкнется на путь кода, который включает Guava. Явная зависимость также охватывает вас от сценария, в котором вы реорганизуете модуль "инвестиции", чтобы он больше не использовал Guava. Ваш "инвестиционный" модуль должен быть независим от таких изменений в его зависимостях.
Всегда правильно явно перечислить ваши прямые зависимости. Когда дело доходит до версии, лучше сохранить это в dependencyManagement
раздел вашего родительского pom, поэтому все дочерние проекты наследуют эту (одну и ту же) версию.