четверг, 7 апреля 2011 г.

Groovy вместе (и вместо) c Java в production. Part 1

Этот пост - некоторое мое размышление о текущем проекте, может кому-то будет просто интересно. А может, у кого-то есть здесь опыт именно в таких вещах, и он прокомментирует. А может, у кого-то просто очень богатый жизненный и профессиональный опыт, и он даст "мудрый совет"  (tm) . Итак.

В последнее время стараюсь сойти с прямых и строгих рельс стальных рельс Java на языки под платформу JVM. Приложение - платформа для систем управления поставками (логистика, розничная торговля и прочее), коотрая включает в себя разные компоненты для интеграции, расчетов прогнозов (статистические и эвристические методы) , планирования заказов, трекинга перевозок и еще много чего. Написана почти вся на Java (с примесью, как водится, SQL, HTML/CSS/Javascript, + в отдельных компонентах встречается флеш и питон). Пока что мы склоняемся к тому, чтобы окончательно выбрать Groovy. Почему же?



Какие были требования к новому дополнительному языку, и в каких местах мы бы хотели его использовать?


1) Тесты. Написание тестов, особенно таких, которые работают в сервлет-контейнере и базой данных, занимает много времени. По разным причинам. 


Первая, это то что сам язык Java весьма громоздкий, и даже отличная поддержка IDE мало помогает. Данные приходится либо загружать в базу из CSV-файлов, либо создавать руками на лету. И то и то требует много дополнительного scaffolding code, писать который неприятно, а на Java, с ее отсутствием поддержки для коллекция, замыканий, Path Expressions и прочих фич так и вовсе утомляет (когда появляется множество тест-классов каждый по 700-1000 строк кода).


Вторая причина довольно специфическая.  Написание контейнерных тестов на Java и их дописывание / отладка часто требует рестартов appserver-a  (у на это JBoss), который занимает 3-4 минуты. Собственно, любое изменение кода, кроме изменения "кода внутри методов" требует рестарта JBoss-a. Поменял название поля класса? Перезапусти JBoss. Поменял тип параметра метода с float на double? Перезапусти JBoss. И так все время.


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


3) Поддержка метапрограммирования - в понятном, не слишком зубодробительном виде, но достаточная, чтобы создавать DSL-языки для таких вещей, как моделирование иерархических структур данных в БД, построение экранов с отчетами, конфигурации портлетов - в общем того, что в мире Java-энтерпрайза традиционно программируется в XML-e.


Вообще,  "программирование в XML" - это совершенно отдельная вещь. Это именно то, что Джоэль Спольски называет leaky abstraction., только в чуть расширенном понимании. До тех пор, пока вы пишете много простых, тривиальных и однотипных кусков чего-то (чего-угодно), вы на коне, и ваша продуктивность приятно радует менеджеров. Это при условии, конечно, что автор соответствующего фреймворка (для парсинга этих XML-описания и построения по ним каких-то реальных вещей) правильно предвидел наиболее типичные случаи использования, и сделал для них нормальную поддержку.


Но как только вам надо сделать что-то такое, что автор соответствующего фреймворка не предусмотрел - ждите проблем - появления множества кода с тегами // HACK, // REVISE LATER, // FOLLOWUP, и долгих часов обсуждений, а можно ли это поддержать внутри фреймворка, а сколько на это понадобится времени, чтобы это реализовать, а сколько это будет стоить, а достаточно ли это нужная и важная фича, чтобы ее поддерживать на уровне фреймворка, и прочее, и прочее. А Тикет в джире все это время висит и висит c тегом "Being investigated".
Пока это все с причинами. Теперь, так какой у нас есть выбор?

1) Очевидно, хотелось бы что-то компилирующееся в Java-байткод. Лучше конечно, чтобы была полная двусторонняя интеграция с Java на уровне байткода JVM.
2) Предлагаюших писать на Lisp или Haskell в команде не нашлось.
3) Можно брать языки, портированные под JVM - JRuby, Jython. Jython мы используем кое-где, но только для скриптинга и работы с файлами в основном. Имело бы смысл, если бы кто-то из нас хорошо знал Ruby или Python. Таковые есть, но мало. Не айс.
4) Наконец, можно писать на языках, специально написанных под JVM, с синтаксисом, более похожим на Java, с явным упором на отличную интеграцию с ней, но перенявших фишки языков из предыдущих пунктов. Таких нашлось два - Groovy и Scala (есть еще Clojure, и недавно появившийся Morah, но это пока слишком экзотично).

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

Как итог, пока что медленно и осторожно пробуем интегрировать код на Groovy в намеченных областях, и кое-какие выводы уже можно сделать.


Плюсы:
 - Возможность перекомпилировать и перезагружать любые изменения в коде классов под JBoss, в отличие от Java hotswap, который умеет перезагружать "на лету" только изменения кода внутри методов класса. Мелочь, а дух захватывает.
 - Поддержка на уровне языка на списков, мэпов, регулярных выражений, замыканий, GPath-итерации по сложным структурым..метаобъектный протокол, билдеры иерархий, и еще много всего, что есть в Python-e и Ruby  и что делает код короче в разы и приятнее в чтении.


Минусы:
 - Динамическая (опциональная) типизация. Иногда удобно, но ненавижу эти no such property, no method found applicable for the following arguments:... и прочие обратные стороны медали под назвнанием "Rapid Software Development".
 - Редакторы кода и  поддержка IDE. Есть, и неплохая - но намного, НАМНОГО хуже чем для Java в современных IDE. Понятно, что язык динамический и многого не накрутишь..но все же (JetBrains - я в вас верю!!).


Часто упоминаемая на разных форумах и в блогах "низкая скорость выполнения" - не знаю, не заметил. Если вы часто вычисляете ряды фибоначчи (вместо того, чтобы раз посчитать и хранить), вычисляете фракталы Мандельбродта или перемножаете матрицы размером 10000 х 10000 - да, у вас вероятно будет много проблем. Но в типичном Enterprise Java приложении, я так думаю, не менее 60-80% кода можно переписать на Groovy без заметной потери производительности.


Да - мои мысли в этом посте немного связаны с этими.

1 комментарий:

  1. отлично, груви - классная штука, можно быстро к базе законнектиться, много удобнее vbs

    ОтветитьУдалить