Сборка и зависимости — Примеры
Пример 1 — Откуда на самом деле пришла зависимость
Проект падает во время работы на классе, которого никто не объявлял в описании сборки, и команда спорит, какое изменение его принесло, хотя ниже объявлена всего одна библиотека. Покажите разрешённое дерево и назовите путь, по которому приходит класс.
# описание сборки, в собственном синтаксисе инструмента
dependencies {
implementation("com.example.reports:report-core:<version>")
}
Решение
+--- com.example.reports:report-core:<version>
| +--- com.example.json:json-core:<version>
| \--- com.example.logging:log-api:<old version> -> <new version>
\--- com.example.runtime:scheduling:<version>
# условное дерево: стрелка показывает версию, которую выбрал решатель
Решатель скачивает библиотеку, затем разрешает её собственные требования транзитивно, а когда две библиотеки просят разные версии третьей, выбирает одну — библиотека планирования в последней строке и есть источник, которого никто не объявлял. Однако какая версия победит — зависит от стратегии разрешения. Поэтому ответ влияет на поведение, а не только на компиляцию. Подстановка своих координат сохраняет пример рабочим образцом; ошибка — считать разрешённое дерево неизменным и никогда осознанно не исключать и не фиксировать версию.
Пример 2 — Сборка, которая меняется без изменений в исходниках
Две сборки одной и той же ревизии ведут себя по-разному, и единственная разница — день, когда они выполнялись. Объявление принимает любую подходящую версию. Сделайте сборку воспроизводимой.
dependencies {
implementation("com.example.reports:report-core:1.+")
}
Решение
dependencies {
implementation("com.example.reports:report-core:1.4.0")
}
# файл фиксации записывает разрешённый транзитивный набор рядом с собой,
# а обёртка фиксирует собственную версию инструмента сборки
Фиксация прямой зависимости, закрепление транзитивного набора и фиксация инструментария означают, что та же ревизия завтра разрешится в тот же артефакт, а каждое обновление станет осознанным действием с диффом для ревью. Опора на версию, установленную на машине одного разработчика, — дефект того же класса. Поэтому версия самого инструмента тоже должна лежать в репозитории. Ошибка — разрешать динамически и называть результат системой сборки.