CodeFest 2012. Сидельников А. — Опыт создания DSL на Ruby. Где...

27
Опыт создания DSL на Ruby. Где применить, как готовить и сколько добавить метапрограммирования. Антон Сидельников [email protected]

description

 

Transcript of CodeFest 2012. Сидельников А. — Опыт создания DSL на Ruby. Где...

Page 1: CodeFest 2012. Сидельников А. — Опыт создания DSL на Ruby. Где применить, как готовить и сколько добавить метапрограммирования

Опыт создания DSL на Ruby. Где применить, как готовить и сколько добавить метапрограммирования.

Антон Сидельников[email protected]

Page 2: CodeFest 2012. Сидельников А. — Опыт создания DSL на Ruby. Где применить, как готовить и сколько добавить метапрограммирования

Содержание

• О самой концепции DSL• Чем Ruby хорош для DSL• Использование Ruby-based DSL в

реальных проектах• Ruby-based DSL Roadmap

2

Page 3: CodeFest 2012. Сидельников А. — Опыт создания DSL на Ruby. Где применить, как готовить и сколько добавить метапрограммирования

Предметно-ориентированный язык (Domain Specific Language)

• Предназначен для решения узкого круга задач

• Понятия предметной области являются элементарными

• Задачи решаются в терминах предметной области

3

Page 4: CodeFest 2012. Сидельников А. — Опыт создания DSL на Ruby. Где применить, как готовить и сколько добавить метапрограммирования

Как можно применить DSL

• Конфиги (apache, etc.), Make• Языки описания данных (HTML, TeX)• Язык описания правил (ipfw)• Язык для написания тестов• Высокоуровневый язык для написания

бизнес-логики

4

Page 5: CodeFest 2012. Сидельников А. — Опыт создания DSL на Ruby. Где применить, как готовить и сколько добавить метапрограммирования

Использование DSL

Pro•Повышение уровня абстракции

•Более явная логика кода

•Повышение скорости разработки

•Можно передать управление не-программисту

Contra•Расходы на создание и поддержку языка

•Область применения действительно мала

•Требует обучения пользователя

5

Page 6: CodeFest 2012. Сидельников А. — Опыт создания DSL на Ruby. Где применить, как готовить и сколько добавить метапрограммирования

Два подхода к созданию DSL

External•Придумываем грамматику

•Пишем интерпретатор...

•…транслятор...

•...или компилятор (если скучно)

Internal•Выбираем язык по вкусу

•Используем синтаксис и семантику старого языка для создания иллюзии нового

6

Page 7: CodeFest 2012. Сидельников А. — Опыт создания DSL на Ruby. Где применить, как готовить и сколько добавить метапрограммирования

Ruby-based DSL

• Internal DSL• Поддерка IDE• Доступ к Ruby gems и прочему

существующему коду• Еще большая скорость разработки• Гибкий синтаксис, обилие syntax sugar• Развитая система метарограммирования• Возможность интеграции с другими языками

7

Page 8: CodeFest 2012. Сидельников А. — Опыт создания DSL на Ruby. Где применить, как готовить и сколько добавить метапрограммирования

bender = Person.new 'Bender'bender.wishes :lunapark, :with => [:blackjack, :hookers]bender.wishes :death, :to_all => :humans

Bender.wishes {lunapark with blackjack, hookersdeath to_all humans

}

Person bender = new Person("Bender");bender.wish("lunapark", new HashMap<String, String[]>() {{ put(“with", new String[]{"blackjack", "hookers"} ); }});bender.wish("death", new HashMap<String, String[]>() {{ put("to_all", new String[]{"humans"} ); });

8

Page 9: CodeFest 2012. Сидельников А. — Опыт создания DSL на Ruby. Где применить, как готовить и сколько добавить метапрограммирования

“По моему опыту, большинство грамотно написанных на Ruby программ уже являются DSL – просто по природе синтаксиса Ruby.”

- Jamis Buck, 37 signals

9

Page 10: CodeFest 2012. Сидельников А. — Опыт создания DSL на Ruby. Где применить, как готовить и сколько добавить метапрограммирования

Простой пример

<?xml version="1.0" encoding="UTF-8" standalone="no"?><repository> <solver class="implementation.solvers.SempSolver"> <setup> <param type="string" name="SOLVER_HOME">"~/.wine/drive_c/semp/"</param> </setup> <method name="EfficiencyTrendAnalysis" input="reflexive"> <param type="string" name="MODULE_PATH">"modules/EfficiencyTrendAnalysis/"<param> ... </method> ... </solver></repository>

Перепиши мне конфиг, а то я тут

ничего не понимаю..!

10

Page 11: CodeFest 2012. Сидельников А. — Опыт создания DSL на Ruby. Где применить, как готовить и сколько добавить метапрограммирования

Простой пример

require 'repo'

solver("implementation.solvers.SempSolver") { SOLVER_HOME = "~/.wine/drive_c/semp/" MODULES_HOME = File.join SOLVER_HOME, "modules" method { name "EfficiencyTrendAnalysis" MODULE_PATH = File.join MODULES_HOME, name }}

Перепиши мне конфиг, а то я тут

ничего не понимаю..!

Сам перепиши!

11

Page 12: CodeFest 2012. Сидельников А. — Опыт создания DSL на Ruby. Где применить, как готовить и сколько добавить метапрограммирования

Жизненный пример

monkey – язык для функционального тестирования промышленных энергетических сетей. Основные функции:

• Описание тест-кейсов• Сбор статистики• Анализ результатов исполнения тест-

кейсов

12

Page 13: CodeFest 2012. Сидельников А. — Опыт создания DSL на Ruby. Где применить, как готовить и сколько добавить метапрограммирования

Исходная инфраструктура системы

• Система управления сетями, написанная на Java

• Доступ к данным через удаленную SQL-базу• Надо тестировать код на mockup-системах• Нужен контроль состояния работающих

систем

13

Page 14: CodeFest 2012. Сидельников А. — Опыт создания DSL на Ruby. Где применить, как готовить и сколько добавить метапрограммирования

Исходная ситуация с тестированием

А как нам писать функциональные тесты

для диагностики работающи систем?

А как нам писать функциональные тесты

для диагностики работающи систем?Окей, вот вам

WebAPI Окей, вот вам

WebAPI

СерверСервер

Java CoreJava Core SQL-базаSQL-база

WebAPIWebAPI SSH-доступSSH-доступ А тесты на PHP писать?!А тесты на PHP писать?!

14

Page 15: CodeFest 2012. Сидельников А. — Опыт создания DSL на Ruby. Где применить, как готовить и сколько добавить метапрограммирования

Решение: JRuby(в других условиях здесь могли бы быть С-Ruby,

IronRuby, а может и другие языки, например Scala или Clojure)

15

Page 16: CodeFest 2012. Сидельников А. — Опыт создания DSL на Ruby. Где применить, как готовить и сколько добавить метапрограммирования

JRuby

• Выполняется на JVM• Прямая работа с Java-объектами через

публичные интерфейсы• Контроль результатов и сбор данных

напрямую из SQL-базы• Обработка данных и анализ результатов

на стороне Ruby• Быстро и эффективно

16

Page 17: CodeFest 2012. Сидельников А. — Опыт создания DSL на Ruby. Где применить, как готовить и сколько добавить метапрограммирования

Результат

СерверСерверJava CoreJava Core

Ruby DSL-frameworkRuby DSL-framework

Запросы к ядру

Запросы к ядру

Сбор данных из БД

Сбор данных из БД

Методы анализа данных

Методы анализа данных

А где PHP, к которому мы уже привыкли?!

А где PHP, к которому мы уже привыкли?!

SQL-базаSQL-база

17

Page 18: CodeFest 2012. Сидельников А. — Опыт создания DSL на Ruby. Где применить, как готовить и сколько добавить метапрограммирования

РезультатTestTouCostOneDay = testcase(MockBaseTestCase, 'TestTouCostOneDay') {

request categorizedMetricDataRequest(subscriber, sdp) { metric(Cost) granularity(DAY) interval(accountInterval.start, accountInterval.start) timezone("PST") }

validate {granularity.should == DAYprocessor(TouProcessor).cost.should

be_granular_limiteddpAccount.servicePlan.costLimit

}}

18

Page 19: CodeFest 2012. Сидельников А. — Опыт создания DSL на Ruby. Где применить, как готовить и сколько добавить метапрограммирования

Как подойти к созданию Ruby-DSL?

19

Page 20: CodeFest 2012. Сидельников А. — Опыт создания DSL на Ruby. Где применить, как готовить и сколько добавить метапрограммирования

DSL Roadmap

• Начните с фиксации предполагаемого DSL в виде валидного Ruby-синтаксиса

• Не увлекайтесь моделью – все равно её переделывать

• Сразу подумайте о том, как вы хотите соединить DSL с существующей средой

20

Page 21: CodeFest 2012. Сидельников А. — Опыт создания DSL на Ruby. Где применить, как готовить и сколько добавить метапрограммирования

DSL Roadmap

• Используйте Test-Driven Development – это естественный способ опробовать язык до того, как он окончательно создан

• Ведите разработку малыми итерациями• Согласуйте вид DSL с экспертом предметной

области, если сами им не являетесь

21

Page 22: CodeFest 2012. Сидельников А. — Опыт создания DSL на Ruby. Где применить, как готовить и сколько добавить метапрограммирования

DSL Roadmap

• Разберитесь с тем, что может, и что не может Ruby. Метапрограммирование является основой создания DSL.

• Убедитесь, что знаете все эти слова:• eval, instance_eval и class_eval• define_method и alias_method• method_missing и const_missing• Open class(1.8) или Refinements (1.9)

• Но повторяю – не увлекайтесь моделью!

22

Page 23: CodeFest 2012. Сидельников А. — Опыт создания DSL на Ruby. Где применить, как готовить и сколько добавить метапрограммирования

DSL Roadmap

• Минимизируйте зашумленность языка• Используйте syntax sugar:

• опциональные скобки и терминальные символы

• символы вместо строк• блоки• литеральные массивы и хэши• группировка аргументов

23

Page 24: CodeFest 2012. Сидельников А. — Опыт создания DSL на Ruby. Где применить, как готовить и сколько добавить метапрограммирования

DSL Roadmap

• Зафиксируйте модель, когда вы целиком разобрались с внешним видом языка

• Наведите порядок, проведите рефакторинг

24

Page 25: CodeFest 2012. Сидельников А. — Опыт создания DSL на Ruby. Где применить, как готовить и сколько добавить метапрограммирования

Дополнительная информация:

• Книга “Metaprogramming Ruby” из серии “The Pragmatic Bookshelf”

• http://rubyconf2008.confreaks.com/advanced-dsls-in-ruby.html

• http://obiefernandez.com/presentations/obie_fernandez-agile_dsl_development_in_ruby.pdf

• Martin Fowler “Domain Specific Languages”

25

Page 26: CodeFest 2012. Сидельников А. — Опыт создания DSL на Ruby. Где применить, как готовить и сколько добавить метапрограммирования

О чем это все было?

• Существуют случаи, когда использование DSL оправдано

• Динамические языки позволяют сравнительно дешево получать это преимущество

• Современные языки можно интегрировать в широкий класс промышленных проектов

• Лучший способ оценить плюсы и минусы – попробовать

26

Page 27: CodeFest 2012. Сидельников А. — Опыт создания DSL на Ruby. Где применить, как готовить и сколько добавить метапрограммирования

Вопросы?

Сидельников Антон

[email protected]+7(923)114-5551

27