Что такое dsl в программировании

Пример использование DSL (Domain Specific Languages) в реальном проекте

DSL (Domain Specific Languages) — языки, специфичные для решения задач какой-либо предметной области (в противовес языкам общего назначения типа Java или C#). Более подробное описание и примеры есть на википедии, я же хочу написать про то, как довольно легко встроить в приложение (C#) свой собственный DSL на базе языка Boo.

Перед нами стояла задача – сервис для онлайн-синхронизации данных из Active Directory в корпоративную информационную систему XXX (пользователи, организационные подразделения, группы и т.п. ). Основная очевидная сложность тут в том, что в каждом конкретном предприятии может быть своя схема AD (где-то для подразделений могут использовать OrganizationalUnit, где-то – группы и т.п.), равно как и свои классы для представления подразделений и работников в чистеме XXX (свои свойства и логика, причем на уровне сервиса синхронизации мы про них ничего не знаем, только их базовые классы), да еще и разные правила для синхронизации (где-то надо синхронизировать должности, где-то – нет).

Навскидку видится решение с заданием маппинга AD в XXX через XML, типа такого:
Что такое dsl в программировании. Смотреть фото Что такое dsl в программировании. Смотреть картинку Что такое dsl в программировании. Картинка про Что такое dsl в программировании. Фото Что такое dsl в программировании

Но тут вылезает множество проблем – необходимость реализации своего парсера правил (который создает объекты правил по XML) и интерпретатора правил (которой их выполняет), ограниченность возможностей XML (как, например, задать преобразование типов или чуть более сложное вычисление, например, добавить к имени логина префикес с именем домена) и т.д. Основное преимущество XML – к таким правилам легко прикрутить GUI для их задания, ну и задача это знакомая и уже не раз решенная.

Вот несколько примеров DSL из книги:

DSL для задания правил авторизации:
Что такое dsl в программировании. Смотреть фото Что такое dsl в программировании. Смотреть картинку Что такое dsl в программировании. Картинка про Что такое dsl в программировании. Фото Что такое dsl в программировании

DSL для задания правил поставки модульного ПО и требований модулей (+ тут же пример реализации редактора DSL с Intellisense и подстветкой синтаксиса на базе редактора кода из SharpDevelop):
Что такое dsl в программировании. Смотреть фото Что такое dsl в программировании. Смотреть картинку Что такое dsl в программировании. Картинка про Что такое dsl в программировании. Фото Что такое dsl в программировании

Все это примеры «внутренних» DSL, которые хостятся в языке Boo, то есть приведенный выше код – легальный код на Boo, который может компилироваться в обычные clr-классы или интерпретироваться. Boo выбран, так как у него довольно удобный синтаксис для DSL, богатые возможности по расширению синтаксиса (можно писать макросы, типа макросов в C, но они манипулируют не текстом, а синтаксическим деревом) + он открытый и у него удобное API компилятора, в которое можно легко встраивать свои действия.

Наш результат

Вот пример довольно сложного правила, которое синхронизирует пользователей и OrganizationalUnit из AD в департаменты и работников корпоративной системы XXX, при этом также учитывая и иерархию подразделений:
Что такое dsl в программировании. Смотреть фото Что такое dsl в программировании. Смотреть картинку Что такое dsl в программировании. Картинка про Что такое dsl в программировании. Фото Что такое dsl в программировании

Кстати, эти правила прозрачно отлаживаются в студии без установки в нее каких-либо плагинов.

Внутренняя реализация

Собственно на самом деле тут все просто и все сделано стандартным синтаксисом Boo. Правило компиляется в контексте нашего класса, в котором есть методы с именами rule, for_type и т.д. Так что код

for_type user
это на самом деле просто вызов метода for_type c одним строковым параметром «user». А внутри метода мы просто записываем переданное значение в свойство правила и в дальнейшем можем им манипулировать.

Entity и ldap – это свойства правила с типами, которые реализуют специальный интерфейс Boo – IQuackFoo, который позволяет реализовать в них динамическую типизацию (типа IExpandoObject и dynamic в C#). Поэтому когда в правиле пишут ldap.GivenName, класс ldap на самом деле ищет в атрибутах пользователя атрибут с именем «GivenName» и возвращает его значение. Аналогично и с entity.

Единственное синтаксически хитрое место – выражение on entity.Sid == ldap.objectGUID. Тут on – это мета-метод, который отрабатывает во время компиляции и подменяет синтаксическое дерево выражения entity.Sid == ldap.objectGUID на другое. Конкретно тут мы просто выпарсиваем из дерева имена свойств, по которым задан ключ и запоминаем их. Выглядит мета-метод как просто метод на C#, который помечен специальным атрибутом и который на вход принимает синтаксическое дерево и возвращает новое дерево. Все просто:).

Детально по реализации спрашивайте, ну или стоит просто почитать DSLs in Boo и поковырять Rhino DSL, там все очень здорово описано, а Rhino DSL позволяет подключить к проекту DSL на Boo за пару минут.

Источник

Сделать сложное простым: что такое DSL, или зачем вам новый язык программирования

Сделать простое иногда во много раз сложнее, чем сложное
© Михаил Калашников

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

Действительно, зачем это нужен ещё один язык программирования? Понятно, он может быть нужен в каких-то НИИ при университетах, но обыкновенному бизнесу — какой толк от этой заумной мути? Вообще к чему столько разных языков, почему бы не использовать один единственный? Давайте разберёмся.

Почему бы не пользоваться одним языком

Жил да был в Великобритании выдающийся математик, логик, криптограф, и звали его Алан Тьюринг. В числе других открытий он придумал машину имени себя. Опуская подробности, скажем, что с помощью этой машины можно реализовать всё то же, что и с помощью любых средств программирования более высокого уровня. То есть любую программу на любом языке можно переписать с помощью этого достаточно простого средства. Тем более на любом языке типа Java или PHP можно реализовать эту самую машину.

Как следствие, существует критерий полноты по Тьюрингу-Чёрчу. Язык называется полным, если на нём можно реализовать машину Тьюринга. Все популярные языки программирования общего назначения (Java, C#, PHP, Python, Scala, JavaScript и так далее) являются полными. Что же это означает? Все популярные языки эквивалентны! Ну вот, смотрите: мы знаем, что все программы можно выполнить с помощью машины. Машину же, которая выполняет, можно написать что на PHP, что на C++. Получается, одну и ту же программу, записав её на языке машины Тьюринга, можно выполнить везде. А мы знаем, что так можно записать вообще любую программу.

На практике это означает, что программу на языке, скажем, JavaScript, поднатужившись, можно переписать на С++. Обратное тоже справедливо. Да, имеют значение библиотеки и фреймворки, но саму логику можно без проблем перенести с одного языка на другой.

Зачем тогда разные языки нужны, почему бы не пользоваться одним? В знаменитом романе Семюэля Дилэни «Вавилон 17» описан человек с выключенной частью мозга. Вместо этого он обучен искусственному языку, близкому по синтаксису к записям математических выражений. Он замечательно подходит для быстрого решения логических задач, компактен и удобен, но ограничен. Например, отсутствовали слова «я» и «ты». Поэтому парадоксы, такие как «Севильский цирюльник», мозг ограниченный «Вавилоном 17», сожжет или заставит обратиться к отключенной части. То есть языковые конструкции во многом определяют способ мышления.

Рассмотрим язык математики более подробно. Вот, например, описание доказательства теорем методом математической индукции:

Что такое dsl в программировании. Смотреть фото Что такое dsl в программировании. Смотреть картинку Что такое dsl в программировании. Картинка про Что такое dsl в программировании. Фото Что такое dsl в программировании

Расшифровывается это так. Допустим, что:

Тогда все утверждения нашей последовательности верны. Обратите внимание: вместо нескольких строк текста имеем лишь одну строку со строгим определением, понятным любому математику.

Что же такое DSL

Domain Specific Language, или язык предметной области, — это язык, созданный для конкретной области применения. Построение его, или структуры данных, отражают специфику решаемых им задач © Википедия.

То есть, если человек знает свою работу, учить DSL не надо — достаточно взглянуть один раз, и всё понятно (см. пример с математикой). Также хороший DSL не требует больших знаний в теории и практике программирования. Во многих, например, нет циклов. В некоторых — условных операторов (типа «if»). Часто язык является не полным по Тьюрингу, то есть написать любую программу с его помощью нельзя. Опять же, вспомним язык математики или кванторов. Он используется лишь для описания теорем или для их автоматического доказательства. Писать web-сервисы с его помощью было бы затруднительно.

Примеры использования DSL

DSL используются очень по-разному. Рассмотрим несколько из них и постараемся понять, в каком же случае следует их использовать.

Резак лазера

Положим, вы — инженер кораблестроитель и хотите вырезать большущую деталь для корпуса судна. Раньше это делалось так: на плотном картоне или фанере вычерчивали детальки, вырезали, прикладывали к листу стали, и люди, которых называли кернильщиками, ползали по листу и набивали по контуру выкройки впадинки. Дальше газорезчик шёл по контуру и вырезал. Представляете, что будет, если резчик с утра перебрал? А можно сделать это автоматически, чтобы робот считывал чертёж и сам ехал по листу, вырезая нужную деталь? Да, можно! Однако проблема в том, что траекторию его передвижения нужно как-то задать. Мол, поедь туда, опусти резак и дальше двигайся эдаким манером. Для этого нам нужны следующие команды:

Таким образом, в наиболее простом случае нам нужны только три команды:

Как видите, язык очень простой, но с его помощью можно вырезать деталь любой сложности. Для программирования с его помощью достаточно навыков на уровне уверенного использования ПК. Добавив к этому языку переменные, условные операторы, циклы и процедуры, получим очень мощное средство. Как бонус — исследование кода методом белого ящика. К примеру, можно проверить, не вылезает ли наш резак за пределы листа металла.

Алгоритмический трейдинг

Трейдер редко ошибается дважды — обычно раза три или больше
© Из грустного опыта продавшего квартиру

Каждый хочет купить дешевле и продать дороже — вроде бы понятно. Но как определить правильное время для сделки, если завтра цена может вырасти или упасть? Решение принимается с помощью фундаментального (новости, анализ экономических и политических событий) и технического (экстраполяция стоимости ресурса на основании предыдущих данных). Признаки, по которым судят о поведении цены, теоретически не доказаны и не точны. То есть какая то связь с реальностью усматривается, но обычно берут несколько признаков и принимают решение о закрытии или открытии сделки, когда сигнал о покупке либо продаже подают все используемые индикаторы.

Кривая цены меняется очень быстро. Данные, полученные 15 минут назад, как правило, интересны только для историков. Деньги на бирже крутятся большие, так что потерять несколько сот миллионов долларов за минуту можно запросто. Поэтому человеческий фактор хорошо бы свести к минимуму. Но как это сделать, если общей теории поведения цены не существует и стратегии торговли трейдер выбирает их с помощью интуиции? Один из способов уберечься от ошибки — создать специальный язык с минимумом «шума». Оставить в языке только необходимое, безжалостно избавясь от возможностей, которые нам не нужны. Что же нужно для трейдинга?

Давайте посмотрим, как будет выглядеть эта стратегия на языке Java. Допустим, мы хотим получить сигналы о покупке/продаже валют на серверах трех бирж с помощью стратегий: «фибоначчи», «скользящее среднее», «преобразование Гильберта». Для простоты будем считать, что время измеряется в тиках, название биржи, на которой работает сервер, задается просто строкой, и торгуем мы валютами — меняем доллары, евро или ещё что-нибудь на украинскую гривню и обратно.

На первый взгляд, код выглядит хорошо, но, если приглядеться, в нём полно ошибок.

Что такое dsl в программировании. Смотреть фото Что такое dsl в программировании. Смотреть картинку Что такое dsl в программировании. Картинка про Что такое dsl в программировании. Фото Что такое dsl в программировании

Во первых, время работы стратегий меньше, чем время, в течение которого работает сервер. Во вторых, мы запускаем только один сервер, вместо трёх. Так что с этим кодом материальные потери не заставят себя долго ждать.

С другой стороны, трейдинг — это постоянный стресс и гонка. Работать нужно действительно быстро, но без ошибок. Как же быть?

Давайте посмотрим, как мог бы выглядеть текст программы, представленной выше, записанный на действительно удобном языке.

Что такое dsl в программировании. Смотреть фото Что такое dsl в программировании. Смотреть картинку Что такое dsl в программировании. Картинка про Что такое dsl в программировании. Фото Что такое dsl в программировании

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

Преимущества предложенного примера очевидны. Во первых, текст стал лаконичным: сервера указываются ровно один раз. Стратегии — в непосредственной близости от сервера, на котором запускаются. Во вторых, мы избавляемся от ненужных подробностей. Трейдеру вовсе и не нужно знать, что такое Thread или что итоговая программа будет написана на языке Java.

Разработка игровой логики

Ошибка: робот погибает при попадании в него гранаты (именно от попадания, а не от взрыва). Д — дизайнер, П — программист.
Д: программисты всё сломали! почему так получается?!
П: естественно, так получается! потому, что у гранаты масса 100 кг! зачем вы это сделали?
Д: да?! а чтобы граната в воде тонула!
П: а почему она с нормальной массой не тонет?
Д: а потому что у воды плотность большая! (прим.: больше, чем у ртути)
П: а почему плотность такая большая?!
Д: а чтобы ящики деревянные плавали!
П: а почему они иначе не плавают?!
Д: а потому что у них масса 50 кг!
П: а зачем такая масса?!
Д: а иначе они некрасиво разваливаются!

Более того, игры сейчас выходят на множестве разных платформ. Выпустили под Windows, и надо выходить на Vii, на планшетах, на smart TV и так далее. Каждый релиз приводит к переписыванию кода, который уже работает и оттестирован, хотя логика действий персонажей не меняется при переходе от устройству к устройству. Можно, конечно, использовать кроссплатформенные средства. Такие как Unity, или Haxe, но, как правило, проблема в том, что кроссплатформа работает одинаково плохо на всех устройствах. То есть хотелось бы сделать так, чтобы разрабатывать заново нужно было только специфические для конкретной платформы вещи, оставив логику без изменений.

Можно ещё использовать для логики скриптовые языки, однако даже они слишком сложны для того, чтобы использовать их без изучения. Там много подробностей, нужных для программиста, но лишних для конструкций: «Если произошло это — сделай то».

Что же делать, учить дизайнера программированию? Но это две довольно разные и в каком-то смысле противоположные специальности. Хотелось бы сделать так, чтобы дизайнер достаточно простым способом без помощи программиста мог поменять поведение персонажей.

Конечный автомат

Представим игровую логику в виде состояний персонажа и переходов между ними. К примеру, у робота может быть три состояния: «бежать к игроку», «стрелять» и «искать патроны», когда они кончились. Действия происходят при входе в состояние, выходе из него, переходе от одного состояния в другое и когда состояние между через определенный метод времени не изменилось. Можно описать состояния и переходы с помощью JSON, или XML и потом воспользоваться шаблоном проектирования «машина состояний», как это описано в банде четырёх. XML для описания представлен ниже:

Но XML очень не удобен для программирования. Покажем, как это описать с помощью DSL-языка.

Что такое dsl в программировании. Смотреть фото Что такое dsl в программировании. Смотреть картинку Что такое dsl в программировании. Картинка про Что такое dsl в программировании. Фото Что такое dsl в программировании

Как видите, описание стало гораздо более лаконичным и удобочитаемым. Появилась подсветка синтаксиса. Скажу вам по секрету, автокомплит и подсветка ошибок тоже есть.

Таким образом, можно отделять игровую логику от платформозависимых вещей: графики, ввода-вывода, управления и даже от того, как методы «стрелять», «бежать» и «кричать» реализованы на практике. Последнее является частным случаем декларативного программирования: вместо того, чтобы реализовывать детальный алгоритм, мы описываем конечный результат. Вместо того, чтобы говорить компьютеру как делать, мы говорим что.

Выводы

Все рассмотренные DSL:

DSL применяется, когда необходимо записать достаточно сложную логику и избавить специалиста в определённом домене от необходимости изучать программирование, а программиста — разбираться в предмете. Обратно, если для реализации задачи не нужно обладать квалификацией помимо собственно программирования, DSL вам не нужен.

Вторая статья будет посвящена графическим языкам программирования, последующие — способам реализовать DSL и применениям их в разных, иногда неожиданных областях.

Что такое dsl в программировании. Смотреть фото Что такое dsl в программировании. Смотреть картинку Что такое dsl в программировании. Картинка про Что такое dsl в программировании. Фото Что такое dsl в программированииПідписуйтеся на Telegram-канал «DOU #tech», щоб не пропустити нові технічні статті.

Источник

О доменных языках

В отличие от универсального языка, такого как C# или UML, доменный язык (DSL) предназначен для выражения инструкций в определенном пространстве или домене.

Хорошо известный домен DSL включает регулярные выражения и SQL. Каждый домен DSL гораздо лучше, чем универсальный язык для описания операций с текстовыми строками или базами данных, но гораздо хуже для описания идей, находящихся за пределами собственной области. Для отдельных отраслей также предусмотрен собственный домен. Например, в телекоммуникационной отрасли языки описания вызовов широко используются для указания последовательности Штатов в телефонном звонке, а в индустрии авиаперелетов Стандартный DSL используется для описания полетом.

Ваш бизнес и ваш проект также имеют дело с особыми наборами концепций, которые можно описать с помощью DSL. Например, можно определить DSL для одного из следующих приложений:

Планирование путей перехода на веб-сайте.

Схемы подключения для электронных компонентов.

Сети конвейера конвейерных и багажа, обрабатывающие оборудование для аэропорта.

Пользователи вашего DSL создают модели. Модели являются экземплярами DSL. Например, они описывают конкретный веб-сайт или подключение определенного устройства или систему обработки багажа в определенном аэропорту.

пользователи могут просматривать модель в виде диаграммы или формы Windows. Модели также можно просматривать в виде XML, то есть как они хранятся. При определении DSL вы определяете, как экземпляры каждого доменного класса и отношения отображаются на экране пользователя. Обычный DSL отображается как коллекция значков или прямоугольников, Соединенных стрелками.

На следующем рисунке показана небольшая модель в схематическое DSL:

Что такое dsl в программировании. Смотреть фото Что такое dsl в программировании. Смотреть картинку Что такое dsl в программировании. Картинка про Что такое dsl в программировании. Фото Что такое dsl в программировании

Возможности DSL

Например, можно написать шаблоны, которые принимают план аэропорта и создают часть программного обеспечения для обработки багажа, а также некоторые пользовательские документы, описывающие этот план.

После определения DSL его можно распространить другим пользователям, которые могут установить его на своих компьютерах. Пользователи DSL могут создавать и изменять модели в Visual Studio.

Можно также определить команды меню и другие средства, помогающие пользователям редактировать DSL, ограничения проверки, чтобы обеспечить правильное использование DSL, а также шаблоны элементов, помогающие пользователям создавать новые экземпляры. в качестве интегрированного пакета можно включить один или несколько языков dsl с помощью средств и других расширений Visual Studio.

Как правило, доменный язык создается, когда группа разработчиков должна написать подобный код для нескольких продуктов. Например, компания, специализирующаяся на системах обработки багажа, может определить DSL Track, с помощью которого можно создать некоторый код для каждой установки. Преимущество DSL заключается в том, что они могут быть понятны своим клиентам, что код, созданный из него, надежен и что система может быть быстро обновлена при изменении требований клиентов.

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

Разработка Domain-Specific

Разработка для конкретного домена — это процесс определения частей приложений, которые можно моделировать с помощью доменного языка, а затем создание языка и его развертывание разработчикам приложений. Разработчики используют доменный язык для создания моделей, характерных для их приложений, используют модели для создания исходного кода, а затем используют исходный код для разработки приложений.

Аспекты разработки графических Domain-Specific

Графический язык, относящийся к домену, должен включать следующие функции:

Модель предметной области

Интеграция с Visual Studio

Notation

Доменный язык должен иметь достаточно небольшой набор элементов, который можно легко определить и расширить, чтобы представить специфические для домена конструкции. Нотация состоит из фигур, представляющих элементы, и соединителей, которые представляют связи между элементами на графической поверхности диаграммы. В Инструменты доменного языка формы можно расширять и уточнять, чтобы представить элементы доменного языка.

Модель предметной области

Доменный язык должен объединять набор элементов и связи между ними с согласованной грамматикой. Он также должен определять, являются ли сочетания элементов и связей допустимыми. Например, языки программирования обычно предотвращают циклическое наследование, при котором один класс является производным от второго класса, а второй класс является производным от первого класса. Ограничения также можно использовать для выражения бизнес-логики, например, один человек не может быть зависимым от самого себя. Инструменты доменного языка использует ограничения для выражения типов ограничений, требуемых для большинства языков, зависящих от домена.

Создание артефактов

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

Сериализация

Доменный язык должен быть сохранен в определенной форме, которая может быть изменена, сохранена, закрыта и перезагружена. Инструменты доменного языка использует формат XML, который позволяет определить и настроить сериализацию или сохранение доменного языка.

Интеграция с Visual Studio

поскольку Инструменты доменного языка размещается в Visual Studio, он расширяет множество Visual Studioных окон и элементов управления. Он также позволяет настраивать поведение команд меню, элементов панели элементов и других элементов пользовательского интерфейса.

Вы также можете создать адаптер шины модели для конкретного доменного языка. Этот адаптер позволяет ссылаться на модель и элементы в модели и позволяет писать код, который может получать доступ к экземпляру DSL и обновлять его. используя мощный механизм шины модели, можно писать расширения Visual Studio, работающие с несколькими моделями. Кроме того, можно создавать автономные приложения, работающие с моделями. дополнительные сведения см. в разделе интеграция моделей с помощью Visual Studio Modelbus.

Преимущества разработки Domain-Specific

Доменный язык может предоставить следующие преимущества:

Содержит конструкции, точно соответствующие области проблемы.

В отличие от языков общего назначения, доменный язык состоит из элементов и связей, которые непосредственно представляют логику пространства проблем. Например, приложение страхового полиса должно включать элементы для политик и утверждений. Доменный язык упрощает проектирование приложения и поиск и исправление ошибок логики.

Позволяет неразработчикам и людям, не знающим домен, понять общую структуру.

С помощью графического доменного языка можно создать визуальное представление домена, чтобы разработчики, не являющиеся разработчиками, могли легко понять структуру приложения.

Упрощает создание прототипа окончательного приложения.

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

Процесс разработки Domain-Specific

Большинство команд разработки программного обеспечения, использующих доменные языки, выполняют следующие шаги для создания и использования их моделей:

Команда различает переменные части домена из частей, которые никогда не изменяются.

Разработчики пишут код для фиксированных частей и оставляют точки расширения для переменных частей.

Ведущий разработчик программного обеспечения или архитектор создает доменный язык, включающий шаблоны разработки фиксированных частей домена и точки расширения для переменных частей.

Ведущий разработчик программного обеспечения или архитектор развертывает доменный язык для разработчиков различных приложений, создаваемых группой.

Каждый разработчик создает модель, которая применяется к конкретному приложению.

Источник

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *