×Закрыть

Переход с Maven на Gradle

Всем добрый день

Тема перехода с одной системы(в данном случае сборки) или библиотеки на другую достаточно обширна, а переход может быть весьма нетривиален.
Это может быть связано с разными версиями систем, мудренностью конфигурации или несовместимостью самих систем.

Я решил написать статью о том, как в базовом варианте перейти с Maven на Gradle. it-simulator.com/#/article/145
Тем более что я уверен, что многие уже прошли этот путь или пройдут его. Тем, кому непонятно, зачем переходить, могу предложить свою презентацию c недавнего доклада, где я описал самые существенные причины. www.slideshare.net/...​sons-to-migrate-to-gradle

Мне было бы очень интересно прочитать про случаи, когда такой переход тяжело дался и почему. Или например был невозможен.
Если у вас было что-то похожее, отпишитесь пожалуйста в комментариях. Также было было бы интересно послушать, почему вы решились на такой переход.

LinkedIn
Допустимые теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter
Допустимые теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter

2 сорта одного гуана

А теперь представим ситуацию, что у вас 170+ микросервисов и все их нужно где-то собирать и еще желательно унифицированно, потому что программистам хочется программировать, а не настраивать билд джобы на тимсити|дженкинсе etc. Вы один раз настраиваете тимплейты и погнали. Сборка ваших артефактов — вы просто об этом не думаете, у вас все настроено и работает во всех проектах одинаково. С гредлом гарантировать, что какой-то модный перец решил подпилить build.gradle нет. И в каждом новом проекте другой модный перец будет делать то, что лично он считает «элегантным решением». Да, у мейвена есть органичения, на эксемелях особо не попрограммируешь, но это же ограничение и является удобным инструментом по унификации сборки проектов. Вообще, тяжело сравнивать мейвен с гредлом — они совершенно разные и цели у них разные. А переводить мейвен проект на гредл, потому что гредл модный — это странная причина.

А теперь представим ситуацию, что у вас 170+ микросервисов и все их нужно где-то собирать и еще желательно унифицированно, потому что программистам хочется программировать, а не настраивать билд джобы на тимсити|дженкинсе etc. Вы один раз настраиваете тимплейты и погнали.

Сборка ваших артефактов — вы просто об этом не думаете, у вас все настроено и работает во всех проектах одинаково.

Сказка из страны наркоманов-гошников.

у нас сейчас на продакшене 170 сервисов в сервис дискавери зарегистрированы и есть еще пачка лигаси проектов. если для вас это наркоманство, то видимо у вас один большой монолит. не стоит по себе судить все сообщество.

А теперь представим ситуацию, что у вас 170+ микросервисов и все их нужно где-то собирать и еще желательно унифицированно

Суть микросервисов как раз в том что они разделены друг от друга и чем меньше у них общих зависимостей тем лучше.
Новый билд настраиватется на тимсити в пару кликов и для мавена и для гредла.

С гредлом гарантировать, что какой-то модный перец решил подпилить build.gradle нет. И в каждом новом проекте другой модный перец будет делать то, что лично он считает «элегантным решением». Да, у мейвена есть органичения, на эксемелях особо не попрограммируешь, но это же ограничение и является удобным инструментом по унификации сборки проектов.

«Полодой перец» — крачавчег: поправил билд скрипт, теперь пусть правит деплой (чтобы микросы работали их жизненый цикл должен быть внутри одной команды). Если чувак не полный уо, то научится понимать когда надо, а когда не надо вносить изменения.

Просто догадка: судя по описанию проблем, речь идет не про микросервисы, а про «распределенный монолит».

Новый билд настраиватется на тимсити в пару кликов и для мавена и для гредла.

Ну вот видите, уже ручной труд, а у нас билды и проекты по кнопке создаются.

Если чувак не полный уо

Всех не проконтролируешь.

судя по описанию проблем

Дело в том, что у нас нет проблем со сборкой проектов. Мы не правим ничего руками, а вы предлагаете решение, в котором каждый должен ходить и что-то где-то править руками. Не забывайте также про бас фактор в данном случае, если каждый ходит и шаманит себе сборку.

«распределенный монолит»

Гадаете по комментариям на доу? :) Проекты друг от друга не зависят, сборка в данном случае подразумевает — прогнать тесты, собрать джарку, собрать контейнер и отправить список нотификаций в нужные ресурсы. Мевеном мы на продакшен не деплоим :)

Ну вот видите, уже ручной труд, а у нас билды и проекты по кнопке создаются.

То есть вы ни разу не создавали билд в тимсити? :)

Если чувак не полный уо
Всех не проконтролируешь.

То есть у вас нет код ревью? Билд скрипт — это часть кода, то есть они должны проходить такое же ревью.

Мы не правим ничего руками, а вы предлагаете решение, в котором каждый должен ходить и что-то где-то править руками.

А если надо либу добавить? А если перегенерировать протобафы-или-типа-того? А если микросервис написан на скале или не дай бог питоне?

Интересен был вопрос, что лучше использовать, Gradle или Maven. Что я нагуглил про Maven, а именно его проблемы:
1. Проблема с транзитивными зависимостями из-за использования стратегии Nearest и невозможности использования других. У Gradle, кстати, c этим всё впорядке, начиная с версии 1.4 он поддерживает три стратегии для транзитивных зависимостей, с которыми можно нормально работать: Latest, Fail и Custom. Подробно в этой статье: habrahabr.ru/...​ompany/jugru/blog/191246
2. У Maven плохая документация, которая описывает 10% его функционала.
3. Что заметил сам, если посмотеть на репозитории обеих систем, то у Gradle все основные показатели примерно в 5 раз больше: количество коммитов, количество релизов, количество контрибуторов.
github.com/apache/maven
github.com/gradle/gradle

2. У Maven плохая документация, которая описывает 10% его функционала.

Как человек активно добавляющий кастомизации в гредловых скриптах, могу сказать:
С...ка! Та у гредла вообще, бл..., нет никакой ипучей документации!!
Документация по АПИ плагинов и компонетов очень убогая, приходится чуть ли не праспечатывать объекты по полям, чтобы понять что у него есть и как пробросить параметры, особенно есть есть подпроекты.

Что заметил сам, если посмотеть на репозитории обеих систем, то у Gradle все основные показатели примерно в 5 раз больше: количество коммитов, количество релизов, количество контрибуторов.

maven.apache.org/source-repository.html
Почитайте что такое ASF и как они работают. А на досуге можете подучать какое отношение метрики которые вы перечислили в контексте __использования__ того или иного тула.

Я думал Gradle — это наиболее стабильный и продвинутый сборщик, типа как Webpack в мире джеэса.

Maven — стандарт в legacy проектах. В новых проектах активнее используют Gradle, после того, как стало возможным использовать Kotlin для написания скриптов

Maven — стандарт в legacy проектах.

Нет. Maven — стандарт по умолчанию. Поскольку под него сделаны много корпоративных инфраструктур. Популярность гредла это не отменяет, но гредл не есть стандарт.

В новых проектах активнее используют Gradle, после того, как стало возможным использовать Kotlin для написания скриптов

Даже до котлина гредл был популярен (потому что всех занадоет ХМЛ).
Конечно, если составлять свое мнение о состоянии индустрии по конференциям, то можно прийти к выводам которые вы сделали. Но не надо забывать, что конференции — это больше шоу чем обмен опытом.

Это ваше личное мнение или вы можете сослаться на статистику?

Это ваше личное мнение или вы можете сослаться на статистику?

Это мой опыт. Интересно услышать ваш опыт, когда заказчик приходил с готовой под гредл инфраструктурой и отсекал любые попытки использовать что-то другое.

Но если вам нужна статистика то trends.google.com/...​&q=/m/04tj5z,maven,gradle

У каждого свой опыт, который разумеется обобщать наивно и бессмысленно. Могу привести статистику по открытым проектам в GitHub:

1) pom.xml — 4,167,195 code results
2) build.gradle — 4,320,155 code results

Могу привести статистику по открытым проектам в GitHub:

С любой статистикой есть одна проблема: нужно понимать числа которые получились.
Вы понимаете что такое ГитХаб? Вы понимаете какого рода проекты там лежат в открытом доступе?
Это норошо что вы хоть основываетесь не на конференциях :)

У каждого свой опыт, который разумеется обобщать наивно и бессмысленно.

Угу, надо уметь делать выводы из этого опыта. Поэтому я и спросил:

Интересно услышать ваш опыт, когда заказчик приходил с готовой под гредл инфраструктурой и отсекал любые попытки использовать что-то другое.

Если предположить что «В новых проектах активнее используют Gradle», то наверное случаии когда гдерл является технологическим ограничением встречались бы все чаще. Но вот я про такие ни разу не слушал.

В статье на хабре(habrahabr.ru/...​ompany/jugru/blog/191246) описывалось, что у Maven есть проблема с транзитивными зависимостя из-за возможности использования только одной стратегии, которая является неприемлемой, а у Gradle такой проблемы нет. Если полагаться на это, то я отдаю предпочтение Gradle. Что можете сказать по своему опыту, так ли это на самом деле, насколько часто возникают проблемы с транзитивными зависимостями в Maven и насколько они большие?

проблемы с транзитивными зависимостями, конечно же, есть у мавена. И это головная боль. Если продукт использует 100500 библиотек, то это большая головная боль. Но если есть опыт борьбы с этим все не так страшно, хотя болью все же остается.
Относительно офигенного Gradle приведу dummy пример, а вы скажите как эту проблему решить впринципе и как Gradle решил ее в частности:
— Ваш проект использует библиотеку ААА:1.4
— В ААА:1.3 есть метод addListener(? extends AAAListener param1, String dummyParam2)
— Вы решили добавить библиотеку ВВВ:1.0.1
— Библиотека ВВВ:1.0.1 использует ААА:1.3
— В ААА:1.3 метод addListener выглядил так addListener(? extends AAAListener param1, String dummyParam2) — я знаю что было бы обратно совместимо было бы все ок, но часто бывает не обратно совместимо увы

= когда загрузиться класлодер он загрузит класс где есть addListener, но так как у вас 2 джара разных версий с одинаковыми пакетами, то какой из них вы не знаете.
А это значит что ошибку вы получите в рантайме.
Из выходов:
— не использовать AAA
— не использовать ВВВ
— использовать версию ВВВ которая зависела на ААА:1.4 (если такая существует)
— использовать версию ААА которая используеться в ВВВ (если ваши нужды, система лицензирования и другие констрейны позволяют)
— законтрибьютить в ВВВ апгрейд версии ААА (тоже может быть проблематично)

А теперь представьте что у вас 25 зависимостей на библиотеки которые используют общий сет библиотек других OSS проектов, но в разных версиях. А этот сет в свою очередь тоже имеет зависимости на тот же сет.

Если кто-то объяснит как с этим бореться Gradle безе перепаковки джаров я буду мегаблагодарен за експириенс.
PS. Сам я Gradle еще не пробовал, все никак время не найду

— В ААА:1.3 есть метод addListener(? extends AAAListener param1, String dummyParam2)
— В ААА:1.3 метод addListener выглядил так addListener(? extends AAAListener param1, String dummyParam2)

А в чем разница с 1.4?

Copy past driven writing )
Должно быть
— В ААА:1.3 метод addListener выглядил так addListener(? extends AAAListener param1)

Ну во-первых, предсказать эту проблему никак нельзя, только увидев, как код упал в runtime.
Бороться с ней можно по-разному, идеальный вариант —

— использовать версию ВВВ которая зависела на ААА:1.4

Если это невозможно, то в своем проекте откатиться на AAA:1.3

Так где же магия грейдла с транзитивными зависимостями?

Gradle(да и вряд ли кто-то) может помощь, если в одном проекте нужны две бинарно несовместимые версии одной библиотеки.

А вот если у вас в проекте куча разных версий одной библиотеки, но они бинарно совместимы, то одну из них можно выбрать:

configurations.all {
resolutionStrategy {
force ’com.google.guava:guava:23.0′
}
}

Можно вообще отключить транзитивные зависимости и вручную добавить зависимости, которые вы хотите:

configurations.compile { transitive = false }

Спасибо за разъяснение. Теперь мне понятно чем Gradle лучше в этом плане.

А как насчет огромных проектов с кучей модулей. В Gradle можно конфигурировать модули на каждом уровне как в мавене или нужно иметь корневую конфигурации которая содержит список всех под модулей?

В Gradle как и в Maven, можно писать конфигурацию подпроекта в build.gradle подпроекта(аналог pom.xml) либо в build.gradle корневого проекта.

Но в Gradle более мощный DSL для всего этого. Например, как добавлять плагины(или зависимости) для всех проектов, кроме одного(project1)

1-й способ:

configure(allprojects — project(’:project1′)) {
apply plugin: ’myplugin’
}

2-й способ:

allprojects {
if (!it.name.startsWith(’project1′)) {
apply plugin: ’myplugin’
}
}

На тему будущего groovy/kotlin в gradle советовал бы послушать 110 подкаст разбора полётов. Довольно интересно.

Gradle более современное решение, более юзерфрендли.
Трудности перехода с Maven на Gradle — такие же как и с любым другим переходом между платформами — нужно потратить время на разбор.
По поводу того что лучше gradle или maven, тоже самое что битва между TestNG и JUnit. От себя скажу, что gradle мощнее. А сейчас уже есть версия 3.0 со статически типизированым языком Kotlin, автодополнение гораздо удобнее чем с версиями на groovy.

Лично из своего опыта перехода мавен на грэдл — это 4 дня с pom.xml на 3 листа до build.gradle в 1 лист. А как перешёл начал любить gradle, потому что он любит своего пользователя, а не просто даёт инструмент

Согласен, но ведь еще нужно потратить время на изучение Groovy(или Kotlin)

Плюсую) Это так и есть, но на глаз груви и котлин проще выглядит чем XML

еще бы JetBrains пнуть для более вменяемой поддержки

Они потихоньку тараканят к бОльшей поддержки котлина и грэдла.. Но до этого у них был один тараканчик для пооддержки грэдл на груви. Но потом они сказали жучкам из грэдл, хотете больше поддержки вот вам наш котлин и они не могли не согласиться :) теперь у Jetbrains больше одного тараканчика для gradle :)

From a tooling story perspective: Gradle is total disaster.
, или почему интеграция градла всегда будет ожидать лучшего wiki.apidesign.org/wiki/Gradle

Интеграция с Gradle с чем?

Очень похоже, что graggle лучше чем maven, потому что в Scala можно геттеры и сеттеры не писать.

Спасибо всем за интересные комментарии. Если вы только начинаете изучать Gradle или хотите подтвердить свои знания и навыки, можете попробовать сдать тест по Gradle: it-simulator.com/#/tests

Мавен работает хорошо пока у вас проект простой. Пусть кто-нибудь расскажет как сделать в мавене:

1. Инкрементальную публикацию в Maven-репозиторий (когда из многомодульного проекта публикуются только те, что изменились)
2. Изменить стратегию разрешения конфликтов для транзитивных зависимостей. Например, я, чтобы упростить переход одного из проектов с Maven на Gradle реализовал стратегию Maven (nearest) и вынес её в отдельный файл. Со следующем релизом уберу и оставлю стратегию по-умолчанию (latest). gist.github.com/...vets/deed0ae9c8c38b17a4f8
3. Сделать так, чтобы разные git-репозитории работали как один без необходимости в предварительно публикации каждого в локальный репозиторий и ручной правки pom-файлов. См github.com/prezi/pride
4. Хранить версию JDK (или другого компилятора) вместе с билдом и подгружать сам JDK из репозитория. Таким образом уменьшая проблемы с работой в параллельных версиях JDK, например, можно легко откатится на предыдущую версию. Это понятный и стабильный workflow: создал ветку будущего релиза, обновил версию gradle и JDK, все кто запулился или подмержил эту ветку сразу начнут работать с нужной версией. Если внезапно баг на продакшене, то чекаут на старую ветку, фикс и сборка без необходимости вручную учитывать и что-то менять.
5. Допустим, вы пишите плагин для большого многомодульного приложения. Вам нужно чтобы эта библиотека в runtime работала с теми же версиями зависимостей, что и при компиляции (Типичный пример, это sevlet-api и tomcat, вам нужно добавить servlet-api как provided зависимость и при этом желательно, чтобы его версия была такая же как в томкате). Я не представляю как это сделать в Maven, а в Gradle я просто создал дополнительную configuration с именем «reference», где указал версию приложения, получил из нее разрешенные транзитивные зависимости и подставил их во все зависимости без указанной версии). Например:

provided 'some_group:library'
reference 'main.big.app:common-lib:1.3.5'

Мы получаем гарантировано именно ту версию зависимости, которая идет с основным приложением. Завтра разработчики main.big.app выпустят версию 2.0, и всё что мне нужно будет сделать, это указать её.

6. Использовать в рамках одного проекта два или более артефакта с одним group-artifactId, но разных версий. Есть живой пример, где подобное требуется чтобы проксировать сервисы, получая артефакты разных версий от тех кто разрабатывает backend. Красиво и быстро решено с помощью github.com/vRallev/jarjar-gradle github.com/...tree/master/jarjar-gradle . Выглядит примерно так:

dependencies {
    futureServices "backend.team:superService:2.0"
}

dependencies {
    currentServices "backend.team:superService:1.0"
}

dependencies {  // common libs
    // Pattern format: https://code.google.com/p/jarjar/wiki/CommandLineDocs#Rules_file_format
    compile jarjar.repackage('currentServicesRepackage', {
        from configurations.currentServices
        destinationDir = file("${rootDir}/.gradle/repackage")
        classRename 'backend.team.**.services.**', 'backend.team.@1.currentServices.@2'
    })
    compile jarjar.repackage('futureServicesRepackage', {
        from configurations.futureServices
        destinationDir = file("${rootDir}/.gradle/repackage")
        classRename 'backend.team.**.services.**', 'backend.team.@1.futureServices.@2'
    })
    ...
}

Покажите мне как в Maven так же легко влезть в lifecycle, не добавляя при этом кучу лишних сущностей. :) При этом остается поддержка всех вещей «из коробки» от инкрементального билда до политик кеширования.

Что мне в Gradle не нравится:
Configurations — название путает, на самом деле это больше коллекции зависимостей, даже коллекции заявок на разрешение зависимостей. Также не нравится, что по-умолчанию как зависимости проекта наследуется default configuration, а оно в свою очередь включает в себя runtime. На мой взгляд, в этой части не совсем удачно продуманы абстракции, из-за чего можно иногда впасть в ступор и долго вчитываться в документацию.

Ох, не завидую я вашим переемникам. С таким уровнем complexity и home grew решений. По паре пунктов вообще в ступор впал — вы там случаем не переписываете шеф средствами грейдла?

Что именно из приведенных решений по-вашему «home grew» (кроме первого, потому что там я не приводил решения)? Пишите конкретно, иначе это выглядит как личный выпад.

Под решениями я имел ввиду ваши решения (decisions), а не куски кода. Так что включая первое.
1. Я так понимаю, что все еще используются -SNAPSHOT, и каждый новый билд перезаписывает старый, в противном случае не представляю как маппятся разные версии одного модуля между собой. Repeatable result в таком случае тупо не работает, потому что состояние системы из нескольких модулей в репозитории зависит от того, что было туда задеплоено и когда, и никакой маппинг версий не спасает. Вчера все работало — а сегодня утром уже нет.
2. «Со следующем релизом уберу» — поздравляю с очередным technical debt. Оно по определению есть home grew (костыль), потому что в противном случае оно было бы оформленно (и не факт что лично вами) в виде дженерик слюшна, плагина, или еще как нибудь.
3. Слишком сложно, что-бы оценить на коленке, воздержусь. Выглядит вроде нормально, но так сходу не понятно, будет ли оно работать в CD и вообще нафига оно там.
4., 5. — переизобретание шефа (паппета, ансибла, подставить любимое)
6. Ну я думаю вы и сами понимаете, где здесь complexity? Какой порог входа что-бы разгрести что-то? Никогда проблем с класспазом не было?

4., 5. — переизобретание шефа (паппета, ансибла, подставить любимое)
4 тут я так понял относится к compile time, а не к runtime. Так что не провижионинг. 5 — наверное.

1. Repeatable и SNAPHOT-версии — это два несовместимых понятия. Я предпочитаю совсем не использовать SNAPHOT’ы и версионировать каждую публикацию своей версией.
2. Сразу видно, что Вы настоящий профессионал, наверное, Вы всегда всё оформляете в виде модуля, плагина, пишите тесты, вылизываете. А то, что бизнесу позарез была нужна эта функция «еще вчера», чтобы срочно выпустить продукт быстрее конкурента и заработать денег, Вас не должно волновать. blog.crisp.se/...od-and-bad-technical-debt
4. Да, давайте добавим chef-монстра для выкачивания и распаковки одного архива, это всё так упростит. Сразу видно, что солидное решение. :) Что же про докер или вагрант не сказали, у меня тогда был бы нормальный аргумент почему их не всегда удобно использовать для локального девелопмента, если это не linux. А так даже не хочу говорить очевидные вещи.
5. Вот спринг выпустил подобный плагин уже после того как я свой написал (по-сути одно и то же) spring.io/...ncy-management-for-gradle Вот дураки-то, надо было chef использовать.
6. Задачу даёт PM, моё дело сделать, чтобы всё работало наиболее бескостыльно. У вас видимо с мавеном бы лучше получилось, пример в студию.

Никогда проблем с класспазом не было?
Это фраза по-моему вообще говорит о том, что вы не поняли, что данный мной пример как раз является решением проблем с classpath.

1. Совершенно так, правда по предыдущим сообщениям мне казалось вы этого не понимаете.
2. Поспешишь людей насмешишь. Так забовляет смотреть на беспомощных девелоперов, когда с помощью такой то матери релиз таки проклацали судя по джире, но что-то как-то не работает в продакшоне ;) Тайм ту маркет подразумевает совсем не хуяк-хуяк-продакшн.
4. Монстра? Вы его не правильно готовили, видимо
6. Только не провтыкайте момент, когда PM скажет работать по выходным, потому что размер тех долга уже иначе не позволяет

Мавен работает хорошо пока у вас проект простой. Пусть кто-нибудь расскажет как сделать в мавене:
Так проект нужно упрощать, а не build tool эбьюзить.
1. Инкрементальную публикацию в Maven-репозиторий (когда из многомодульного проекта публикуются только те, что изменились)
Если это так сильно нужно, то наверное нужно проект разбивать на репозитории, возможно с суперпомами, нет?
3. Сделать так, чтобы разные git-репозитории работали как один
 Не совсем понятно что значит «работали как один». Одна SHA1 у них все равно не получится.
4. Хранить версию JDK (или другого компилятора) вместе с билдом
это идея конечно благородная, вот только на этом уровне излишне усложняет. Как обеспечить наличие всех нужных версий на девелоперских лаптопах? А еще кроме версии ОС может играть роль, так что все равно для надежности должно собираться на конролируемом CI сервере, где это не обязано задаваться в, а приходит извне.
6. Использовать в рамках одного проекта два или более артефакта с одним group-artifactId, но разных версий.
должно быть в принципе точно так же достижимо, хоть и менее грациозно — два субмодуля с shadow, зависимость на них из целевого. Или еще лучше целевой разбить на субмодули. А вообще большой вопрос зачем это нужно. На первый взгляд выглядит что artifactId должен был быть поменян на backend.team:superService-2:1.0.
Если это так сильно нужно, то наверное нужно проект разбивать на репозитории, возможно с суперпомами, нет?
Монорепозиторий, в котором 50 модулей, разбить на 50 репозиториев?
Не совсем понятно что значит «работали как один». Одна SHA1 у них все равно не получится.
Когда Вы добавляете репозитории gradle в pride, то в процессе билда он подменяет внешнюю зависимость вида «groupId:arfifactId:version» на внутреннюю, из тех, что вы добавили в прайд при условии что groupId и artifactId у него те же. Это позволяет обходится без предварительно установки в локальный ~/.m2/repository, а использовать несколько репозиториев как будто это один gradle-билд. При это можно запускать команды на весь прайд, например pride do -- git status --short
это идея конечно благородная, вот только на этом уровне излишне усложняет. Как обеспечить наличие всех нужных версий на девелоперских лаптопах? А еще кроме версии ОС может играть роль, так что все равно для надежности должно собираться на конролируемом CI сервере, где это не обязано задаваться в, а приходит извне.
Отличные вопросы, я специально не углублялся в подробности в рамках одного комментария. Первая сложность связана с тем, что для разных платформ своя версия бинарников. Это решается с помощью этого плагина github.com/.../osdetector-gradle-plugin . Выглядит, например, так:
apply plugin: 'com.google.osdetector'

dependencies {
    sdk "your.company.sdk:jdk:${jdkVersion}:${osdetector.classifier}"
}

Таким образом, что на CI-серверах с линуксом, что на компьютере девелоперов с windows проблем не испытываем.

Вторая сложность связана с тем, что предварительно JDK нужно положить в maven-репозиторий. В принципе, если миграция происходит только на мажорные версии (java 1.6, java 1.7 и т.д.) или в случае критических багов в JDK, то не сложно делать раз в несколько лет руками. В моем случае я это автоматизировал добавив специальный «псевдо-мавен» сервис как proxy-репозиторий в Nexus, который предоставляет псевдо мавен репозиторий для всего, что используется при сборке, но не имеет своего собственного maven-репозитория. Не нужно думать, что там какой-то супер монстр, всего лишь python-скрипт на 100 строк. Может быть найду время немного причесать и выложить на гитхаб.

должно быть в принципе точно так же достижимо, хоть и менее грациозно — два субмодуля с shadow, зависимость на них из целевого. Или еще лучше целевой разбить на субмодули. А вообще большой вопрос зачем это нужно. На первый взгляд выглядит что artifactId должен был быть поменян на backend.team:superService-2:1.0.
Мы получаем готовые jar-файлы от backend-команды. В условии задачи мы не можем повлиять на backend-команду административными средствами потому что они редиски (или, например, они вообще из другой компании и их наше существование мало волнует). Важно то, что есть техническая возможность это решить без потери времени и чрезмерного усложнения.
Монорепозиторий, в котором 50 модулей, разбить на 50 репозиториев?
ну если у них разный релиз сайкл, то конечно разбивать. Особенно если 50. ИМХО это просто не удобно даже с точки зрения девелопмента. Не, ну если есть команда преемственных билд инженеров, то можно конечно и заморочиться, только принципиальных проблем это ИМХО не решает.
Когда Вы добавляете репозитории gradle в pride, то в процессе билда он подменяет внешнюю зависимость вида «groupId:arfifactId:version» на внутреннюю, из тех, что вы добавили в прайд при условии что groupId и artifactId у него те же. Это позволяет обходится без предварительно установки в локальный ~/.m2/repository, а использовать несколько репозиториев как будто это один gradle-билд. При это можно запускать команды на весь прайд, например pride do — git status —short
много умных слишком для меня слов, но похоже на то, что решается путем чекаута этих разрозненных репозиториев одну папку и добавлением фейкового мавеновского пома ими рулить. IntelliJ IDEA коммитит насквозь без проблем. Чуть возни с пушами и ручным проставлением новых снапшотов. Если градл это делает удобно — ему конечно плюс в карму, но ИМХО опять же если таковая потребность возникает часто то что-то не так с разбиением модулей и мавен мне лично будет предпочтительнее потому как будет дополнительным повод сделать по-человечески.
JDK
интересно. Мне лично больше импонирует файл с требованием версии для CI в корне проекта, но как опцию знать полезно.

Спасибо всем за комментарии.
Я все-таки хотел услышать истории миграции и проблемы, с ними связанные. К сожалению, не услышал. То ли проблем не было, то ли все так и остались на Maven.

та вот у меня на проекте еле еле на мавен переползли
и то как то по рагульному
у людей часто адский ад на ant для сборки и эту фигню вывести труднее чем тараканов

Успехов вам в вашем нелегком деле

так и остались. Как только появится внятная поддержка в IDE — так сразу можно будет второй заход.

Проблемы при миграции с Maven навскидку:

1. Не было provided-конфигурации, приходилось использовать плагины или добавлять самому. В последней версии, наконец, она появилась под именем compileOnly
2. Как я уже писал выше, стратегия разрешения конфликтов другая и нужно, либо внимательно смотреть и тестировать какие зависимости получились при новой стратегии, либо использовать стратегию nearest.
3. Нет аналога <dependencymanagement> секции, для этого нужен отдельный плагин.
4. Отсутствуют профили, вместо них предлагается использовать property, однако получается, в общем, похоже gradle -PbuildProfile=test build

Спасибо большое, Слава.
По поводу

provided-конфигурации
 — чем вам не подходил providedCompile ?

Дело в том, что эта конфигурация идет только с WAR-плагином. А, допустим, для EJB нужен на выходе JAR-файл, который компилируется с javaee-api, но при этом он не должен торчать в pom.xml как compile зависимость.

— поддержка Gradle в той же IDEA чуть хуже, чем хреновая
— многомодульные проекты со странными вещами типа связки Scala и GWT — боль и унижения

а так — вполне хорошая и годная вещь. Но maven все ж более предсказуемый.

Ну Maven все-таки с 2004 года, а Gradle c 2011 ...
С другой стороны Ant еще более предсказуемый.

Ant — это закат солнца вручную и make buildworld. Ну то есть конечно можно, но зачем, особенно в 2016-м году. Я честно попробовал в Gradle, на этапе связки с GWT compiler, генерацией кода и прочих приятностей — я забил. Тут только два года прошло как мне перестали задавать вопросы «как мне собрать проект без тестов», never again.

я не смог проект в IDEA влить. А это огромадный минус

Достаточно странно. Ни разу еще не видел, чтобы Gradle проекты не импортировались в Eclipse/Idea. А что у вас за ошибки были ?

Дисклеймер: сказанное ниже не относится к проектам из ~10 человек.
Во-первых, собственно про Maven vs Gradle: это война куда шире за рамками двух тулов, это декларативный vs императивный подход. Мавен прекрасен тем, что ты описываешь свой проект, и мавен сам знает что делать на основе этих данных. В Gradle куда более велик соблазн наворотить чего нибудь «эдакое», что вам лично кажется весьма и весьма элегантным, только не факт что таковым является на самом деле. К тому-же увеличивается порог вхождения. Эта изящность имеет право на жизнь, когда мы имеем возможность написать тесты, в соответствии с канонами infrastructure as a code. Насколько я знаю, в Gradle нет возможности покрывать gradle файлы тестами. В случае мавена, если сильно надо — у нас есть возможность выйти за рамки с помощью собственного плагина, и тестами этот костыль покрывается точно так-же, как и любой другой джава-проект.
Ну а во-вторых, в любом случае все не ограничивается системой сборки. Как правило существует целая инфраструктура, например на моем текущем проекте на базе шефа и jobdsl построен целый фреймворк, который позволяет делать много магии. Например, я могу добавить небольшой конфиг файл в репо с приложением, и для этого репо автоматически построется целый CD пайплайн и поднимутся все энвы. Легко и просто поменять звено цепи в такой системе не получится, это будет массивная фича в фреймворке для поддержки Gradle рядышком с Maven. И это отдельно от эффорта девелоперской команды на непосредственно перевод своего конкретного проекта с Maven на Gradle, когда его (Gradle) поддержка в инфраструктуре уже имплементирована.

Во-первых, собственно про Maven vs Gradle: это война куда шире за рамками двух тулов, это декларативный vs императивный подход.
У гредла тот же контракт что и у мавена. Проблема с тем что «кто-то чего-то отчубучит потому что может» остается, но она решается административно. Админ часть убрать нельзя так как с маненном так же можно отжечь, кто-то все равно должен следить и сдерживать полет фантазии.
Насколько я знаю, в Gradle нет возможности покрывать gradle файлы тестами.
Есть: docs.gradle.org/...ic.html#sec:build_sources
У гредла тот же контракт что и у мавена. Проблема с тем что «кто-то чего-то отчубучит потому что может» остается, но она решается административно. Админ часть убрать нельзя так как с маненном так же можно отжечь, кто-то все равно должен следить и сдерживать полет фантазии.
Я вроде-бы все так и сказал. Вопрос в том, зачем тогда Gradle если его основное преимущество запрещать «административно»? XML так сильно надоел?
Есть: docs.gradle.org/...ic.html#sec:build_sources
Сорри, но это лишь хороший энтри поинт. И если-бы мне очень сильно нужно было написать свои костыли и покрыть их тестами, я бы пошел именно сюда. Готового фреймворка, насколько я понимаю, нету. Или есть? Я правда очень давно в последний раз смотрел в сторону Gradle, понимаю что многое могло измениться, но на вскидку гугл ничего не находит. Я говорю про что-нибудь вроде rspec.info для руби, на основе которого построили docs.chef.io/chefspec.html. Из коробки я могу написать пачку тестов, положить их в репо с кукбуком, и запускать как часть билда. Что можно заюзать в Gradle из коробки для этого, не наворотив кучу кода для реализации этой потребности через buildSrc, при этом знатно покопавшись в сорцах самого Gradle?
Вопрос в том, зачем тогда Gradle если его основное преимущество запрещать «административно»?
1) Не запрещать, а контролировать.
2) Потому что __при наличии мозга или контроля__, появляется возможность проще кастомизировать била процесс.
XML так сильно надоел?
да
Я говорю про что-нибудь вроде rspec.info для руби, на основе которого построили docs.chef.io/chefspec.html.
А для мавен есть что-то подобное?
Из коробки я могу написать пачку тестов, положить их в репо с кукбуком, и запускать как часть билда. Что можно заюзать в Gradle из коробки для этого, не наворотив кучу кода для реализации этой потребности через buildSrc, при этом знатно покопавшись в сорцах самого Gradle?
Не совсем понял чего вам нужно. Можете привести пример реальной задачи которую вам надо протестировать?
Потому что __при наличии мозга или контроля__, появляется возможность проще кастомизировать била процесс.
Проще это хорошо, но после определенного размера во главу угла ставится задача ничего не поломать, а не сделать проще.
А для мавен есть что-то подобное?
В мавене в поме нет бизнес логики, вся она в плагинах, которые могут быть покрыты тестами как любой другой джава проект. Экзотические случаи вроде ант таргетов прямо в поме не рассматриваем. К тому-же мавен не корректно сравнивать с шефом, а Gradle — да, потому что оба они представляют из себя DSL с очень смешанным декларативно-императивным подходом.
Не совсем понял чего вам нужно. Можете привести пример реальной задачи которую вам надо протестировать?
Я хочу IaaC, я хочу покрыть тестами код, отвечающий за бизнес логику билд процесса, точно так-же как покрыт тестами код самого продукта. Пример: кусок бизнес логики для билда у меня реализован прямо в gardle файле, обычный какой-нибудь цикл по зависимостям, или по файлам в проекте с определенным расширением, с каким-то банальным действием, как мне покрыть этот код тестами?
В мавене в поме нет бизнес логики, вся она в плагинах, которые могут быть покрыты тестами как любой другой джава проект.
buildSrc предоставляет вам ту же возможность, но проще и более предсказуемо и контролируемо.
кусок бизнес логики для билда у меня реализован прямо в gardle файле, обычный какой-нибудь цикл по зависимостям, или по файлам в проекте с определенным расширением, с каким-то банальным действием, как мне покрыть этот код тестами?
Вынести это в таск, класс, метод в buildSrc

Ок, а проект у нас при этом не один, и мы не будем копипастить. Приходим к runtime зависимости, и чем это отличается от плагина в Maven? :)

Ок, а проект у нас при этом не один, и мы не будем копипастить. Приходим к runtime зависимости, и чем это отличается от плагина в Maven? :)
Тем что если у вас была ситуация:
кусок бизнес логики для билда у меня реализован прямо в gardle файле,
то, с большой вероятностью, вам достаточно будет одного метода и для его написания не надо будет изучать специфическое апи плагинов.
Конечно же мы можем исходить из того что у нас психическое расстройство вызванное отказом от телятины и непомерным потреблением кари и мы зафигачили 100500 строк бизнес-логики прямо в файл (1 файл) с била скриптом.

Ой да бросьте, точно так-же надо будет изучать «специфическое апи» Gradle для хоть сколько-нибудь более сложной операции, чем я описал выше. Только сложного здесь ничего нет. Тем же мавеном генерится пустой плагин из архетипа, и все ок. Так что мне все еще кажется, что имеет место всего-лишь паталогическая неприязнь к XML :)
А лично мне более нравится идея физической невозможности наворотить делов, как то: лимиты самой системы; АПИ; метрики проверяемые автоматически и не дающие закоммитить говнокод; etc. Красивые полиси на конфлюенсе никто не читает, и спустя два года проект все равно скатывается в «легаси» и «ынтырпрайз головного мозга». Если что-то возможно сделать, кто-то это обязательно сделает. И если в мавене использование antrun плагина сразу в глаза бросается, то среди грейдловских кложур и DSL такое смотрится вполне себе естественно и, вообщем-то, было задумано by-design.
Я бы сказал, что основная проблема мавена, это то, что собственному плагину нужно будет организовать собственный CI/CD и где то хостить бинарники. В более-менее большой компании это все, как правило, и так уже есть и поставлено на конвеер. А более маленьким компаниям стоит задуматься, реально ли они способны контролировать рост technical debt с грейдлом, или лучше все таки не пускать все на самотек.

Как человек, который уже с десяток билдов (от маленьких до больших) перевел на Gradle, скажу Вам, что всё не так плохо. Скорее даже наоборот. В общем, случае мой типичный подход выглядит примерно так:

1. Когда нужно что-нибудь быстро исправить или проверить (например, просто убедится, что это работает, вроде proof of concept) я могу написать немного кода в императивном стиле. В случае, если это быстрый фикс, там как раз не до красоты, потому что нужно как можно быстрее собрать/задеплоить/поставить. Или, если это проба новой идеи, то всё делается в отдельной ветке и не касается стабильного кода.

2. Далее когда у меня обрисовалось в голове, как это должно работать я могу вынести логику, либо в отдельный gradle-файл, либо в buildSrc. На этом этапе уже можно мержить в future release ветку.

3. Переношу код из buildSrc в отдельный репозиторий, пишу тесты. Раньше использовал специальный plugin от netflix. В последних версиях добавлена нативные возможности для тестирования плагинов:

docs.gradle.org/...nder-test-via-testkit-api

Свой CI в данном случае не нужен, достаточно прогнать тесты перед тем как запушить.

Насчет физической невозможности наворотить делов и говнкодить в мавене, вы заблуждаетесь. В этой области есть выдающиеся специалисты.

Ну раз мы начали мерятся достижениями, то как человек, организовавший сервис для десятков девелоперских команд и проектов (от маленьких до больших), скажу вам, что все ужасно. Если только у вас нет бюджетов нанимать 100500 инженеров в свою команду, что-бы покрывать все-все кейсы от всех-всех девелоперских команд со всеми-всеми проектами, вы будете стремиться к унифицированному солюшну. Да, страдает flexibility иногда (но не так уж и сильно, если с умом), но в огромной толпе девелоперов Gradle просто не работает — девелоперы всегда будут ломать CD, и держать процесс в рамках достаточно эффективно помогает только мавен.

Я вообще не собирался с Вами «мерятся достижениями». Просто хотел отметить, что возможность что-то напрямую запрограммировать не всегда плоха и при этом можно стремится к декларативному стилю в целом.

«Стремится» — это хорошо. Но если мы коммитимся на техникал дебт, стремления его убрать не достаточно — даже абстрактной стори в бэклоге не достаточно. Если ничего не ломается и бизнес доволен конечным результатом, этот костыль останется до близжайшего большого рефакторинга, или вообще навсегда.
Потому возможность пошорткатить и излишняя флексибилити — не всегда хорошо, а зачастую даже плохо.
И дело тут даже не в декларативном стиле как таковом.

Давно заметил, что именно в вопросах системах сборки аргументы оппонентов сводятся именно к вопросу «нравится — не нравится», а не аргументации по существу

А в вопросах выбора фреймворков/СУБД/etc по другому? :)

Ну фреймворков и СУБД намного больше, плюс люди зачастую прыгали с одной на другую, поэтому явного фанатизма здесь меньше.

Как по мне, «переход» Maven->Gradle может быть «нетривиален», в том случае если уже есть проект мало-мальски сложный на Maven и пришла мысль — «а не перевести ли его мне на Maven потому что вот последнее время какие-то фичи сборки в Maven добавлялись ну как-то совсем нетривиально». Мое наблюдение — в таком случае эта мысль долго не живет, понимаешь, что времени надо будет потратить немало, а ведь и так все работает и собирается, ну может где-то с костыльком. И как сказал Богдан:

«Время потраченное на миграцию можно потратить на запиливание фич :)»
.
Если же под «переходом» понимается использование Gradle в последующих новых проектах, то как по мне особой сложности не должно вызвать, более того, возможностей таки реально больше, особенно если брать во внимание Groovy: там где под maven или свой плагин надо было писать или в процессе сборки вызывать что-то внешнее, в Gradle пилится намного быстрее.

Сергей, а вам приходилось в уже существующем проекте менять систему сборки ?

Нет, в крупных проектах у меня «чистого» перехода Maven->Gradle не было, так что б поменялась только система сборки. Но вот у меня есть текущий проект, from scratch, и на определенном этапе руководство сообщило, дескать он должен соответсвовать одной из принятых парадигм внутри компании, где в том числе есть пунктик — сборка Gradle. Пришлось пару недель потратить на миграцию (посмотрел только что в Jira, на сабтаску Gradle build scripts залогал 2 часа). Ну и руководствуясь принципом: если используешь какой-то инструмент — используй его правильно, потом потихоньку еще были изменения.

В итоге могу сказать, что отношусь к вопросу скорее нейтрально: восторга от Gradle не испытываю, отторжения не наблюдается, при этом Maven скорее «дело привычки», но «зубами за него не держусь».

Начал бы я новый проект на Gradle без обязательной на то вводной? Возможно.
Одобрил бы сам себе инициативу перехода Maven->Gradle? Вряд ли, с оговоркой — если сложность сборки проекта внезапно изменилась бы и я «увидел» как Gradle это легко решает.

В этом и скрывается подвох.
Для того, чтобы увидеть, как Gradle легко решает сложные вещи, нужно хорошо знать Gradle, его DSL. А в этом никто не хочет разбираться, потому что есть привычный Maven.

мне приходилось несколько раз в больших проектах переходить в мавен с анта
это ад и погибель по трудозатратам
с мавена на грейдл уже не должно быть так плохо тк депенденси менеджмент по идее уже нормальный есть

Я решил написать статью о том, как в базовом варианте перейти с Maven на Gradle
Статью не читал потому что imgur.com/p2sxl1X :)
По слайдам, основной недостаток — это использование HelloWorld как примера (создается впечатление что тебя хотят на...обмануть :) ).
По хорошему у gradle 2 преимущества:
1) XML в 2016 году — это странно
2) gradlew — упрощает жизнь
.
Основных недостатком на мой взгляд 3 (первые 2 относятся к продвинутому уровню и не должны коснуться большинства maven-проектов):
1) его мощь, он позволяет наворотить такого что через неделю это понять не возможно (обычно оно начинается со слайда 33 :) )
2) groovy :) И замечательные несовместимости АПИ. Это становится проблемой когда ваш buildSrc усложняется
3) Вам прийдется таки прочитать доку (и не факт что этого хватит). Пример слайды 43 и 49 содержат интересные слова doLast и doFirst, а также оператор <<
.
Брокеров я вижу 2:
1) Корпоративная политика: разрешения и тд.
2) Время потраченное на миграцию можно потратить на запиливание фич :)

Спасибо. Какой у вас броузер, что у вас получилось imgur.com/p2sxl1X ?

По поводу недостака в том, что он слишком мощен — тут мне кажется проблемы могут быть только если разработчики без опыта. Если девелопер хорошо разбирается в чем-то(в том же Gradle), то чем мощнее тулза, тем лучше

В Ant взагалі абсолютна свобода, проте його build.xml-и з часом на повну кашу перетворюються, незалежно від рівня тих, хто їх пише.

Согласен. В этом и есть плюс Gradle — компактность плюс конвенции. Мое исследование показало, что при переходе с Maven на Gradle объем скриптов уменьшился в 2.5 раза.

Я все ж схильний надавати перевагу conventions over configuration, навіть якщо це йде всупереч компактності. :) Maven 3.3.1, кажуть, дозволяє писати pom.xml взагалі майже довільно: github.com/takari/polyglot-maven (в Overview є приклад на Ruby, хоча я так і не мав змоги з таким підходом попрацювати). У Gradle, принаймні як це заявлено на офіційному сайті, все ж є (?) суттєвіші переваги аніж просто компактність: gradle.org/maven_vs_gradle Знову ж таки, не мав змоги перевірити — приходиться вірити на слово. :)

Если девелопер хорошо разбирается в чем-то(в том же Gradle)
Билд система — это вспомогательный инструмент, а не основной род занятий. Может лучше проторить время на изучение (в глубину) чего-то более профильного, например, ТДД, многопоточность/распределенные вычисления, внутренности основной платформы, алгоритмы и структуры данных и тд?
, то чем мощнее тулза, тем лучше
Но-но-но, знания знаниями, а тратить время на «соблюдение техники безопасности» надо будет больше.
Ваш же пример со спринговыми артифактами (слайд 43), довольно легко превращается целую цепочку вызовов (просто потому что есть такая возможность), таким образом ухудшая читабельность и добавляя проблем с конфликтами версий.

Так можно долго спорить :) Как по мне вывод очевиден, Maven — для новичков с большим багажом copy-paste, Gradle — полезный инструмент для людей с опытом.

Как по мне, практика показывает обратное. Новички предпочитают градл, опытные джависты от мавена не страдают.

Новички предпочитают градл
Потому что понимают, что за ним будущее, и не хотят переучиваться в дальнейшем? :)

Что будет в будущем, никто не знает. Но тенденция сейчас такая, что популярность Gradle падает, Maven падает. Еще раз повторюсь, что это разные системы. Maven предназначен для конфигурирования, Gradle для программирования. Если вам больше нравится Maven — пожалуйста, используйте его.

Я думаю, что новички не могут влиять на выбор системы сборки. Это прерогатива тимлида или даже может быть заказчика.

2) groovy :)

Ну поначалу поплеваться приходится, конечно, но потом ничего, привыкаешь ;)

Ну врачи-специалисты говорят, что изучение новых языков улучшает и продлевает работу мозга :)

Насколько я понимаю, это истинно для любой интенсивной мозговой деятельности ;)

Ну поначалу поплеваться приходится, конечно, но потом ничего, привыкаешь ;)
И как вы привыкнете что у вас Спок, гредл и груви имеют не совместимые версии, просто потому что у вас в системе где-то прописался груви 2.2?
Дочитайте строку до конца: я говорил не про язык, а про инфраструктуру.

Я дочитал и понял о чем речь целиком. Просто подумал, что смайл сразу после groovy это дополнительно самому языку «комплимент» :)

Выскажусь по «недостаткам» maven, на которых всегда пытаются выехать адепты gradle:
1) Не нравится XML — используй Atom, Groovy, Clojure, Ruby, Scala, YAML: github.com/takari/polyglot-maven
2) Хочешь враппер как gradlew? Пожалуйста: github.com/takari/maven-wrapper

Большой плюс maven (по крайней мере для меня) — это использование парадигмы Convention over configuration. Все maven проекты выглядят однообразно, чего не скажешь о gradle.

В Gradle «convention over configuration» тоже хорошо проработано. Нет нужны например явно указывать groupId или artifactId для проекта.
По поводу «Polyglot Maven» — честно говоря, мало о нем слышал. Но все равно вы будете использовать ту же самую модель POM, которая была в XML. В Gradle модель и DSL напорядок круче.

У меня результат билда — это maven артефакт, который заливается в репозиторий. Используя gradle, всё равно надо создавать pom (только из groovy, а не xml). Поэтому каких-то преимуществ от перехода я не увидел. А вот сделать что-то не так возможностей у gradle больше.

«С большой силой приходит и большая ответственность» ©. Конкретных примеров не приведу, у меня с gradle небольшой опыт.

Мне кажется, это похоже на сравнение Java и C++. Предпочитать Java, потому что в C++ слишком много свободы по работе с памятью, можно забыть удалить или не туда обратиться ...

похоже на сравнение Java и C++
 ну может кстати аналогия не так уж и далека. Предпочту унаследовать java/maven от среднестатистической команды. И не буду советовать им пользовать С++/градл по умолчанию. Но аналогия заканчивается на том что в умелых руках С++ может оказаться значительным преимуществом во многих контекстах, а gradle при умелом использовании принципиально ничего не меняет. А в неумелых боли доставит больше.

Ну если для себя лично умелого — то можно и градлом побаловаться, конечно. Если тянет.

Наверное, можно и так сказать, что Maven — средство для конфигурирования, Gradle — средство для программирования. Естественно, что конфигурировать проще, и уровень вхождения тут меньше. Фактически любой разработчик может освоить Maven, а вот Gradle только человек с опытом.
Хорошо это или плохо? Наверное, хорошо иметь софт, который берешь и сразу используешь. Но с другой стороны шаг в сторону — и тебе придется долго ломать голову, что и как делать.

Все maven проекты выглядят однообразно, чего не скажешь о gradle.
Ага, особенно когда в них 100500 профайлов и мутных плагинов :)
.
Мавен и гредл довольно похожи (на данный момент): они просты в простых случаях и сложные в сложных.
Поэтому смысла мигрировать нет (если вы четко не понимаете какую именно проблему это вам решит), но и начинать новый проект на мавене так же нет (если че то у гредла такое же соглашение как и у мавена)

Maven и Gradle похожи? Разве что оба имеют дело с зависимостями и в основном работают с Java проектами. Gradle развивается семимильными шагами. Android, ++, новые фитчи появляются каждый 2-3 месяца.

Подписаться на комментарии