Статьи

Возвышенная простота написания сценариев с Groovy

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

Groovy предоставляет простой сценарий для разработчиков Java

В посте « Я использую метод main ()» Божидар Божанов пишет, что он «[использует] класс инструментов с основным методом», а не создает сценарии в Linux / bash или Windows PowerShell . Божанов идет, объясняет это решение:


В Java есть много мощных библиотек, которые позволяют мне избавиться от необходимости делать что-то в оболочке или использовать bash-скрипты. И хорошая вещь — это Java, он может быть версионирован при необходимости, и он прост в использовании, без дополнительной кривой обучения, без man-страниц и т. Д.

Хотя я был замечен в написании и поддержке Perl и, как известно, использовал другие языки сценариев, такие как Ruby , Python , PHP и shell / bash или PowerShell , я также ценю причины, по которым Божанов предпочитает класс Java с функцией main () для разработки инструментов. JDK и JVM предоставляют мощные и многофункциональные библиотеки и возможности и знакомы мне как разработчику Java.

Groovy — это отличный язык сценариев для человека, которому более комфортно работать с JDK и JVM, чем с базовой операционной системой. Groovy прост в освоении Java-разработчиком и делает некоторые вещи еще проще, чем когда он написан на Java. Groovy особенно хорош в предоставлении характеристик «стиля сценария», таких как нет необходимости писать явные объекты, нет необходимости писать public static void main методов public static void main , нет необходимости перехватывать исключения (проверенные или непроверенные), встроенная поддержка командной строки , множество полезных GDK- расширений JDK , динамическая типизация, лаконичный синтаксис ( однострочные примерыкрайние примеры ), легкий доступ к загрузчику корневых классов для внутренней загрузки классов, удобные функции вывода отчетов , встроенная поддержка Ant , простой доступ к SQL , простой анализ XML улучшенная поддержка регулярных выражений и многое другое.

Одним из преимуществ использования сценариев в Groovy над некоторыми другими языками сценариев является возможность запуска сценариев Groovy на любой платформе, поддерживающей виртуальную машину Java .

Groovy расширяет знания Java

Я также веду блог об использовании простых основных классов Java для изучения языка . Ранее на этой неделе коллега столкнулся с неожиданным открытием, связанным с Double.MIN_VALUE. Когда он спросил, знаю ли я, каково значение Double.MIN_VALUE, я сказал ему, что не знаю, как это происходит, но через несколько секунд смог сказать ему, выполнив следующую простую команду на командная строка:

1
groovy -e "println Double.MIN_VALUE"

Результат выполнения этой однострочной команды был, как показано на следующем снимке экрана, 4.9E-324. Он спросил меня, потому что был (и теперь я) удивлен, что это не было отрицательным. После прочтения Javadoc для Double.MIN_VALUE это значение имело смысл, но для меня было быстрее найти значение, запустив этот простой скрипт Groovy, чем для доступа к Javadoc или даже к Google. Я постоянно нахожу Groovy очень полезным для быстрого изучения языка Java.

groovyDoubleMIN_VALUE

Кстати, Javadoc для Double.MIN_VALUE утверждает (я добавил акцент ): «Константа, содержащая наименьшее положительное ненулевое значение типа double, 2-1074. Он равен шестнадцатеричному литералу с плавающей точкой 0x0.0000000000001P-1022 и также равен Double.longBitsToDouble (0x1L) ». Я предположил, что это было отрицательное число, потому что я никогда не использовал его раньше и из-за моего предыдущего опыта с отрицательными значениями для Integer.MIN_VALUE и Long.MIN_VALUE . Большое обсуждение причины такого выбора Double.MIN_VALUE (и применимо к Float.MIN_VALUE) доступно в потоке StackOverflow Минимальные значения и Double.MIN_VALUE в Java?

Groovy упрощает встроенную интеграцию

Хотя одним из преимуществ использования сценариев в Groovy является возможность запуска сценариев Groovy на любой платформе, поддерживающей JVM, во многих случаях сценариям необходим доступ к собственной операционной системе. Groovy имеет доступ к собственной операционной системе через java.lang.Runtime и java.lang.Process . Groovy упрощает использование этих классов благодаря расширению JDK класса Process .

Класс JDK Process имеет метод waitFor () , в описании которого указано Javadoc (я подчеркнул ):


Заставляет текущий поток ждать, если необходимо, до тех пор, пока процесс, представленный этим объектом Process, не завершится. Этот метод сразу возвращается, если подпроцесс уже завершен. Если подпроцесс еще не завершен, вызывающий поток будет заблокирован до выхода из подпроцесса .

Класс Javadoc для процесса более четко описывает потенциальное негативное влияние (я добавил акцент ):


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

Отличная статья 2000 JavaWorld Когда Runtime.exec () не показывает примеры использования кода Java для записи ввода и чтения вывода, чтобы избежать блокировки или тупика, но усовершенствование Groovy Process GDK значительно упрощает его применение. Например, метод Groovy GDK Process.waitForProcessOutput (Appendable, Appendable) позволяет двум экземплярам StringBuilder, например, представлять стандартные выходные буферы и стандартные буферы ошибок, чтобы предотвратить «блокировку процесса из-за полного выходного буфера».

Следующие два списка кода и связанные снимки экрана с выходными данными сценариев демонстрируют это.

demoDeadlock.groovy — Process.waitFor () Deadlocks

1
2
3
4
5
6
#!/usr/bin/env groovy
def recursiveDirCmd = "cmd /c dir /s ${args[0]}"
println "Running command ${recursiveDirCmd}..."
def result = recursiveDirCmd.execute()
result.waitFor()
println result.in.text

gdkProcessWaitForInBlocking

demoNoDeadlock.groovy — Process.waitForProcessOutput (добавляемый, добавляемый) не блокируется

1
2
3
4
5
6
7
8
#!/usr/bin/env groovy
def recursiveDirCmd = "cmd /c dir /s ${args[0]}"
println "Running command ${recursiveDirCmd}..."
StringBuilder standard = new StringBuilder(450000)
StringBuilder error = new StringBuilder(450000)
def result = recursiveDirCmd.execute()
result.waitForProcessOutput(standard, error)
println standard

gdkProcessWaitForProcessOutputNotBlocking gdkProcessWaitForInBlocking

Приведенный выше список кода и соответствующие снимки экрана демонстрируют, что расширение Process от GovK в Groovy позволяет легко блокировать команды, выполняемые в базовой операционной системе. Хорошая статья о вызове команд оболочки из кода Groovy — Выполнение команд оболочки в Groovy .

Вывод

Три разных события на этой неделе подтвердили мое мнение о том, что Groovy сочетает мощь Java с простотой сценариев Groovy.