Программирование в форме диалога. Часть II. Реализация диалога, предыстория
См. также начало: Часть I. Зачем это нужно.
Первая задача. Lisp
Первое, что необходимо для реализации диалогового программирования, это дать компьютеру возможность оперировать не фиксированным (как это сейчас происходит при программировании на большинстве языков программирования), а изменяемым набором понятий. Так же как математики могут вводить в математику новые понятия, описывать и доказывать их свойства, задавать их связь с другими понятиями. Они могут ввести понятие умножения, понятие матрицы и вектора, понятие множества, вводить свойства этих понятий, скажем перечислимые и континуальные множества, конечные и бесконечные и так далее.
Возможность вводить новые понятия в программировании существует уже давно. Изначально оно было реализовано в таких языках как Lisp и Forth. И немедленно программисты столкнулись с проблемой синтаксиса, или она же — проблема компромисса между полнотой и выразительностью. В любом месте программы на Lisp-е или Forth-е вы можете использовать любые определённые вами понятия. В Lisp-е они синтаксически выделяются скобками, что ставит предел выразительности языка. Если вы не используете скобки, разделяя понятия определённым вами синтаксисом — то вы теряете универсальность, поскольку уже не можете использовать в этом месте любое новое понятие. В Forth-е дерево развёрнуто в стек (и может быть преобразовано в дерево на основе количества аргументов у слов Forth-а), но победив проблему скобок, мы получили проблему фиксированного порядка записи. Существует много более или менее успешных попыток сделать синтаксис более гибким, не потеряв общности (возможности в любом месте текста использовать любое понятие). Например, в XL текст однозначно преобразуется в дерево через заданные приоритеты и ассоциативность задаваемых пользователем операторов. Это практически полностью решает проблему выразительности и общности для выражений, но для деклараций выглядит намного менее естественным. Есть и другие языки, такие как Dylan, Nemerle и прочие, в которых тем или иным образом решается проблема выразительности и общности синтаксиса, возникающая из-за возможности определять новые понятия в языке.
Такие языки (со встроенной поддержкой метапрограммирования) позволяют очень легко определять новые понятия, в терминах которых будет решаться поставленная задача. Но эта лёгкость является источником одного серьёзного ограничения. А именно — новые понятия определяются в них через способ их трансляции в уже существующие понятия, до тех пор, пока все новые понятия не будут выражены в предопределённом базовом наборе, фактически задающем модель исполнения. То есть, лёгкость задания новых понятий в конечном итоге ограничивает среду исполнения программы, которая может быть очень далека от оптимальной для решаемой задачи. Если же задавать новые понятия с последующей их трансляцией в оптимальную среду исполнения, то фактически это требует создания полноценного компилятора, что зачастую оказывается более сложной задачей, чем написание самой программы, а возможный синтаксис будет намного хуже (менее выразительный и привычный), по сравнению с языком программирования специализированным под эту среду исполнения.
Другая принципиальная проблема с текстовым синтаксисом, это то, что вводимые понятия и связи, как правило, многомерны. И их передача в дискурсивном (последовательном, линейном) виде либо в принципе невозможна, либо крайне неудобна для восприятия. Для примера можно привести ту же MVC модель, используемую для дизайна и реализации пользовательского интерфейса.
Вторая задача. MPS
Поэтому, вторая задача, которую необходимо решить для реализации диалогового способа программирования — это разделение внутреннего и внешнего представления программы, или фактически, это отказ от текстового формата программы.
Программа в этом случае будет храниться и обрабатываться в некоем внутреннем представлении компьютера (как правило, это дерево или направленный ацикличный граф). А отображаться и редактироваться она будет совсем в другом виде, специально созданном для удобства восприятия кода человеком и удобства редактирования.
Подобные системы сейчас находятся в стадии разработки, это такие технологии как IP (Intentional Programming реализуемая в Intentional Software, основателем которой является Чарльз Симони, руководившего в Microsoft созданием Word-а, Excel-я и MS Office в целом), MPS (Meta-programming system реализуемая в JetBrains, создавшей лучшую на сегодняшний день IDE для Java — IntelliJ IDEA, и ReSharper плагин для MS Visual Studio).
Про реализацию и внешний вид IP почти ничего не известно, поскольку у них нет ни публичного релиза, ни подробного описания технологии. Известность же IP получил благодаря регулярных выступлениям и статьям Чарльза Симони, и видео-демонстрации его возможностей, в далёкие времена, когда проект разрабатывался ещё в Microsoft.
Реализация MPS от JetBrains доступна с сайта www.jetbrains.com/mps и находится в состоянии бета-версии. Вскоре они обещают сделать релиз своей среды разработки. Большая часть кода этой среды открыта, кроме ядра системы. Что, в общем-то, делает достаточно сложным её использование, так как почти невозможно расширить или изменить её функциональность, или исправить критические ошибки самостоятельно, до того, как это сделают в JetBrains и выпустят следующую сборку.
Кроме решения проблем с синтаксисом и ограничением программы средой исполнения языка (присущей Lisp-у, Forth-у и другим), важным преимуществом MPS (и, по всей видимости, IP) является тот факт, что созданные и описанные в рамках этой среды языки — сразу, изначально, интегрированы в среду разработки, в IDE. Что позволяет (по крайней мере теоретически) использовать все те преимущества, которые предоставляет IDE, вроде авто-дополнения текста при наборе, фоновой компиляции и проверки правильности программы, встроенного отладчика и многое другое.
Малая распространённость DSL вызвана, в частности, тем фактом, что хотя хороший специализированный язык позволяет в несколько раз увеличить производительность труда программиста (поскольку он программирует в терминах максимально удобных для решения данного типа задач), но он автоматически лишается поддержки IDE. Текстовый редактор — вот всё, что у него остаётся, если он начинает использовать DSL. В то же время современная IDE сама по себе в несколько раз увеличивает производительность труда программистов, и в результате, выигрыш от перехода на специализированный язык оказывается не таким уж и большим, а ведь требуется ещё и реализовать компилятор для этого DSL. В этом плане MPS (потенциально) является значительным шагом вперёд, по сравнению с традиционными технологиями использования DSL-ей. Основная проблема при актуализации этой потенциальности — освоение как идеологии, так и чисто практических приёмов и навыков работы в MPS. Что достаточно сложно сейчас, при том небольшом количестве документации, отсутствии учебников и просто знакомых которые могли бы помочь советом.
MPS обладает сейчас несколькими важными (с точки зрения реализации диалогового программирования) ограничениями. Первое — это наличие только одного «синтаксиса» для отображения и редактирования для каждого понятия («концепции» в терминах MPS). Следовательно, невозможно задать более или менее детальное отображение кода, ни многомерное отображения кода. Точнее, многомерность имеется в ограниченном виде, скажем, для описания разных аспектов одной концепции используются различные языки — один язык описывает атрибуты концепции, другой описывает способ отображения и редактирования, третий описывает дополнительные проверочные условия целостности концепции, четвёртый описывает правила вывода «типов» для этой концепции, пятый описывает трансляцию этой концепции в исходный код программы (увы, в текстовый код, а не в другие концепции).
Ещё одним важным недостатком является неудобство редактирования в MPS. Дело в том, что MPS и подобные концепции используют структурный редактор, и редактируют дерево программы напрямую. У подобного способа программирования есть одно преимущество — программа «синтаксически» всегда правильная. Это не вызывает особых проблем при редактировании деклараций, но становится серьезным недостатком при редактировании выражений, где удобство редактирования как раз и требует использования пусть временно, но неверного «синтаксически» дерева. Например, вы хотите изменить выражение a+1 на 2*a+1. Редактируя дерево программист должен удалить a, получив ?+1, вставить операцию умножения, получив ?*?+1, и вставить 2 и a, получив 2*a+1. Даже для такого небольшого выражения это не так просто и удобно, как при редактировании текста, а для более сложных выражений редактирование их как дерева можно вообще стать кошмаром. Конечно, в MPS есть средства позволяющие несколько упростить процесс редактирования выражений, но они не решают проблемы в целом.
Проблема с редактированием и разнообразным отображением одного и того же кода проистекает из того факта, что в MPS код программы, его семантика, не полностью отделена от синтаксиса. Вплоть до того, что они имеют концепцию «выражения в скобках», то есть a+1 это не то же самое, что (a+1). А ведь скобки — это чисто синтаксическая конструкция, используемая для изменения приоритета выражения при разборке текста согласно приоритетам и ассоциативности операторов. Фактически, это тот водораздел, который не позволяет отнести эту среду разработки к диалоговому программированию, необходимому для качественного скачка — перехода от процесса написания программы программистом к процессу написания программы компьютером.
См. также продолжение: Часть III. Реализация диалога, будущее
3 коментарі
Підписатись на коментаріВідписатись від коментарів Коментарі можуть залишати тільки користувачі з підтвердженими акаунтами.