2015-02-09

Про языки и DSL

Я уже как-то писал про инсайты, приходящие именно в тот момент, когда ты готов услышать их. Хотя большой вопрос: каков вклад счастливой случайности? Может это знание, как тайные знаки всегда было рядом, а ты их смог увидеть и понять, только когда стал готов, а случай подвернется рано или поздно.

Embedded. Сначала был Diablo

Было это в беззаботные студенческие времена (лет 8 назад): кореш поднял у себя на работе батл.нет и мы в сободное от безделья время зарубались в Diablo II. Довольно быстро мне надоело тупо фармить и захотелось разнообразия - был найден D2jsp (java script parser) и за пару дней непрерывной работы бота герои для обмена вещами были под завязку забиты уникальными вещами на любой вкус. Исход немного предсказуем - дальше играть стало совершенно неинтересно (gameplay was ruined by cheater). Тем не менее, мне стало интересно, как устроен бот и я немного поковырял скрипты. JS я на тот момент более менее понимал и тут меня капитально накрыло: язык общего пользования, в котором доступно API для взаимодействия в интерфейсом игры, доменная модель для получения информации о персонаже. После этого я по-новому взглянул на DOM API, предоставляемый браузером и на XMLHttpRequest. Как это делается я узнал сильно позже, но на тот момент этого было достаточно для неизгладимого впечатления.

Lex/AWK и конфиги

Первая работа окунула меня с головой во FreeBSD 5 или 6, где гуй KDE 3.5 нужно было запускать командой startx. Конфиги для Esomo парсились через Lex, AWK тоже вроде использовался для каких-то внутренних нужно, суть одна - набор правил, описанных регулярными выражениями. Они не воспринимались как что-то крутое, рабочие утилитарные инструменты. Очень часто этого не хватало на винде, люди вынуждены извращаться, портирование не помогает из-за проблем с консольными кодировками (как там дела обстоят в 8-ке и старше я не знаю).

JavaCC и Excel

Мы делали супе-пупер универсальный инструмент для сбора и консолидации данных. Проблема была в том, что у нас было 4 вида формул: вычисления на текущем листе (аналог excel), агрегатные вычисления на листе (sum,max,min,avg etc.), агрегатные функции поверх множества отчетов сданных за разный период и вычисления с использованием результатов агрегатных функций. Все это делалось при помощи SQL, но в один прекрасный момент захотелось динамизма: довольно глупо в вебе рисовать аналог excel и жать кнопку сохранить, чтобы пересчитать сумму в колонке. Были написаны аналоги SQL функций на JS (тут я вспомнил d2jsp).

Следущим очевидным шагом было написание языка, который транслируется в SQL (выбирая данные из таблиц) и JS (который работает с массивами). Взяли старый и проверенный javacc - после Lex и AWK воспринималось на ура, просто java диалект проверенных временем технологий. Мы взяли готовую грамматику для plsql (поскольку он был основной целью и совпадал на 95% с исходником) и доточили для своих нужд. Совершенно бесплатно получили еще и проверку синтаксиса. Короче, писать свои языки, особенно если брать готовые грамматики - оказалось очень просто.

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

Fluent API

Второй раз накрыло, когда зачем-то ковырял Guava. Обладая небогатым инструментарием из анонимных, inline-классов и vararg-аргументов строится красивейший API на билдерах. Реально пирдуха, простейшая по-сути вещь, ретроспективно очевидная как колесо, после такого хочется выбросить половину своего кода и переписать его на fluent API.

Groovy DSL

Groovy - это язык, который хочет казаться DSL надстройкой над java. У нас был простой синтаксис, где точка с запятой и скобки необязательны, легко можно пердавать замыкания в качестве параметра и целое множество аннотаций всех сортов и расцветок. Не то что бы это был необходимый запас для создания DSL. Но если начал собирать метаинструменты, становится трудно остановиться. Единственное что вызывало у меня опасение - это AST-трансформации. Нет ничего более беспомощного, безответственного и испорченного, чем макро зомби. Я знал, что рано или поздно мы перейдем и на эту дрянь.

Шутки шутками, но на данный момент groovy видится как терминальная стадия - это тот инструмент, который я буду использовать в первую очередь. Как определить успешность DSL? - им начинают пользоваться люди от бизнеса (непередаваемое ощущение, когда тебе говорят в строке 5 неправильно рассчитывается прибыль): excel тут пример оглушительного успеха, а SQL пример такого же оглушительного провала этой затеи. Неотъемлимыми качествами являются: синтаксис, который может понять человек далекий от программирования (без императивщины, модульного программирования, рекурсии, циклов), обратная связь (валидация синтаксиса, понятные ошибки с примерами) и запуск даблкликом без танцев с тулчейном - все это есть в groovy. Очень многое в языке завернуто в DSL - в качестве примера можно посмотреть на Criteria в GORM (хотя реализация с точки зрения использования ужасна).