Что такое java dsl

Обновлено: 24.11.2024

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

DSL очень распространены в вычислительной технике: примеры включают CSS, регулярные выражения, make, ant, SQL, многие элементы Rails, ожидания в JMock, язык точек graphviz, файл конфигурации Strut.

Внешние DSL имеют собственный синтаксис, и для их обработки необходимо написать полный анализатор. В сообществе Unix существует прочная традиция делать это. Вариантом этого является кодирование DSL в представлении структуры данных, таком как XML или YAML.

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

DSL можно реализовать либо путем интерпретации, либо путем генерации кода. Интерпретация (чтение сценария DSL и его выполнение во время выполнения) обычно проще всего, но иногда необходима генерация кода. Обычно сгенерированный код представляет собой язык высокого уровня, такой как Java или C.

Языки домена

В последние годы 00-х меня глубоко заинтересовало возрождение DSL, подпитываемое усилиями сообщества Ruby, желанием создавать плавные интерфейсы и заманчивой, хотя и туманной, перспективой Language Workbench. Я видел довольно много проектов, использующих идеи из DSL, но большинство людей не имели четкого представления о своих возможностях в их создании и использовании. Поэтому я решил заняться этим, написав книгу шаблонов для использования для простых внутренних и внешних текстовых DSL. Несмотря на то, что за прошедшие годы этот интерес поутих, я все же считаю, что эта книга хорошо описывает эти приемы. В частности, он проливает свет на использование адаптивных моделей для использования альтернативных вычислительных моделей, таких как механизмы правил, таблицы решений и конечные автоматы.

Мартин Фаулер

Вопросы и ответы по DSL

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

Мартин Фаулер

Граница DSL

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

Мартин Фаулер

Language Workbench: лучшее приложение для доменных языков?

Большинство новых идей в разработке программного обеспечения на самом деле являются новыми вариациями старых идей. В этой статье описывается один из них, растущая идея класса инструментов, которые я называю Language Workbenchs. Примерами таких инструментов являются Intentional Software, система метапрограммирования JetBrains и Software Factory от Microsoft. Эти инструменты используют старый стиль разработки, который я называю языково-ориентированным программированием, и используют инструменты IDE, чтобы сделать языково-ориентированное программирование жизнеспособным подходом. Хотя я не настолько предсказатель, чтобы сказать, добьются ли они успеха в своих амбициях, я все же думаю, что эти инструменты — одни из самых интересных вещей на горизонте разработки программного обеспечения. Достаточно интересно, чтобы написать это эссе, чтобы попытаться объяснить, хотя бы в общих чертах, как они работают и основные проблемы, связанные с их будущей полезностью.

Мартин Фаулер

Рефакторинг в адаптивную модель

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

Мартин Фаулер

Удобный для бизнеса DSL

Позволят ли DSL деловым людям писать правила для программного обеспечения без привлечения программистов?

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

Мартин Фаулер

Синтаксический шум

Распространенная фраза, которая часто упоминается, когда речь идет о DomainSpecificLanguages ​​(да и вообще о любом компьютерном языке), — это шумный синтаксис. Люди могут сказать, что Ruby менее шумный, чем Java, или что внешние DSL менее шумные, чем внутренние DSL. Под синтаксическим шумом люди подразумевают посторонние символы, которые не являются частью того, что нам действительно нужно сказать, но существуют для удовлетворения языкового определения. Шумовые символы плохи, потому что они затемняют смысл нашей программы, заставляя нас ломать голову над тем, что она делает.

Мартин Фаулер

Каталог DSL

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

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

Чем предметно-ориентированные языки отличаются от «настоящих» языков программирования?

Язык предметной области обычно менее сложен, чем язык общего назначения, такой как Java, C или Ruby. Как правило, DSL разрабатываются в тесном сотрудничестве с экспертами в области, для которой предназначена DSL. Во многих случаях DSL предназначены для использования не программистами, а непрограммистами, которые свободно разбираются в предметной области, к которой относятся DSL-адреса.

Каковы преимущества предметно-ориентированных языков? Почему меня это должно волновать?

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

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

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

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

Как соотносятся языки домена и обычный код?

Существует два принципиально разных способа интеграции традиционного кода и кода DSL. Первый хранит код DSL и обычный код в отдельных файлах. Затем код DSL преобразуется в код языка программирования автоматическим генератором кода, или, альтернативно, программа загружает код, специфичный для предметной области, и выполняет его. Этот первый подход с раздельным языком общего назначения (GPL) и кодом DSL называется внешними DSL. Думайте о SQL как о примере внешнего DSL.

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

Стоит отметить, что некоторые GPL больше подходят для расширения, чем другие.

Оба подхода могут иметь смысл в зависимости от обстоятельств, и MPS поддерживает оба.

Структура и синтаксис DSL определялись написанием кода на языке, в который должен был быть встроен код DSL. Обычно IDE не знали о DSL и, следовательно, не предоставляли поддержки (завершение кода, индивидуальная проверка ошибок и т. д.). Однако с MPS вы используете структуру MPS с ее специализированными DSL для разработки языка, чтобы определить языковые расширения. Таким образом, IDE знает о них, поэтому система может обеспечить полную поддержку IDE для встроенных языков предметной области.

Что такое языково-ориентированное программирование?

Термин "языково-ориентированное программирование" был введен Сергеем Дмитриевым, генеральным директором JetBrains и "отцом" MPS, в его статье 2004 года "Языково-ориентированное программирование: новая парадигма программирования". Другие люди придумали похожие подходы, обычно под другими названиями; основным примером является Чарльз Симони и его подход к преднамеренному программированию, а Мартин Фаулер описал этот подход в своей статье 2005 года Language Workbenchs: The Killer-App for Domain Specific Languages?.

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

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

В следующем видео показан пример создания интерактивного голосового ответа (IVR) с помощью MPS. Этот DSL предназначен для людей, не являющихся техническими специалистами, поэтому пользовательский интерфейс адаптирован для них.

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

Когда я запускал RuleBook, я использовал простой метод, объединяющий предметно-ориентированный язык (DSL), который также использовал новые функции Lambda в Java 8. Однако по мере того, как росло мое желание усовершенствовать [внутренний] DSL и улучшить взаимодействие с языком, я обнаружил, что просто иметь пару объектов, объединяющих свои собственные методы в цепочку, недостаточно.

Порядок слов имеет значение

Если целью DSL является создание удобочитаемого языка, похожего на английский, то даже внутренний Java DSL, который строит предметно-ориентированный язык из языка общего назначения (GP), должен стремиться следовать некоторым правилам преемственности. Возьмем, к примеру, языковой формат Given/When/Then (GWT), связанный с Business Driven Development. Если Дано Когда Тогда имеет смысл. Но «Тогда при условии, когда» не имеет особого смысла, особенно если оба утверждения эквивалентны в соответствии с DSL.

Теперь давайте добавим в систему еще несколько разводных ключей. В языках GWT довольно часто допускается использование нескольких операторов «тогда». Кроме того, давайте предположим, что есть необязательное ключевое слово «using», которое можно использовать для ограничения состояния, доступного для последующего оператора «тогда» (как в RuleBook). Теперь, даже если язык не применяет ограничений порядка, становится ясно, что порядок используемых ключевых слов имеет значение. А поскольку порядок важен для правильного преобразования языка в желаемую функциональность, язык должен применять необходимые ограничения в этом порядке для защиты от нежелательного поведения.

Исполнение приказа

Возьмем простой DSL-интерфейс формата GWT, в котором используется цепочка методов через построитель.

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

Однако первый фрагмент кода не имеет большого смысла. Например, если using() фильтрует данные для действия then(), к какому действию оно применяется? Тогда вот как это читается. «Затем происходит какое-то действие при заданном состоянии, затем происходит какое-то другое действие с использованием некоторого подмножества состояния» не имеет точного логического лингвистического потока. Было бы разумнее, если бы язык применял некоторые правила, подобные следующим:

  1. Первым методом может быть только метод "данный", "когда", "использующий" или "тогда".
  2. Только "данный", "когда", "использующий" или "тогда" метод может следовать за "данным" методом.
  3. За методом "когда" может следовать только метод "тогда" или "использование".
  4. Только метод "использование" или "затем" может следовать за методом "использование".
  5. За методом "тогда" может следовать только метод "использование", "затем" или "сборка".

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

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

Соответствие тоже имеет значение

Что делает что-то интуитивно понятным? Является ли это результатом природного инстинкта или обусловленности? Возьмем, к примеру, вождение автомобиля. Большинство из нас, читающих это, вероятно, умеют водить машину. Но уж точно никто из нас не родился умеющим водить машину. Однако прямо сейчас, если бы кто-то дал нам ключи от машины, мы бы, скорее всего, знали, как пользоваться этими ключами, чтобы водить машину.И это справедливо практически для любой машины. Это интуитивно понятно, потому что известно. И точно так же, если вы умеете водить одну машину, вы знаете, как водить почти все остальные машины. Я полагаю, что если бы существовала машина, к которой не применялись бы обычные правила вождения, то мало кто бы ее вел. Это потому, что люди тяготеют к тому, что известно. А то, что известно или может быть легко познано посредством обусловленности, мы называем интуитивным.

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

Использование инструментов в наборе инструментов Java DSL

Связывание методов

Последовательность методов

Вложенные вызовы методов

Лямбда-выражения

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

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

Обзор

Создание интуитивно понятного [внутреннего] предметно-ориентированного языка (DSL) требует большего, чем просто соблюдение общепринятых методов разработки, таких как абстрагирование языка выражений от API. Это требует вдумчивого понимания того, как следует использовать язык и как его не следует использовать. Внимание к таким вещам, как порядок слов и последовательность в языке, может иметь большое значение для того, чтобы сделать язык удобным и легким для понимания.

Из книги "Современная Java в действии" Рауля-Габриэля Урма, Марио Фуско и Алана Майкрофта

В этой статье вы узнаете о DSL с Lambdas, плюсах и минусах DSL, а также о различных решениях DSL на JVM.

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

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

Код пишется один раз, но читается много раз. Удобочитаемость важна для удобства сопровождения, а код, который легко читать, лучше, чем код, который легко написать. Вы всегда должны программировать так, как будто человек, который поддерживает ваш код, — серийный убийца-маньяк, который знает, где вы живете.

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

Плюсы и минусы DSL

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

Краткость – API, который удобно инкапсулирует бизнес-логику, позволяет избежать повторений и приводит к более компактному коду.

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

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

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

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

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

С другой стороны, внедрение DSL в кодовую базу также может иметь несколько недостатков. Давайте также обсудим их:

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

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

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

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

Ограничения языка хостинга. Некоторые языки программирования общего назначения известны своим подробным и жестким синтаксисом, и Java входит в их число. Эти языки не подходят для размещения DSL. DSL, разработанные на их основе, ограничены этим громоздким синтаксисом и часто трудны для чтения. Введение лямбда-выражений в Java 8 предложило новый мощный инструмент для решения этой проблемы.

Если вы работаете в такой богатой среде, как та, которую предоставляет JVM, разработка DSL на основе Java 8 — не единственное существующее решение для создания более удобочитаемой абстракции поверх базовой модели предметной области. Прежде чем исследовать, какие шаблоны и стратегии мы могли бы использовать для разработки удобочитаемого и простого в использовании DSL на Java 8, давайте быстро рассмотрим другие альтернативы, уточнив, при каких обстоятельствах они могут быть эффективным решением.

Различные решения DSL доступны на JVM

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

В оставшейся части этой статьи мы сосредоточим наше внимание на том, как создать внутренний DSL на основе Java 8. Важно упомянуть доступные альтернативы, чтобы принять обоснованное решение о правильной технологии для использования с учетом характеристик вашего проекта и, что, возможно, более важно, навыков вашей команды разработчиков. JVM дает вам третью возможность, которая находится где-то между внутренним и внешним DSL: использование другого языка программирования общего назначения, работающего на JVM, но более гибкого и выразительного, чем Java, такого как Scala или Groovy. Мы будем называть эту третью альтернативу полиглот DSL. Пришло время проанализировать эти три возможности в соответствии с возрастающими уровнями мощности, гибкости и сложности.

Поскольку это статья о Java, когда мы говорим о внутреннем DSL, мы явно имеем в виду DSL на основе Java. Исторически Java не считался дружественным к DSL языком, потому что его громоздкий и негибкий синтаксис затрудняет чтение краткого, выразительного DSL.Эта проблема была в значительной степени смягчена введением лямбда-выражений — фактически, их широкое использование приводит к DSL с более приемлемым соотношением сигнал/шум. Чтобы продемонстрировать это, давайте попробуем напечатать список строк с синтаксисом Java 7, но с использованием API Java 8:

В этом фрагменте мы показали часть, которая несет сигнал кода. Все остальное — синтаксический шум, не несущий никакого дополнительного смысла и которого больше нет в Java 8. Анонимный внутренний класс можно заменить лямбда-выражением:

или, что еще лучше, со ссылкой на метод:

Тем не менее, если вы можете использовать выразительность лямбда-выражений Java 8, и вы можете жить с выдающимся шумом и многословием, вызванными синтаксисом Java, у вас есть много преимуществ при разработке вашего DSL на простой Java:

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

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

Пользователям вашего DSL будут доступны все функции, обычно предоставляемые вашей любимой IDE Java, такие как средства автозаполнения и рефакторинга. Современные IDE улучшают свою поддержку других популярных языков JVM, но по-прежнему несопоставимы с тем, что они предлагают разработчикам Java. Хуже того, если вы решите создать свой собственный язык, у вас не будет поддержки IDE. Вы можете запланировать интеграцию между вашей IDE и DSL, но это обычно выходит за рамки бюджета и возможностей большей части команд разработчиков.

Если вам нужно внедрить более одного DSL для покрытия разных частей вашего домена или нескольких доменов, нет проблем с компоновкой и обеспечением взаимодействия этих DSL, если они написаны на простом Java. Это верно, даже если вы решите использовать другой язык JVM, но очевидно, что будет не так просто интегрировать различные внешние DSL, сделанные на заказ.

В настоящее время на JVM работает, вероятно, более 100 различных языков. Некоторые из них, такие как Scala и Groovy, сейчас довольно популярны, и найти разработчиков, владеющих этими языками, несложно. Другие, такие как JRuby и Jython, представляют собой переносы других известных языков на JVM. Наконец, есть и другие развивающиеся языки, такие как Kotlin и Ceylon, которые набирают популярность, в основном потому, что они утверждают, что обладают функциями, сравнимыми со Scala, но с меньшей внутренней сложностью и более легкой кривой обучения. Большинство этих языков моложе Java и были разработаны с менее ограниченным и многословным синтаксисом. Эта характеристика оказывает положительное влияние при реализации DSL, что приводит к созданию языка с более низким церемониальным шумом.

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

Обратите внимание, что в Scala вызов этой функции с большими значениями i не приведет к переполнению стека, как это произошло бы в Java, поскольку в Scala есть оптимизация хвостового вызова и рекурсивный вызов функция times не будет добавлена ​​в стек. Вы можете использовать эту функцию для выполнения другой функции, в данном случае той, которая печатает «Hello World» три раза, как показано ниже.

Каррирование функции времени или разделение ее аргументов на две группы:

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

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

Таким образом, пользователь нашего небольшого DSL может трижды выполнить функцию, выводящую «Hello World» следующим образом:

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

Получение аналогичного результата на Java невозможно, а преимущества использования более удобного для DSL языка очевидны. Этот выбор имеет некоторые явные неудобства. Сначала вы должны выучить новый язык программирования или иметь кого-то в вашей команде, уже умеющего с ним работать. Учтите, что разработка DSL на этих языках обычно требует использования некоторых дополнительных функций, а поверхностного знания нового языка обычно недостаточно.Во-вторых, необходимо усложнить процесс сборки, интегрируя различные компиляторы для сборки исходного кода, написанного на двух или более языках. Наконец, несмотря на тот факт, что большая часть языков, работающих на JVM, заявляет, что они на 100% совместимы с Java, часто требуются неуклюжие приемы и компромиссы, чтобы заставить их взаимодействовать с Java. Это взаимодействие иногда приводит к потере производительности: например, коллекции Scala и Java несовместимы, и когда коллекция Scala должна быть передана в функцию Java или наоборот, исходная коллекция должна быть преобразована в коллекцию, принадлежащую собственному API. целевого языка.

Третий вариант — реализация внешнего DSL. В этом случае вам нужно с нуля разработать новый язык с его собственным синтаксисом и семантикой, а затем настроить отдельную инфраструктуру для синтаксического анализа нового языка, анализа выходных данных синтаксического анализатора и генерации исполняющего кода. ваш внешний DSL. Если это звучит как много работы, то это потому, что так оно и есть, а навыки, необходимые для выполнения этих задач, не являются ни обычными, ни легкими для приобретения. Инструмент, наиболее часто используемый в Java для создания парсера текстового файла, — это ANTLR. Кроме того, Scala с помощью своей библиотеки комбинаторов синтаксических анализаторов предоставляет мощный инструмент синтаксического анализа.

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

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

Это все для этой статьи.

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

Укомплектование публикаций

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

Читайте также: