У Java есть много возможностей, благодаря которым она хорошо подходит для больших и долгих проектов. Но я обнаружил, что она на удивление неплохо справляется и с небольшими задачами. Благодаря новым возможности языка это становится ещё удобнее. Киллер-фичи — это типизация во время компиляции и отличная поддержка инструментов.
В моей работе писателя и преподавателя есть множество повторяющихся задач, например, перемещение файлов и скучное преобразование их содержимого. Берясь за автоматизацию рутины, я обычно смотрю на задачу и думаю: «Никаких проблем, напишу шелл-скрипт». А затем происходит неизбежное: с появлением новых особых случаев скрипт превращается в ужасный хаос bash-кода. И я начинаю жалеть, что не написал его на настоящем языке программирования.
«Очевидный» выбор для этой задачи — Python, но Python API не так уж чудесен, а из-за динамической типизации мне понадобится слишком много времени на отладку. Поэтому я попробовал Java. Я знаю её API назубок; по крайней мере, то, что касается коллекций, файлов, regex и так далее. Java статистически типизируемая, поэтому я защищён от глупостей ещё на ранних этапах кодинга. А её среды разработки просто потрясающие.
Что вы говорите? Действительно ли я хочу создавать отдельный файл POM и иерархию src/main/java
для каждого скрипта? Хм.
Нет, я этого не делаю. К счастью, современная Java и её инструменты этого не требуют. Давайте разбираться!
Запуск без компиляции
Представим простую, но не слишком простую задачу. Например, у меня есть процедура для проверки работоспособности моих бэкапов. Раз в день в запланированном job я извлекаю десять случайных файлов. (Это очень хорошая идея, которая несколько раз спасала меня от ненадёжных бэкапов.) Скрипт случайным образом выбирает десяток файлов из дерева каталогов. Он написан на Java. И он находится в папке, где ещё есть довольно много других вспомогательных скриптов.
Разумеется, я могу его скомпилировать, но тогда моя папка со скриптами будет забита файлами классов. Или я могу создать файл JAR. Но это дополнительная работа. Когда пишешь скрипт, ценность которого пока неочевидна, то разве у тебя найдётся терпение на возню с JAR и uber JAR?
Именно поэтому я люблю JEP 330 и JEP 458. Теперь я могу сохранить свой код в файл .java
, и просто запускать его такой командой:
java RandomFiles.java 10 /home/cay/data
Файл компилируется на лету при каждом запуске скрипта. И это как раз подходит мне для разработки и дальнейших экспериментов. К тому же это меня не особо беспокоит при регулярном использовании, ведь он не особо медленный. Разработчики на Python никогда от подобного не страдают, так почему должен я?
Чтобы ускорить время запуска, можно компилировать скрипты в нативные исполняемые файлы при помощи Graal. Я экспериментировал с ним, но не увидел особой разницы для моих сценариев использования.
Почему бы не использовать JShell? Я люблю использовать JShell для маленьких экспериментов (основная часть которых связана с отладкой регулярных выражений). Но для скриптов он не очень подходит. Сам инструмент JShell имеет очень рудиментарную интеграцию с редактором, а поддержка JShell в IDE плоха.
Методы Main и неявные классы экземпляров
JEP 477 снижает количество кода при написании маленьких программ на Java. Мотивацией для этого предложения стали два желания. Во-первых, желание упростить изучение Java. Во-вторых, упростить «другие виды маленьких программ, например, скриптов и утилит командной строки». Обучая программированию Java в течение многих лет, я ни разу не встречал студентов, которые бы сказали «у меня голова болит, когда я копирую и вставляю эти public static void main
». Но я знаю, что они напрягают многих преподавателей. Поэтому избавление от этого — хороший шаг.
А нам, скриптописателям, удобно не разбираться в этой мешанине.
Никаких лишних class
, никаких static
.
Строго говоря, любой файл Java с методом main
верхнего уровня становится неявным классом, переменные и методы экземпляра которого становятся переменными и методами верхнего уровня в файле. Стоит отметить, что вполне нормально и даже желательно создавать в неявном классе классы, интерфейсы, перечисления или записи. Они превращаются во вложенные типы.
Дополнительное преимущество заключается в автоматическом импорте всего модуля java.base
. Ура, больше никаких
import java.util.List;
(Как оказалось, имена классов в java.base
были тщательно подобраны так, чтобы не конфликтовать друг с другом.)
В стандарте Java 23 из java.io.IO
автоматически импортируются три метода: println
, print
, readln
. С точки зрения обучения это неидеально, потому что требует запоминания ещё одного факта. Но мне, как скриптописателю, это нравится.
Удобством этих автоматических импортов мы пользуемся только в неявном классе, но для многих скриптов это вполне подходит.
Записи и перечисления
Программисты на Python часто используют для агрегирования связанной информации произвольные словари (например, map). В Java у нас есть записи (record):
record Window(int id, int desktop, int x, int y, int width, int height, String title) {}
Они упрощают чтение кода и становятся естественными точками работы с методами:
record Window(...) {
int xmax() { return x + width; }
int ymax() { return y + height; }
}
То же самое относится к перечислениям (enum):
enum Direction { NORTH, EAST, SOUTH, WEST };
Гораздо удобнее, чем неуклюжие перечисления в Python.
Другие полезные фичи языка
При работе со сложными программами я обращаюсь с использованием var
консервативно и применяю их только тогда, когда тип очевиден сразу, например:
var builder = new StringBuilder();
Но в скриптах я использую var
свободно. Почти как в Python, только у нас всё равно есть типизация во время компиляции. На самом деле, такой синтаксис лучше, чем в Python, потому что можно различать объявление и присвоение.
Также я более агрессивен с импортом static:
import static java.lang.Math.*;
diagonal = sqrt(pow(width, 2) + pow(height, 2));
(На самом деле, это лишь пример, можно просто использовать hypot(width, height)
.)
Блоки текста удобны для хранения данных вместе с кодом. Они играют ту же роль, что и «here documents» в скриптах. Надеюсь, эта интерполяция вскоре вернётся, а пока для частей с переменным текстом я пользуюсь String.formatted
.
Полезные фичи API
Библиотека Java для строк, regex, коллекций и даты/времени превосходна и крайне хорошо задокументирована. Мне она нравится гораздо больше, чем её эквиваленты в Python, JavaScript или (хех) Bash.
Например, чтение файла в строку выполняется очень просто:
var content = Files.readString(Path.of(filename));
Для запуска внешнего процесса я использую вспомогательные объекты:
String run(String... cmd) throws Exception {
var process = new ProcessBuilder(cmd).redirectErrorStream(true).start();
process.waitFor();
return new String(process.getInputStream().readAllBytes());
}
Стоит отметить, что начиная с JEP 400 можно полагаться на UTF-8 как на кодировку по умолчанию.
Для HTTP есть HTTPClient
(JEP 321) и простой веб-сервер (JEP 408).
Поддержка XML вполне пригодна к работе. API устарел и неудобен, но хотя бы работает предсказуемо. В Python есть большой выбор вариантов, но каждый из них по-своему частично поломан.
В стандартной библиотеке отчаянно не хватает двух вещей: JSON и обработки командной строки. Для большой программы на Java это не особая проблема., достаточно добавить в POM свою любимую библиотеку, например, Jackson или PicoCLI. Но это становится препятствием при написании скриптов. Я не хочу вручную скачивать все зависимости Jackson, а затем добавлять их к пути к классам.
Можно поступить хитро: использовать очень простые библиотеки, умещающиеся в один файл. Я пользовался Essential JSON и JArgs. Достаточно закинуть файл в папку со скриптом.
Проверяемые исключения
В определённых условиях может оказаться приемлемым, чтобы скрипт завершался с трассировкой стека, если что-то пошло не так. Но, разумеется, вам всё равно нужно объявлять или перехватывать проверяемые исключения. В большой программе это имеет смысл, но в скрипте кажется лишней обузой.
Проще всего решить эту проблему, добавив throws Exception
к каждому методу, который может выбросить проверяемое исключение, включая и main
.
Кстати, для студентов-новичков это может стать ещё одним «способом уменьшения количества церемоний». Почему бы не делать это автоматически в методах неявных классов? Но правила придумываю не я.
Проблема с проверяемыми исключениями остаётся в лямбда-выражениях. Скрипты много работают с файлами, и иногда API передаёт потоки путей к файлам. Поэтому вам может потребоваться сделать что-то подобное:
streamOfPaths.map(Files::readString)
Но вы не можете этого сделать, потому что метод readString
может выбросить IOException
.
Правильным решением, разумеется, была бы какая-нибудь обработка исключения. Например, можно возвращать пустую строку. Записывать исключение в лог. Превращать его в UncheckedIOException
. Подходящее решение можете выбрать только вы.
Но в скрипте это может быть не важно, и достаточно будет просто завершить программу. Существует несколько библиотек «скрытного выбрасывания» для решения этой проблемы, например, Sneaky Fun. В них используется дыра в системе типов Java. Благодаря хитрому применению дженериков можно превратить метод со спецификаторами throws
в метод, их не имеющий. Подробности этого тоже скрыты, но для применения этой фичи их знать необязательно. Достаточно написать
streamOfPaths.map(sneaky(Files::readString))
Я практически уверен, что это никогда не станет частью JDK, потому что это плохо для больших и серьёзных программ. Но почему бы не использовать это в «быстром и грязном» скрипте? Только не забудьте убрать это, если ваш скрипт вырастет и перестанет быть быстрым и грязным.
IDE и организация файлов
Мне не хочется писать скрипт в простом текстовом редакторе. Весь смысл работы на Java заключается в том, что это язык со статической типизацией, а IDE может помогать с автодополнением кода и мгновенным отображением ошибок в программе.
Обычно я начинаю с редакторов средней весовой категории наподобие Visual Studio Code или Emacs в режиме LSP. Это обеспечивает мне интеграцию с Java, но без необходимости настройки отдельного проекта под каждый скрипт. Достаточно открыть файл Java и начать его редактировать.
Как я уже говорил, меня напрягает создавать новую структуру папок src/main/java
каждый раз, когда в голову приходит идея скрипта. Поэтому я продолжаю работу в своём любимом редакторе. Рано или поздно скрипт разрастается до таких размеров, что я больше не хочу отлаживать его при помощи print
. Можно отлаживать программу на Java внутри VS Code, но мне это не кажется особо удобным. На этом этапе мне уже хочется комфорта настоящей IDE, но без src/main/java
.
На самом деле, можно убедить тяжеловесную IDE использовать базовую папку проекта в качестве папки исходников. Если «породить» базовую папку проекта файлом Java, а затем создать в IDE проект из готовых исходников, то она должна автоматически распознать ваши намерения. Имея готовый проект, измените структуру проекта. В Eclipse нажмите правой клавишей мыши на имени проекта, выберите Properties и Java Build Path, а затем вкладку Source. В IntelliJ перейдите в Menu → Project structure... → Modules, удалите «content root» и добавьте базовую папку проекта в качестве нового «content root», помеченного как Sources. Это звучит странно, но работает.
JBang
Самая серьёзная болевая точка скриптинга на Java — использование сторонних библиотек. Почему загрузчик java
из одного файла не может выполнять импорт из Maven? Ну, во-первых, Java понятия не имеет о существовании Maven. В стандарте языка Java ничего не говорится об экосистеме Maven. В этом сказывается большой возраст Java. В более современных языках программирования есть единый механизм для сторонних библиотек. Но мне кажется, что Oracle не хочет и не может это исправить. Поэтому нужен какой-то инструментарий для интеграции с экосистемой Maven, и он не будет частью JDK.
В качестве быстрого решения (адаптированного из одного хака) я иногда создаю тривиальный скрипт Gradle с координатами Maven для получения файлов и для вывода пути к классам. Но я делаю это только тогда, когда не могу использовать JBang. (Введение в JBang можно прочитать в статье JavaAdvent.)
Киллер-фича JBang заключается в возможности добавления зависимостей Maven непосредственно в исходный код:
//DEPS org.eclipse.angus:jakarta.mail:2.0.3
После чего можно выполнить
jbang MailMerge.java
В Linux и Mac OS можно также превратить файл в исполняемый скрипт при помощи «шебанг»-строки:
///usr/bin/env jbang "$0" "$@" ; exit $?
Обратите внимание, что //
скрывает шебанг от Java, а exit $?
маскирует остальную часть файла Java от шелла. (Три косые черты используются по запутанным причинам совместимости с Posix.)
Остальная часть JBang — это просто gravy. Вы можете запускать JShell с вашим файлом и загруженными зависимостями. Можете запускать IDE с симлинками на ваши исходники внутри временной src/main/java
. У него есть и другие фичи, требующие размышлений, но их не так много. Если вы серьёзно намерены писать скрипты на Java и можете использовать сторонние инструменты, то скачайте JBang.
Ноутбуки
Пока мы рассматривали только скрипты — короткие программы для регулярного запуска. Ещё одна грань «малого» программирования — это исследовательское программирование: написать код один или несколько раз, чтобы получить какой-то результат от набора данных. Дата-саентисты предпочитают для этой работы ноутбуки. Ноутбук состоит из ячеек кода и текста. Результат каждой ячейки кода отображается как код, таблица, изображение или даже как аудио- или видеоклип. Ячейки с кодом мотивируют идти путём проб и ошибок. После получения нужного результата вычисления можно аннотировать ячейками текста.
Почему это лучше, чем JShell? Экспериментировать с ячейками гораздо проще, чем со строками кода в JShell. Можно видеть табличные данные и графики, сохранять и отправлять ноутбуки коллегам.
Самый популярный ноутбук для Python называется Jupyter. Его можно запускать локально, обычно с веб-интерфейсом, или где-нибудь хостить. Популярный сервис для хостинга — это Google Colab.
На самом деле, базовая технология Jupyter не зависит от языка. Можно устанавливать разные ядра для различных языков программирования. Процесс установки ядра может быть запутанным, но в статье JavaAdvent описывается Jupyter Java Anywhere — простой механизм (использующий JBang) для установки ядра Java.
Сбивает с толку то, что есть множество разных ядер Java (в том числе IJava, JJava, Ganymede и Rapaio). У каждого ядра есть свой способ установки зависимостей Maven, отображения нетекстовых результатов и так далее. Juypter Java Anywhere устанавливает классическое ядро IJava, у которого есть неустранённые проблемы с разрешением зависимостей. Было бы очень желательно, чтобы Oracle или другой поставщик взялся за курирование ядра и даже создать сервис для ноутбуков Java наподобие Colab. Что-то более полезное, чем Java playground.
Кодерам в ноутбуках Python повезло — у них есть пара библиотек для вычислений, в частности NumPy и Matplotlib. Ни одна из них не показалась мне идеальной с точки зрения дизайна API, но они очень популярны, а потому на StackOverflow и в чат-ботах можно найти рекомендации (многие из них оказываются полезными) по настройке вычислений и графиков.
Исследовательский кодинг на Java не так популярен (пока) и для него нет длинного списка сопровождающих библиотек. Я думаю, приемлемым эквивалентом NumPy может быть tablesaw. У него есть обёртка для известного JavaScript-пакета отрисовки на Plot.ly.
Для улучшения ситуации Свен Реймерс разрабатывает ноутбук JTaccuino. Это реализация JavaFX с более дружественным интерфейсом пользователя, чем у веб-ноутбука Jupyter. Внутри него используется JShell. Проект пока находится на ранних этапах развития, но за ним стоит понаблюдать.
Для Kotlin существует плагин для IntelliJ Kotlin Notebook.
Хотя ноутбуки Java, возможно, и не готовы к полнофункциональному применению, надежда на будущее есть.
Заключение
При подходящем инструментарии Java оказывается на удивление эффективным выбором для написания маленьких программ. Для простых скриптов, использующих только Java API, можно просто запускать файл исходников на Java. JBang сильно упрощает запуск программ со сторонними библиотеками. Вы можете пользоваться преимуществами типизации во время компиляции и возможностями апгрейда, когда ваши программы становятся сложнее, что случается довольно часто.
По тем же причинам Java может стать привлекательным выбором и для исследовательского программирования, но инструментарий для этого ещё не совсем готов.
Комментарии (15)
adenisov
19.12.2024 17:53Когда в руках молоток все вокруг кажется гвоздём
Особенно учитывая фразу про сложность отладки питона из-за динамической типизации.
Lewigh
19.12.2024 17:53При подходящем инструментарии Java оказывается на удивление эффективным выбором для написания маленьких программ.
При всем уважении, Java - это один из самых неэффективных и неудобных языков для написания именно маленьких программ. Это тот редкий случай когда из коробки решение представляет из себя буквально ничего. Ни пакетного менеджера, ни сборщика артефактов, ни парсера аргументов командной строки. То что в других языках делаеться с лету встроенным функционалом, в Java нужно обмазываться кучей инструментов, библиотек и плагинов для написания простейшей cli программы.
yrub
19.12.2024 17:53Статью читали? Сейчас вам ничего не надо собирать, чтобы выполнить программу состоящую из одного файла. Просто java MyProgram.java
Если нужны зависимости для запуска этого файла без компиляции - используйте
jbang
Сборка артефактов? Ну тогда вам нужно делать по-нормальному с maven/gradle. Но и тут я не вижу проблемы, это 3 клика в ide на все про все.
(Сейчас вот добавляют возможность импортить все сразу одной строкой)
Ни пакетного менеджера, ни сборщика артефактов, ни парсера аргументов командной строки. То что в других языках делаеться с лету встроенным функционалом
Это в каких? И так чтобы потом сообщество не наизобретало 100 своих пакетных менеджеров и сборщиков, потому что стандартный вышел не очень и теперь у нас pip на анаконде и ты сидишь второй час и пытаешься вникунуть что к чему относится и когда использовать ;) В этом плане в java все отлично: два сборщика полнофункциональных: для ретроградов и для модных.
ни парсера аргументов командной строки
о каком парсере идет речь? аргументы придут в массиве, хотите что-то продвинутей, ну найдите модную библиотеку которая вас устроит
Я просто не пойму с чем вы сравниваете
PS: реально только одна проблема: так никто раньше не делал и к такому не привык.
PPS: насчет оверхеда надо смотреть, где-то будет ок, где-то нет, я не знаю какой реальный оверхед на запуск bash и иных скриптов (но учитывая, что иногда git bash под win зависает - там все тоже не летает)
Lewigh
19.12.2024 17:53Статью читали? Сейчас вам ничего не надо собирать, чтобы выполнить программу состоящую из одного файла. Просто java MyProgram.java
Если нужны зависимости для запуска этого файла без компиляции - используйте
jbang
Сборка артефактов? Ну тогда вам нужно делать по-нормальному с maven/gradle. Но и тут я не вижу проблемы, это 3 клика в ide на все про все.
Есть такая элементарная и очень базовая задача - написать приложение для командной строки. Могу я схожу создать такое приложение имея только Java?
Ну если hello word может быть. Если что-то чуток серьезнее где не один файл или нужна либа то нет. Нам уже нужно установить сборщик Ну ок. Далее мне чтобы получать в удобном виде аргументы командной строки, выводить help сообщения и т.д, нужно искать отдельную либу. Далее мы сможем собрать наше приложение в единый файл? Нет. Нам нужно ставить плагин чтобы хотя бы иметь возможность собрать все в Jar. Окей, будут ли в этом Jar файлы зависимости нашей либы? Нет. Нам нужен еще один плагин чтобы собирать полный Jar. Можем ли мы удобно это запускать как исполняемый файл не заставляя пользователя помнить что нужно прописывать java -jar? Нет не можем, нам опять нужен еще один из плагинов которые будет запускать скрипт когда мы пытаемся запустить Jar. И наконец, можем ли мы сделать полноценный исполняемый файл чтобы бы мы могли его запустить? Да, но нам нужно установить в систему и настроить отдельную JVM. И только после этого всего мы сможем сделать простейшую задачу - написать cli утилиту.
Как итог, можем мы сделать это на Java? Да можем.
Удобно ли это делать на Java? Да нефига.Я просто не пойму с чем вы сравниваете
Да просто на вскидку. Возьмем Go, накидываем программу, используем встроенные средства для основных задач вроде парсинга аргументов, компилируем и получаем исполняемый файл без всяких танцев с бубном. Ну ок Go компилируемый.
Берем самого очевидного и похожего конкурента C#. Просто через командную строку .net создаем сразу проект cli программы, накидываем что нужно и собираем в том виде в котором нам интересно: либо в единый исполняемый файл требующий виртуальной машины на ОС или в единый запускаемый файл в который уже все встроено. По итогу получаем исполняемый файл который не требует установки ничего и выполняем то что нам нужно. Нам не нужно ставить пакетные менеджеры, не нужно ставить и настраивать 10 плагинов и библиотек, и даже не нужно ставить сторонние виртуальные машины. У нас для элементарной задачи есть элементарное и удобное решение из коробки.
Это называется - удобный языки для написания маленьких программ.yrub
19.12.2024 17:53в java тоже можно создать проект одной строчкой со всеми нужными плагинами, библиотеками и папками: есть понятие maven archetype . да, удобно когда есть официальный способ создания, а его нет, надо разбираться и искать кто такой уже делал.
Ну ок Go компилируемый.
да, и теперь мы привязаны к платформе и должны думать как создать билд под другие системы.
Кстати раз такое пошло, то мы тоже можем скомилировать java в испольняемый файл.
Далее мне чтобы получать в удобном виде аргументы командной строки, выводить help сообщения и т.д, нужно искать отдельную либу.
у каждого свое понятие удобности, стандартно вам дают массив, для всего остального лучше библиотека, потому что мода оформления и логика работы консольных программ меняется со временем. + в win и linux изначально схема указания параметров отличалась. Все это веские причины не подавать на вход программы что-то сложнее массива, и оставить эту работу сторонним библиотекам.
Нам не нужно ставить пакетные менеджеры
не вижу проблем поставить во время разработки, более того они идут с IDE и ставить нужно только ее. Собственно так же наверно происходит и с C#, очевидно что будучи частью системы он будет с ней дружить.
Но теперь возвращаясь к теме топика: мне нужна простая программа, которая например сходит на какой-то урл и что-то сделает. 1 файл, я могу в IDE накидать все это без зависимостей и запустить на любой системе где ставили java одной командой как обычный bash скрипт, и работать это будет и под win и под nix. Я даже могу попросить chatgpt создать такой файл, могу поменять его в любой момент да и просто посмотреть что он делает. Можно так же на go или net? Нет, надо разбираться, запускать какие-то команды в консоле чтобы создать проект и скомпилировать его, т.е. иметь компетенцию в этом. С таким же успехом я поставлю всю что мне надо в java, сделаю или исполняемый jar или исполняемый файл. В первый раз будет трудно, если похожего готового мануала не найду, а потом легко.
Если моей программе нужны зависимости и я хочу ее запускать опять без компиляции одним файлом - ставлю jbang. Кстати манул как писать на нем продвинутые консольные команды с парсингом аргументов я видел. Минс: нужно ставить jbang после java, не для прода это.
В сухом остатке получаем что ситуация не однозначная, у каждого подхода есть свои плюсы (в целом все что вы перечислили принимается), но как по мне минимальный порог входа для того, чтобы сделать что-то относительно простое из всего о чем шла речь именно у java. Как я понимаю похожая ситуация с python и ruby. Далее есть варианты и все равно каждый будет использовать то, что он умеет и понимает. Да, наверно мне на java надо будет больше телодвижений, но это не проблема ни разу, которая как-то сильно меня затормозит.
Lewigh
19.12.2024 17:53Вам говорят:
на язык X можно создать cli приложение в прямом смысле слова в пару команд, пользуясь официальной документацией, используя встроенную библиотеку и средства разработчика и собрать это в том виде в котором нужно для конкретной цели. Не нужно ничего особо дополнительно устанавливать, не нужно лазить по интернету в поисках решений и библиотек для простейшей задачи. Не нужно дополнительные виртуальные машины ставить. Происто идем по оф. мануалу и вызваем несколько команд.
Хотите кроссплатформенный вариант который будет работать на любой машине где установлена среда выполнения(C#), хотите - исполняемый файл, который будет работать без установленной виртуальной машины(C#/Go). Без проблем. Все из коробки.
Вы говорите:
на Java все делается просто: если так -то вот так, а если вот так - то по другому, а если нужно чуток посложнее то вот это идем идем гуглим читаем доки. Для выполнения простейшей операции нет встроенной в язык функции? Да и не нужно, массив приходит и ладно. Нужно будет поискать еще библиотеки не проблема.
Нужно исполняемый файл? Нужно ставить отдельную виртуальную машину в систему? Ну и ладно.
Можно ли все это сделать на Java, да можно, никто не спорит.
Но когда после вышеописанного, что проще для простой программы: вызвать пару команд или копаться ковыряться в изучении плагинов для элементарных вещей, искать по интернету инструменты чтобы элементарно нормально можно было свое простое решение использовать, вы как ни в чем не бывало пишите:В первый раз будет трудно, если похожего готового мануала не найду, а потом легко.
...
...но как по мне минимальный порог входа для того, чтобы сделать что-то относительно простое из всего о чем шла речь именно у java.
Это называется фанатизм своим языком программирования вопреки здравому смыслу. Тут спорить бесполезно.
Therry
19.12.2024 17:53Не самый лучший выбор для автоматизации рутинных задач. А что насчёт питона, то там есть inlay hints.
kivan_mih
19.12.2024 17:53Я обычно использую немного другой подход для "одноразовых скриптов", а точнее просто небольших утилит для личного пользования, которых может быть много. У мавена есть возможность делать мультимодульные проекты, в которых модули организованы иерархически. Модули могут иметь свои зависимости, работать на разных версиях jvm и т.д, а иерархия может добавлять общие настройки группам модулей. Современные IDE вроде IDEA отлично работают с такими проектами. Используя этот подход, все вспомогательные утилиты я много лет складываю в один проект, в котором сейчас 172 модуля. Конфигурации запуска я также группирую иерархически для удобства работы. Поскольку всё это происходит в рамках одного проекта, то с одной стороны доступны все возможности IDE по работе с кодом, а, с другой, вы всегда можете в случае необходимости переиспользовать какой-то код, просто добавив зависимость и убедившись, что они на одной версии рантайма.
Звучит возможно тяжеловесно для "скриптов", но это было вполне сознательное решение после того, как с одной стороны я устал от хаоса при работе со скриптами на скриптовых языках, а с другой периодически появлялась потребность переиспользования кода, которая обычно в мире скриптов решалась копипастой, что добавляло головной боли, если скрипты оказывались не такими "одноразовыми", какими казались вначале.
На универсальность такого подхода не претендую, но лично мне он помог навести порядок.
3vi1_0n3
19.12.2024 17:53По ходу автор (оригинальный) написал статью ради статьи.
Какой хаос у него там в баше вообще непонятно. Он вместо баша припёр ВСЮ джавовскую инфраструктуру и пишет в джаве скрипты, которые выглядят почти так же, как выглядел бы скрипт на баше, который делает то же самое. Только теперь у него есть еще и грэдл с мавеном и, соответственно, JVM, которая не бесплатная (в плане ресурсов). Те же вопросы к питону.
Я в чем-то могу его понять, наверное, когда там что-то сложнее, и больше, и имеет смысл использовать ООП. Но, блин, заводить комбайн ради трех колосков?
Spyman
19.12.2024 17:53Просто когда есть знакомый инструмент, а задачи уровня "это для хобби, лепим из говна и палок" - так и хочется вкорячить знакомое)
Я вот тоже, когда в пет проекте нужно поднять север или перелопатить сотню файлов - зачастую поднимаю для этого nodejs. Да, можно файлы и в shell скрипте перебрать, и на python написать все. И не надо будет ничего устанавливать. Но зачем - если вспоминать синтаксис shell скриптов я буду дольше, чем писать весь скрипт на js)
nehaev
Хорстманну надо бы почитать про scala-cli: вот удивится, наверное.
breninsul
а ещё есть kotlin скрипты...