О грустном
Сидел я вчера на очередном интервью, грустил, что
javax в меня какашками кидается, и слушал печальную историю соискателя о том, как он мучался пытаясь прикрутить сериализацию в JSON к модели на Java не имея ее исходников. От вида его попыток настроение мое не улучшилось.
Мы попробуем лучше, потому что, в отличие от него, мы знаем про Groovy.
Этот пост является более-менее продолжением
вчерашнего. Им хотелось бы убить мешок зайцев:
- Показать реальный пример мета-программирования на Groovy
- Показать немного более навороченный способ работы с мета-классами
- Показать работу с json-lib в Groovy
- Рассказать про dependency management для бедных
Вместо посвящения
Всегда… Нет. Никогда не выходи в пургу пиши такой код ни для чего, кроме подобных забав.
Гийом — lead разработки языка Groovy
Reflection во зло
Один мой друг — большой любитель головоломок. Всяких, и программистких в том числе. Вот его последняя забава:
Напишите нужный код в static initializer, чтобы assert перестал падать:
public class Test {
static {
//Write some code here
}
public static void main(String[] args) {
Integer a = 20;
Integer b = 20;
assert (a + b == 60);
}
}
Если вы решите попробовать, не забудьте
включить assertions (флагом -ea).
Дальше будет решение и кое какие рассуждения на тему, так что если вы уже справились, или вам влом -смело под кат.
Нил Форд, Архитектор ПО, ThoughWorks Inc.
03 Апреля 2012
перевод статьи
Functional thinking: Functional design patterns, Part 2
В последней
части (на
хабре), я начал исследование взаимодействия традиционных шаблонов “Банды четырех” (Gang of Four, GoF) и более функциональных подходов. Я продолжу разбор в этой части, показывая решение типичных проблем в рамках 3х различных парадигм: паттерны, метапрограммирование и композиция функций.
Если первичная парадигма, которая поддерживается вашим ЯП объектная, то намного проще думать о решении каждой проблемы в рамках ее терминов. Тем не менее, большинство современных языков программирования являются мультипарадигменными, это значит, что они поддерживают объекты, метаобъекты, функциональную и другие парадигмы. Изучение использования различных парадигм для наиболее подходящего решения проблемы — часть эволюции в лучшего разработчика.
25 апреля 2012, 02:07
210
Нил Форд, Архитектор ПО, ThoughWorks Inc.
06 Марта 2012
перевод статьи
Functional thinking: Functional design patterns, Part 1
Некоторые представители функционального мира утверждают, что концепция шаблонов проектирования содержит недостатки и ей нет места в мире функционального программирования(далее ФП). Это мнение может быть подтвержено используя довольно узкое определение слова
шаблон(pattern), но это больше касается семантики, чем реально использования.
Концепция шаблона проектирования — именованное, представленное в виде каталога решение для распространенной проблемы- живо и здравствует.Тем не менее, шаблоны могут принимать различные обличья, в рамках разных парадигм. Учитывая, что подходы к построению программ и решению проблем в функциональном программировании другие, некоторые шаблоны «Банды четырех»(Gang of Four, GoF) исчезают, другие сохраняют проблему, но решают ее радикально по-другому.Эта часть и несколько других будет содержать в себе исследования некоторых традиционных шаблонов проектирования и переосмыслять их в рамках функционального подхода.
23 апреля 2012, 10:39
209
В одном из своих проектов мне понадобилось автоматизированно формировать документы договоров для клиентов. Договор представляет собой юридический документ длиной около 10 страниц и является шаблоном: в нужных местах подставляются данные конкретного клиента.
Задача
Первичные требования были такими:
В сложном стилизованном документе doc или docx вывести нужную информацию в помеченных местах.
В дальнейшем они были уточнены и расширены:
- В сложном стилизованном документе docx вывести данные в помеченных местах.
- Разметка вывода данных должна быть похожа на скриптлеты:
${}, <%%>, <%=%>.
- Данными для вывода могут быть объект. Нужна возможность обращения к полям.
- Для вывода использовать один из скриптовых языков: Groovy, JavaScript.
- Нужно иметь возможность выводить списки объектов в таблицы, в каждой ячейке отображая поля.
Имеющиеся решения
Оказалось, что имеющиеся в области продукты (я говорю про платформу Java), не решают поставленную задачу. Ниже краткий обзор продуктов:
Jasper reports
В качестве шаблона использует файл xml-разметки *.jrxml. Файл разметки документа + данные (как из БД, так и Map параметров) отдаются процессору, который формирует любой из следующих форматов: PDF, XML, HTML, CSV, XLS, RTF, TXT.
Не устроило:
- Это не WYSIWYG, даже при наличии iReport — визуального средства формирования jrxml-файлов.
- Надо хорошо изучить JasperReports API, чтобы создать и стилизовать сложный шаблон.
- Не выводит в нужном формате. Можно и PDF, но хотелось бы иметь возможность потом поредактировать выходной документ.
Geb на практике
Я вот, скажем, люблю, когда всю работу за меня делают роботы. Поэтому считаю необходимым всякие скрипты, inspections, проверщики орфографии и, разумеется, автоматические тесты. Кстати, как вам такой тестик:
Browser.drive(driver: new InternetExplorerDriver()) {
go "http://www.google.com"
$('form', action:endsWith('/search')).q =
'тестирование при помощи geb и spock'
$('button', value:'Поиск').click()
waitFor { $('#search') }
assert $('#search').size() == 1
assert $('#search').find('li.g a.l').size() > 0
println "Первый результат: " + $('#res').find('li.g a.l', 0).text()
}.quit()
Мне кажется, у таких тестов высокая степень читаемости — неважно даже, какой это язык. Можно по такому вот образцу написать еще несколько подобных же тестов, не имея вообще никакого понятия о Geb, Groovy и о том, как это работает. Но для полного понимания немного углубимся в основы.
Не так давно я задавал вопрос в Groovy mail-list — есть ли какой-то устойчивый список вещей, которые надо избегать при написании высокогопроизводительного на Groovy. Среди прочих советов, один из главных разработчиков Groovy, Jochen «blackdrag» Theodorou указал, что в общем случае, зачастую использование конкретного типа при объявлении переменной (например, MyType var =… вместо def var = ...) может ухудшить производительсть из-за накладных расходов на проверку типов и, если нужно, их приведение.
По утвеждениям разработчиков Groovy, многие из проблем в этом области наблюдались в версиях вплоть до 1.7 и были затем исправлены во время большой работы по общей оптимизации рантайма, проделанной в версии 1.9. Ниже, однако, небольшой эксперимент, который показывают эти накладные расходы даже на Groovy 1.8.3.
Перед этим экспериментом будет полезно просмотреть следующую статью —
groovy.codehaus.org/From+source+code+to+bytecode, где рассказывается про то, как по шагам исходный код на Groovy преобразуется в байткод JVM, а так же почитать какую-нибудь вводную статью в собственно байткод, например эту —
www.ibm.com/developerworks/ibm/library/it-haggar_bytecode/.
В какой-то момент проявилась одна заметная проблема, мешающая мне осуществить абсолютно 100% замену PHP на Groovy для веба без использования относительно тяжеловесного MVC-фреймворка Grails.
Это касается *.gsp страниц (Groovy Server Pages), представляющих собой html-страницы со вставками вида <%… %> с произвольным кодом на Groovy или Java, или на языке оригинала: "
GSP means GroovyServer Pages, which is similar to JSP (JavaServer Pages)."
Зачем нужен deploy-скрипт
Grails-приложения очень легко собираются в WAR. Делается это так:
grails war
Помимо того, что WAR собирается, очень хочется этот WAR еще и установить на сервер. В нашем случае это Tomcat. Установка вручную требует некоторой возни:
- Остановить сервер. Убить процесс, если он не остановился сам.
- Удалить старые файлы приложения (на всякий случай)
- Скопировать новый WAR на сервер. Иногда его нужно переименовывать (скажем, в ROOT.war)
В Maven эту работу может проделать, например, cargo plugin. Но с ним много приключений и настройки, причем он не особо учитывает особенности сервере.
Мы также можем использовать shell-скрипт. Но зачем писать на неудобном языке shell, когда есть замечательный кроссплатформенный язык Groovy?
Подключить полнотекстовый поиск в
Grails — задача довольно легкая. Для этого используется плагин
Searchable, который делает все сущности Grails-приложения индексируемыми. Searchable позволяет абстрагировать весь процесс индексирования и поиска. При этом сам плагин использует библиотеку
Compass, которая следит за тем, чтобы при изменении объекта (т.е. при сохранении в БД) он автоматически переиндексировался. Сам по себе Compass по сути является довольно мощным средством «поискового ORM»: