Журнал «Компьютерра» № 10 от 14 марта 2006 года - Компьютерра. Страница 33

прототипируйте, выпуская сборки как можно чаще (золотое правило экстремального программирования);

определяйте возможные направления будущих изменений проекта (это уже из области технологий «третьего глаза»).

Этот список можно продолжать бесконечно, однако и так понятно, что подобные рекомендации позволяют лишь снизить риски, обусловленные расхождением проекта и исходного кода. Корень же всех зол кроется в том, что высокоуровневые аспекты проекта выражаются и документируются в терминах естественного языка (каким является, например, русский или английский), тогда как код реализации пишется на каком-нибудь формальном языке (C++, Java, C#). И между двумя этими типами языков лежит целая пропасть.

Языки предметной области

Решение проблемы напрашивается само собой: может, сразу излагать бизнес-требования на формальном языке? Или хотя бы не бизнес-требования (это мы сильно замахнулись), а высокоуровневые абстракции предметной области, из которых и состоит проект системы?

Да вот только где бы найти подходящий язык! Очевидно, что универсальные языки программирования для этой цели непригодны: в описании функций системы никогда не встречаются термины наподобие «класс» или «виртуальный метод». Диаграммы UML тоже хороши только в качестве красивых иллюстраций к техническому проекту системы[Справедливости ради нужно отметить, что диаграммы классов и взаимодействия могут быть полезны и на этапе реализации, но они опять-таки не содержат «правильных» абстракций]. Еще несколько лет назад казалось, что с этой ролью справится XML, однако сейчас понятно, что подобные проблемы ему не по зубам (более подробно по этому поводу см. врезку «XML и XSLT»).

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

Идея языков предметной области стара как мир. Макросы, языки командных оболочек (shell-скрипты Unix, например), проблемно-ориентированные языки приложений (такие как встроенный язык известной в России системы «1С»), языки пользовательских интерфейсов (например, XUL, широко известный в сообществе Mozilla), даже «великий и могучий» SQL для работы с базами данных, – все вышеперечисленные языки относятся к категории DSL, поскольку каждый из них проектировался для своей предметной области. Вместе с тем, за редкими исключениями, DSL не используются в качестве средства разработки программных приложений. А ведь как было бы здорово: разработать DSL и записать на нем код проекта…

«Создавать языки под каждый конкретный проект? Вздор!» – скажет вам любой специалист, хорошо знающий, как дорого обходится проектирование формальных языков с нуля. Действительно, при классической схеме разработки любого языка нужно написать много кода для распознавания исходных текстов на этом языке и их погружения в объектную модель, пригодную для дальнейших манипуляций. Кроме того, даже при условии, что эта работа проделана, возникает ряд вопросов.

Как отображать и редактировать программы на таком языке? Понятно, что в век высоких скоростей и мощных сред разработки ограничиться простым текстовым редактором a-la «Блокнот» уже не получится: представления о производительности труда разработчика ныне совсем не те, что в «далекие» 90-е годы XX века.

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

И главное: предположим, объектная модель получена. Что делать дальше? Ведь модель еще нужно связать с языком реализации системы, что является отдельной головной болью.

Языковые инструментарии

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

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

Из разработок в этой области хотелось бы упомянуть два перспективных проекта. Первым из них является Meta Programming System компании JetBrains. Система MPS ориентирована на совместное использование с фирменной IDE компании – средой разработки Java-приложений IntelliJ IDEA, которой автор уже восхищался в статье «Кодируй да радуйся» («КТ» #562). Другой проект, Software Factories, принадлежит перу софтверного гиганта Microsoft и выступает в качестве дополнения к недавно вышедшей Visual Studio 2005[Meta Programming System можно свободно скачать по адресу jetbrains.com/mps. Проект Software Factories в настоящий момент представляет собой набор инструментов DSL Tools, доступных для скачивания в составе SDK к Visual Studio 2005. Подробности можно узнать здесь: msdn.microsoft.com/vstudio/teamsystem/workshop/sf].

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

Что такое метапрограмма?

Грубо говоря, метапрограмма – это программа, формирующая в результате своей работы другую программу. Сложно? Тем не менее все это интуитивно понятно человеку, хоть раз занимавшемуся разработкой динамических серверных страниц. Действительно, для веб-дизайнера HTML является «программой для браузера», а для веб-разработчика тот же HTML выступает в роли данных, которые нужно сформировать в результате работы некоторого серверного кода.

Следует отметить важную особенность метапрограммирования: любая метапрограмма определяет не одну конкретную программу, а целый класс. Ниже приведен пример метапрограммы, которая определяет класс всех документов HTML, содержащих произвольное число параграфов. Текст метапрограммы (ASP.NET, С#) заключен между специальными операторами <%...%> и <%=...%>.

<HTML>

<BODY>

<%foreach(Paragraph p in Document) {%>

<%=p.Content%>

<%}%>

</BODY>

</HTML>

Проектирование DSL

Создание языка предметной области начинается с этапа моделирования данных – той информации, которая будет впоследствии записана в терминах DSL. Для простоты предположим, что нам необходимо разработать DSL, на котором можно описать структуру статьи для журнала «Компьютерра». Предметная область этой задачи включает в себя понятия статья, раздел и подраздел[Понятие «подраздел», конечно же, является избыточным, но кому нужны эти скучные профессиональные детали?]. Для статьи характерны название, автор и некоторая структура, включающая в себя разделы статьи.

Проиллюстрируем вышесказанное диаграммой (см. рис. 1), описывающей модель данных нашего DSL, который условно назовем «Структура статьи в КТ».

Журнал «Компьютерра» № 10 от 14 марта 2006 года - _630j21c1.jpg

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