Языково-ориентированное программирование (ЯОП) (), также Расходящаяся разработка (), также метаязыковая абстракция, также Разработка, опирающаяся на предметно-специфичный язык () — парадигма программирования, заключающаяся в разбиении процесса разработки программного обеспечения на стадии разработки предметно-ориентированных языков (DSL) и описания собственно решения задачи с их использованием. Стадии могут вестись последовательно или параллельно, однократно или рекурсивно; DSL могут быть реализованы зависимо или независимо от базового языка и иметь одну или множество реализаций.
Место и роль в информатике
ЯОП предназначено для разделения сложностей: машино-ориентированная часть кода (низкоуровневая функциональность) и человеко-ориентированная (собственно решение прикладной задачи) разрабатываются независимо друг от друга, что исключает экспоненциальный рост результирующей сложности разработки всего проекта и решает проблему сложности как фундаментальную проблему программирования, описанную Фредериком Бруксом в знаменитом эссе «Серебряной пули нет», из-за которой оказывается невозможно простым совершенствованием рабочего инструментария повысить производительность труда программистов даже на порядок. Из этого же прямо следует большинство остальных преимуществ.
О достоинствах сужения специализации языков говорили ещё в середине 1980-х, а о достоинствах повышения уровня языков — намного раньше, но DSL-ориентированная разработка сформировалась как самостоятельная методология лишь к середине 1990-х.
Использование DSL вместо языков общего назначения существенно повышает уровень абстрактности кода, что позволяет вести разработку быстро и эффективно и создавать программы, которые легки в понимании и сопровождении; а также делает возможным или существенно упрощает решение многих задач, связанных с манипулированием программами (порождение программ, исследование определённого свойства программ — корректности, эффективности и др.). С другой стороны, разработка нового языка и эффективная его реализация является нетривиальной проблемой теоретической и прикладной информатики.
Среди прочих подходов к проектированию программ ЯОП выделяется гораздо более агрессивной направленностью на приближение компьютера к человеку. Среди исследователей ЯОП бытует мнение, что в наукоёмких задачах хорошо спроектированный и реализованный DSL делает общение человека с компьютером куда более удобным и продуктивным, чем графический интерфейс пользователя. В качестве примеров чаще всего приводятся следующие популярные предметно-специфичные языки: AutoLisp для компьютерного моделирования (САПР) для подготовки (компьютерной вёрстки) текстовых документов Perl для манипулирования текстами SQL для СУБД Mathematica и Maple для символьных вычислений и др.
Преимущества ЯОП проявляются даже в тех случаях, когда DSL разрабатывается не для массового использования, а для решения единственной задачи. Например, при разработке системы автоматического эквивалентного преобразования программ переход от «плоского» программирования на Лиспе к рекурсивному ЯОП (на Лиспе был реализован язык WSL, на нём — язык MetaWSL, а уже на нём — целевая функциональность) не только позволил сократить общий объём кода со 100 до 16 тысяч строк, но одновременно повысил все основные качественные характеристики кода и даже сделал возможным решение задач, которые иначе решить не удавалось.
Упрощённо сравнить рост трудозатрат при использовании традиционного и языково-ориентированного подходов позволяет график. Как видно, ЯОП оказывается целесообразно лишь начиная с некоторого порога объёма и сложности функциональности целевой системы.
Большинство исследователей ЯОП опирается на функциональные языки и метаязыки, что обусловливает высокий порог вхождения для разработчиков. Мартин Уорд отмечает возможность реализации DSL на традиционных языках, но лишь после его окончательной разработки.
В мейнстриме часто применяется встраивания интерпретатора в язык общего назначения (см. Подход), хотя это делается не только без апелляции к принципам ЯОП, но и зачастую без осознания факта её применения как таковой. Наиболее часто встраиваются: язык регулярных выражений (интерпретатор PCRE), Lua, SQL, XML. Также был разработан инструментарий визуального программирования для использования в мейнстриме некоторых идей ЯОП.
Многие исследователи видят цель ЯОП в том, чтобы полностью размыть границы между математической моделью и её реализацией на ЭВМ и сделать возможной разработку программного обеспечения специалистами предметных областей, не имеющими специфичных знаний в программировании: -- проверка вхождения точки в регион:inRegion :: Point -> Region -> Boolp ‘inRegion‘ r = r p…Благодаря точному запечатлению семантики предметной области даже не-программисты оказываются способны понять значительную часть кода. В эксперименте, проведённом по заказу Naval Surface Warfare Center, совершенно незнакомые с Хаскелом люди схватывали основные понятия на лету. Некоторые даже выразили неверие в то, что этот код был действительно исполнимым.(В самом деле, несмотря на присутствие в тексте этого последнего предложения, один из рецензентов первого черновика данной работы выразил недовольство тем, что «работа заявляется как рассуждения одновременно о синтаксисе и семантике, но её содержание в основном касается синтаксиса (как, например, определение inRegion), и не делается никаких различий между математикой и программированием». Но на самом деле, это определение inRegion целиком и полностью семантическое. Более того, эквациональные рассуждения … позволяют размыть грань между математикой и программированием: программы могут рассматриваться как спецификации. Это особое свойство, так как расширяет применение формальных методов.)
Подход В основе подхода лежит идея о том, что язык, специально разработанный под поставленную задачу, будет обеспечивать заведомо более высокие показатели качества кода, чем любой язык общего назначения, и что для решения сложных промышленных задач более эффективным будет изобрести более простой в понимании (человеко-ориентированный или точно инкапсулирующий предметные знания) язык, нежели преодолевать трудности использования имеющегося, даже укоренившегося в промышленности.
Большинство исследователей говорят о ЯОП как о переводе всей индустрии разработки ПО на использование текстовых языков 4-го и 5-го поколения, но некоторые ориентируются на использование визуальных языков.
Основные проблемы подхода состоят в нахождении способов быстро создать реализацию придуманного DSL, чтобы начать разрабатывать собственно решение задачи, и в обеспечении хорошей вычислительной производительности DSL.
Предметно-ориентированный язык, как и вообще любой язык программирования, определяется алфавитом, грамматикой, семантикой и психолингвистикой, однако, в зависимости от способа реализации DSL, роль и взаимосвязь этих уровней может размываться и/или наследоваться от языка его реализации.
Разные авторы делают акцент на разных способах разработки предметно-специфичных языков: реализация независимого компилятора (Ахо — Сети — Ульман, Кнут); встраивание интерпретатора в язык общего назначения (Маккарти, — Абельсон — Сассман, Уорд); использование макросредств языка (и нередко отождествление их с термином «метапрограммирование») (Маккарти, Леруа, Шалуа — Манури — ПаганоDeveloping Applications With Objective Caml, Таха); чистое встраивание () (, Хейнс, Хьюдак, Шиверс, Бертомью, Рэмси).
При использовании макросредств, в свою очередь, различают шаблонное метапрограммирование и многостадийную статическую интерпретацию.
Третий и четвёртый методы имеют фундаментальное преимущество перед первыми двумя — DSL не заменяет, а расширяет язык общего назначения, повторно используя весь инструментарий базового языка, начиная с парсера, благодаря чему: появляется возможность комбинировать в едином коде возможности базового языка, общих библиотек к нему, разработанного предметно-специфичного языка и даже нескольких других разработанных аналогичным образом предметно-специфичных языков, применяя устоявшиеся для базового языка идиомы, трюки, скрещивая методологии; устраняется необходимость реализовывать с нуля тривиальные вещи (такие как арифметика чисел) — достаточно адаптировать синтаксис; устраняется необходимость разработки полного комплекса инструментария разработки (оптимизирующего транслятора с информативными сообщениями об ошибках, REPL, отладчика, профилировщика и пр.). При рекурсивном встраивании DSL повторное использование кода достигает гигантских масштабов.
Многие авторы состредотачиваются на эффективном (без интерпретации) встраивании в язык определённых изначально отсутствующих в нём возможностей для адаптации к определённым задачам, что в дальнейшем может служить основой для чистого встраивания DSL. Значительное внимание уделяется использованию продолжений для разработки DSL с недетерминированной семантикой (, , , , и другие).
Приложения подхода и самоприменимость
Важным подвидом ЯОП является Пользовательское программирование, позволяющее самым разным людям, не имеющим никакого представления об информатике, эффективно решать множество прикладных задач. Роль этого приложения ЯОП столь велика, что едва ли не самым распространённым в мире языком программирования на практике оказываются средства вёрстки крупноформатных таблиц ().
В зависимости от трактовки термина «метапрограммирование» (МП) и способа реализации DSL, либо ЯОП является квинтэссенцией МП, либо МП служит одним из способов реализации ЯОП. Последний вариант наиболее применим в случае встраивания DSL в язык общего назначения посредством макро-подмножества последнего. При использовании средств визуальной разработки DSL эти определения оказываются синонимичными, так как само визуальное программирование представляет собой простейшую форму МП. Рассмотрение МП в качестве самоприменения ЯОП означает: для встраиваемых DSL — рекурсивное применение ЯОП, предлагаемое Уордом и Хьюдаком; для независимых DSL — раскрутку компилятора ().
Инструментарий Для разработки независимых трансляторов широко распространены генераторы лексеров и парсеров на основе определения грамматики целевого DSL посредством БНФ и регулярных выражений: Lex Yacc ANTLR Библиотека Parsec для языка Haskell и другие.
При компиляции независимого DSL целевой платформой редко выбирается машинный код или даже Ассемблер, более предпочтительным (как для снижения трудоёмкости реализации DSL, так и для повышения портируемости) является использование платформы более высокого уровня: языка общего назначения высокого уровня; языка общего назначения среднего уровня (Си, BitC, Forth) промежуточного языка или фреймфорка компиляторов (C--, MLRISC) низкоуровневой виртуальной машины (LLVM)
Для встраивания DSL в язык общего назначения используются следующие технологии: Метаязыки: Lisp, ML, Haskell, Nemerle, Forth, Tcl, Rebol Встраивание объектного языка посредством квазицитирования — параметрический парсер ОКамла Библиотека Boost.Spirit для языка C++ (за исключением регулярных грамматик и )
Чистое встраивание не предполагает каких-либо дополнительных инструментов, но накладывает довольно жёсткие ограничения на выбор базового языка.
При использовании многостадийной статической интерпретации целевая платформа совпадает с базовым языком.
В рамках традиционного программирования (на языках, наследованных от Алгола) использование некоторых идей ЯОП делает возможным инструментарий визуального программирования, разработанный в первой половине 2000-х годов: Intentional Software, Meta Programming System (JetBrains)
История, философия, терминология