Сборка проекта
Maven против Gradle, жизненный цикл Maven, области зависимостей и структура многомодульного проекта.
4 вопросов
JuniorТеорияОчень частоЧто Maven и Gradle делают для Java-проекта и чем они отличаются?
Что Maven и Gradle делают для Java-проекта и чем они отличаются?
Оба разрешают зависимости, компилируют, тестируют и пакуют проект. Maven декларативен: фиксированный жизненный цикл из pom.xml, поэтому любая сборка выглядит одинаково. Gradle программируем: DSL строит граф задач, с инкрементальной сборкой и build cache.
Типичные ошибки
- ✗Думать, что сборщик заменяет
javac, а не управляет им - ✗Считать, что декларативен Gradle, а Maven — скриптовый
- ✗Видеть в них только менеджеры зависимостей, забывая про жизненный цикл сборки
Уточняющие вопросы
- →Какие фазы жизненного цикла выполняются, когда вы набираете
mvn test? - →Что переиспользует build cache в Gradle из того, что обычная сборка Maven делает заново?
MiddleТеорияЧастоЧто означают области зависимостей Maven compile, provided, runtime и test?
Что означают области зависимостей Maven compile, provided, runtime и test?
Область решает, на какие classpath попадёт зависимость. compile — по умолчанию, есть везде и уезжает в артефакт. provided доступна при компиляции, но в рантайме её даёт контейнер. runtime нужна только для запуска; test видна лишь тестам.
Типичные ошибки
- ✗Считать, что
provided-зависимость пакуется в артефакт - ✗По привычке брать
compileдля servlet API или JDBC-драйвера - ✗Думать, что
test-библиотеку можно импортировать из продакшн-кода
Уточняющие вопросы
- →Какая область подходит для servlet API при деплое во внешний Tomcat?
- →Как
provided-зависимость ведёт себя транзитивно в зависимом модуле?
MiddleТеорияЧастоВ чём разница между mvn package и mvn install?
В чём разница между mvn package и mvn install?
Жизненный цикл Maven накопительный: install делает всё, что и package, плюс одну фазу. package компилирует, тестирует и кладёт артефакт в target/. install ещё и копирует его в локальный репозиторий ~/.m2, чтобы от него могли зависеть другие проекты.
Типичные ошибки
- ✗Думать, что
packageуже публикует артефакт в локальный репозиторий - ✗Считать, что
installотправляет артефакт в удалённый репозиторий — этоdeploy - ✗Полагать, что эти фазы независимы, а не накопительны
Уточняющие вопросы
- →Какая фаза публикует артефакт в общий удалённый репозиторий?
- →Почему зависимому проекту на той же машине иногда сначала нужен
install?
MiddleДизайнИногдаОдин Maven-модуль разросся: в нём REST-контроллеры, доменные сервисы, JPA-персистентность и ещё клиентский SDK, который две другие команды копируют себе. Любое изменение перекомпилирует и перетестирует всё целиком, а доменные классы начали импортировать контроллеры. Нужно перестроить это в многомодульную сборку при ограничениях: клиентский SDK поставляется отдельным артефактом и не тянет серверные зависимости; версии зависимостей согласованы между модулями; изменение одного модуля не должно вызывать полную пересборку остальных; слоистость обеспечивает сборка, а не договорённость. Как вы разложите модули и направление зависимостей и что не даст снова нарушить слоистость?
Один Maven-модуль разросся: в нём REST-контроллеры, доменные сервисы, JPA-персистентность и ещё клиентский SDK, который две другие команды копируют себе. Любое изменение перекомпилирует и перетестирует всё целиком, а доменные классы начали импортировать контроллеры. Нужно перестроить это в многомодульную сборку при ограничениях: клиентский SDK поставляется отдельным артефактом и не тянет серверные зависимости; версии зависимостей согласованы между модулями; изменение одного модуля не должно вызывать полную пересборку остальных; слоистость обеспечивает сборка, а не договорённость. Как вы разложите модули и направление зависимостей и что не даст снова нарушить слоистость?
Разбить по слоям: domain, persistence, web и отдельный client-sdk, под родительским POM, который фиксирует общие версии. Зависимости идут только внутрь, поэтому доменный класс с импортом контроллера перестаёт компилироваться. Каждый модуль — свой артефакт.
Типичные ошибки
- ✗Делить по техническому виду (интерфейсы/реализации), а не по слоям
- ✗Полагаться на именование пакетов вместо зависимостей модулей для слоистости
- ✗Объявлять версии в каждом дочернем модуле вместо родительского POM
Уточняющие вопросы
- →Почему цикл зависимостей между двумя модулями Maven невозможно собрать?
- →Как удержать модуль SDK свободным от транзитивных серверных зависимостей?