Maven vs Gradle? Это неправильная постановка вопроса

Написать, наконец, этот пост меня заставила уже давняя дискуссия вот к этому посту на тему, которая время от времени всплывает то там, то тут.

Я много раз имел возможность убедиться, что далеко не все одинаково понимают, в чем же состоит декларативность vs процедурность той или иной системы сборки. Основным достоинством инструмента сборки зачастую считается возможность писать алгоритмы сборки на удобном языке. Нужен DSL, никуда без него.

В gradle этот DSL базируется на groovy. sbt использует скалу, leiningen — Clojure, Ant использует xml (совершенно не по делу, кстати). Несложно припомнить системы сборки на базе javascript. Каждый собирает на том языке, который ему ближе. И новые инструменты пишут, например, на котлине.

Увы, но наличие DSL совсем не означает декларативности. Скорее наоборот. В итоге, gradle проект вообще не может полноценно жить без pom.xml. Это шутка, но с большой долей правды. Посмотрите вот сюда: это репозиторий.

Что у нас тут лежит? Да-да, именно pom.xml, он самый. А где же у нас build.gradle? А нет его. Понимаете? Его тут нет.

То есть все метаданные, которые предоставлены о собранном проекте, который заметим, собирается при помощи gradle, состоят только и исключительно из метаданных maven.

Вас это не удивляет? Меня — нисколько. На мой взгляд, gradle, sbt, leiningen и многие другие инструменты почти (или вовсе) не предоставляют метаданных в доступном другим продуктам виде.

Они реально видны только самим себе, и только изнутри процесса сборки. Просто потому, что скрипт сборки — это груви код (Clojure, скала, javascript). Именно поэтому же их так плохо поддерживают IDE (в сравнении с maven или ant, где скрипт это xml). Чтобы понять, что там происходит, нужно выполнить. Нужно иметь gradle внутри, и нужно чтобы gradle отдавал в IDE необходимую информацию.

Как я вижу себе декларативность, и зачем она бывает нужна? В качестве иллюстрации приведу два своих проекта, и один от apache:

  • Начнем пожалуй с Apache Karaf. В ssh-консоли вам доступна команда установки модуля (OSGI-bundle). Эта команда использует не что иное, как координаты модуля в maven repository: bundle:install mvn:groupId/artifactId/version. При этом самого maven karaf не содержит — под капотом ничто иное, как Aether, плюс обертка над ним (Pax URL).
  • Аналогичную конструкцию я реализовал когда-то давно на Jython, и работала она внутри Weblogic. Использовался тот же Aether, плюс WLST API. И позволяло все это автоматически обновлять установленные в контейнере JavaEE модули, разыскивая их новые версии в репозитории.
    Опять же — maven в конструкцию не входил. Использовались репозиторий, Aether, и pom.xml, которые maven упаковывает в META-INF модуля.
  • И последний пример. В моей практике был один maven plugin, который в качестве исходных данных для своей работы использовал SVN, сканируя папки и файлы на предмет изменений в проектах, сравнивая их с bug tracker, и принимая решения, какие именно собранные артифакты нужно включать в релиз, и деплоить.

Какие выводы можно из этого сделать?

Во-первых, мы видим, что с описанием проекта (в моем случае это всегда был pom.xml) иногда бывает нужно и можно работать из любого достаточно развитого языка. Это не обязан быть инструмент сборки, на который изначально расчитан проект.

Во-вторых, если репозиторий спроектирован правильно, в соответствии с принципами REST, то нам не нужен никакой специальный софт для работы с ним, кроме http-сервера. Нужны только данные метауровня чуть выше проекта (список доступных версий, например).

В-третьих, очень удобно то, что важная часть инфраструктуры, в нашем случае plugins, сами просто обычные артефакты, лежат в том же репозитории, и никак не связаны вообще с конкретным проектом.

Вот это я называю декларативным подходом. У нас есть проекты, их много. Они бывают в репозитории, в виде собранных артефактов, в VCS, и еще где-либо, и могут обрабатываться разными инструментами — а не только одним единственным. Дескриптор проекта — это просто файл, любого стандартного и удобного для обработки формата. Репозиторий артефактов — это тоже стандартизованный формат + простой REST API. А логика сборки, на любом удобном вам DSL, лежит отдельно. Хотите — в самом дескрипторе, хотите — в репозитории.

Как бы я вообще это все сделал? В сущности, если брать за основу maven, то сейчас тут не хватает гибкости в части plugins, их настроек, и т.п., потому что существующий xml — это сериализованное представление java-модели данных plugins и ядра, и оно не гибко. Если разработчики решили, что какие-то данные о проекте вам не нужны — у вас остается только вариант key-value в виде properties.

А следовало бы сделать нечто произвольной, но регулярной структуры, ну скажем типа RDF (не обязательно именно его).
Описание проекта в виде RDF сразу позволяет делать полезные вещи вроде поиска в нем, как в базе данных (т.е. репозиторий, в части метаданных, становится просто SPARQL endpoint, и умеет отвечать на поисковые запросы). И такие же запросы можно строить применительно к проекту.

Вот это и был бы истинный poliglot maven. Причем это, кстати, выглядит вполне реализуемо, даже в рамках существующей инфраструктуры.
  • +5
  • 31,9k
  • 5
Поделиться публикацией

Комментарии 5

    +3
    Мне кажется maven сейчас лучшее, что у нас есть. Самый большой его напряг описан в статье habrahabr.ru/company/jugru/blog/191246 и это стратегия nearest. Минусы мавена — плохая документация, которая описывается примерно 10% его функциональности и частично устарела\врет. Тот случай когда регулярно надо смотреть в код реализации плагина, либо в готовый конфиг. Я иногда хожу по гитхабу, смотрю чужие pom-ы, «а что, так можно было?» — почти в каждом проекте.
      0
      Минусы мавена — плохая документация, которая описывается примерно 10% его функциональности и частично устарела\врет.


      Вы книжку от Sonatype читали? В смысле, обе книжки?
      0
      А вот это вот не ожидал. В Maven зависимости, а в Gradle логика сборки — удобно. Вы поправили мою вселенную сборки проектов.
        0
        Действительно интересно почитать!
        RDF сразу позволяет делать полезные вещи вроде поиска в нем, как в базе данных

        А по xml с учётом не такой сложной структуры POM вполне можно искать xquery, как по БД
          0
          Хм. Не думал, что это через два года кто-то читает :)

          >вполне можно искать xquery, как по БД
          Ну да. Меня в этом смысле всегда удивляют заявления приверженцев gradle, что maven де совмещает в одном файле метаданные и билд скрипты… Мало того, что это не так по большому счету — дело еще в том, что POM, будучи XML, достаточно хорошо структурирован, чтобы при необходимости выделить из него все, что душе угодно. Не нравится, что там репозитории? Берем любой инструмент, хоть xslt, хоть xpath, находим, вырезаем…

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

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

        Самое читаемое