Знакомство с Groovy DSL на примере из Gradle

от автора

Если вы пользовались системой сборки Gradle, то, вероятно, уже применяли и извлекали пользу из DSL-возможностей языка Groovy. В этой статье давайте рассмотрим такой пример.

Возьмем следующий фрагмент DSL из конфигурации Gradle.

plugins {     id 'java' }

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

def plugins (def pluginConfig) {     println "Plugins called" }  //--------------- DSL plugins {     id 'java' }

Когда мы запускаем приведенный выше код, то видим, что в консоли выводится «Plugins called» (вызываемые плагины). Мы понимаем, что plugins — это метод. Посмотрите на альтернативный способ вызова метода plugins.

plugins({     id 'java' })

Теперь понятно, что содержимое внутри ‘{}’ передается в качестве аргумента методу plugins. Такие блоки кода в Groovy называются closures. Если последний аргумент вашего метода (он может быть и единственным) является замыканием (closure), Groovy позволяет писать их вне круглых скобок. Таким образом, приведенный выше код можно записать следующим способом.

plugins() {     id 'java' }

Кроме того, Groovy позволяет опускать круглые скобки, если метод имеет хотя бы один аргумент, что и произошло в данном случае. Таким образом, мы получаем оригинальный код, используемый в нашем DSL.

plugins {     id 'java' }

Поскольку мы хотим добавить плагины в проект, давайте создадим структуру для хранения информации о нем.

class Project {     List<Plugin> plugins = [] }  import groovy.transform.ToString  @ToString(includePackage = false) class Plugin {     String id }

Теперь нам осталось создать экземпляр класса Plugin и добавить его в plugins Project. Как вы уже догадались, id 'java' означает, что мы вызываем метод идентификации с ‘java’ в качестве аргумента. Давайте добавим этот метод в класс Project, поскольку он кажется подходящим местом для его размещения.

class Project {     List<Plugin> plugins = []      def id(String pluginId) {         println "Adding plugin $pluginId"         plugins << new Plugin(id: pluginId)     } }

Давайте обновим наш метод плагинов, чтобы вызвать замыкание на инстансе project.

def plugins(def pluginConfig) {     Project project = new Project()     println "Plugins called"     project.with pluginConfig }

В консоли должно появиться сообщение «Adding plugin java» (Добавление плагина java). Здесь мы используем метод with, чтобы обеспечить замыкание, которое мы получили в качестве аргумента, для объекта ‘project’ (а не для инстанса этого скрипта).

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

def plugins(def pluginConfig) {     Project project = new Project()     println "Plugins called"     project.with pluginConfig     println project.plugins }  //--------------- plugins{     id 'java'     id 'groovy' }

На консоли вы должны увидеть следующее:

Plugins called Adding plugin java Adding plugin groovy [Plugin(java), Plugin(groovy)]

Конечно, полноценный DSL будет более сложным. Здесь я попытался передать суть идеи с помощью максимально простых примеров.


В заключение приглашаем всех желающих на открытое занятие «Shared Libraries в Jenkins», которое пройдет завтра в 20:00. На этом уроке посмотрим, как расширять пайплайны в Jenkins с помощью внешних библиотек и научимся их писать. Урок будет особенно полезен DevOps-инженерам и Java-разработчикам, которые хотят научиться создавать и настраивать сборки Java Backend проектов.


ссылка на оригинал статьи https://habr.com/ru/companies/otus/articles/743980/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *