|
|
|||||||||||||||||||||||||||||
|
Искусство метапрограммирования: Часть 3. Корпоративное метапрограммирование (исходники)"О, нет, - воскликнете вы, - только не еще одна 'теоретическая' дискуссия!" Но, тем не менее, прочтите статью до конца - эти рассуждения о теории метапрограммирования могут помочь вам отделить факты от вымыслов, которые порой встречаются в бурных маркетинговых заявлениях разработчиков различных инструментов метапрограммирования. В этой статье исследуются теоретические рамки возможностей метапрограммирования и архитектуры OMG's MDA. Эта архитектура отделяет бизнес-логику и логику приложений от лежащей в их основе технологической платформы. Узнайте о проблемах, которые можно решать с помощью MDA, и рассмотрите пример текстовой системы, использующей эту архитектуру. Теоретические рамки возможностей метапрограммированияЗная возможности, перспективы развития и неотъемлемые ограничения метапрограммирования, вы сможете подбирать нужные вам инструменты и задавать правильные вопросы их поставщикам. Графическое и текстовое метапрограммированиеВ первой и второй статьях этой серии мы рассматривали текстовые системы; тем не менее, многие существующие системы метапрограммирования являются графическими. Давайте начнем с рассмотрения программы, представленной как в текстовом, так и в графическом виде, и выясним, какие существуют сходства и отличия. В этом примере используются регулярные выражения. Регулярные выражения по существу представляют собой небольшой подъязык для обработки текста и используются для поиска и замены символьных строк. В листинге 1 содержится регулярное выражение на языке Perl, которое заменяет каждое вхождение подстроки Листинг 1. Регулярное выражение Perl для замены HTML-тегов
Язык, на котором написано регулярное выражение, не является языком Perl; это предметно-ориентированный язык, используемый Perl. Как бы то ни было, точный синтаксис регулярного выражения не так важен - регулярные выражения могут быть составлены многими различными способами. Как правило, когда вы общаетесь с компьютером на полнофункциональном или на узкоспециализированном языке программирования, вы используете определенный способ передачи символов этого языка компилятору или интерпретатору. Вы можете делать это, просто набирая код, но также вы могли бы выразить вышеупомянутое регулярное выражение следующим образом: Рисунок 1. Регулярное выражение Perl в виде диаграммы Это работает не только для предметно-ориентированных, но также и для общих языков программирования. Поскольку компиляторы оперируют символами, вы можете выражать эти символы в текстовой или графической форме. Текстовая форма используется по следующим причинам:
Что касается регулярных выражений, то вводить код с помощью графических средств оказывается, несомненно, сложнее. Каждая из двух форм представления регулярного выражения содержит одно и то же количество информации программирования . Таким образом, графическое описание концепции разработки не уменьшает объем программирования. Если вы использовали какую-либо графическую среду разработки приложений, ваш опыт может отличаться, благодаря преимуществу предметно-ориентированных языков, но не конкретных графических методов. Давайте рассмотрим пример программирования в Windows - описание ресурсов Win32 для построения диалоговых окон: Листинг 2. Пример описания ресурсов Win32
Код в листинге 2 требует, чтобы вы "передали" такое же количество информации, как и в случае использования графических инструментов для построения и позиционирования диалогового окна. Разница состоит в том, что выбирать экземпляры и располагать их на экране с помощью мыши намного проще, чем вручную набирать их имена и указывать координаты. Количество информации, которое вы передаете компьютеру, одинаково в обоих случаях. Так почему же выполнение действий требует меньшего объема программирования, чем ручное написание кода на языке C? Ограниченный, предметно-ориентированный подъязык требует меньшего объема программирования независимо от того, является ли инструмент текстовым или графическим. Из этого можно сделать следующие выводы:
Тем не менее, в графические представления вы можете добавлять больше информации, не относящейся к программированию. Например, вы можете:
Графические модели выводят программирование на новый уровень не потому, что программист передает меньше информации компьютеру, а потому, что больше информации может быть передано от программиста программисту более естественным путем. Метапрограммирование, программисты и эксперты в предметных областяхТеперь, когда мы установили, что предметно-ориентированный подъязык, уменьшающий объем программирования, не обязательно по своей природе должен являться графическим, можем ли мы достичь того, что программирование может полностью выполняться экспертом в определенной предметной области? Другими словами, можем ли мы отказаться от фактического выполнения работы программистами и просто предоставить экспертам в предметных областях инструменты метапрограммирования, с помощью которых они могут разрабатывать и писать свои приложения от начала и до конца? Чтобы ответить на этот вопрос, подумайте о том, что делают программисты в процессе работы над проектом, помимо написания кода. Пытаясь определить все возможные сценарии для определенной операции, эксперт в предметной области может что-то упустить. Например, давайте предположим, что вы создали приложение, которое автоматически выбирает город при указании почтового индекса. Заказчик этого приложения может не знать о том, что некоторые почтовые индексы соответствуют нескольким городам. Что происходит в этом случае? Получит ли пользователь сообщение? Будет ли автоматически выбран один город? Все такие неопределенные моменты программирования называются edge cases . По своему собственному опыту я могу сказать, что самая важная роль программиста/аналитика - это выявление всех таких моментов, о которых может не задумываться эксперт в своей области. Программисты стремятся обдумывать все стороны процесса более методично, и поэтому часто находятся в более выгодном положении, помогая экспертам выявить и понять все неявные моменты. Эксперты, пользуясь своими собственными методами, часто оставляют без рассмотрения многие аспекты работы системы, как бы они ни старались избегать этого. Разработка узкоспециализированных решений обычно является лишь частью бизнеса, а составление всеохватывающих технических требований не является повседневной задачей экспертов. Другой задачей программистов является полное понимание синтаксиса, семантики, возможностей и ограничений языков программирования, использующихся для написания приложений. Как было упомянуто выше, к графическим языкам предъявляется не меньше требований относительно точной семантики, чем к текстовым языкам, поскольку в обоих случаях все, в конечном счете, сводится к использованию символов. По этой причине даже в самых лучших, самых упрощенных графических средах крайне необходимо иметь полное понимание используемых инструментов и их семантики. Основываясь на этих двух наблюдениях, я уверен в том, что пока будут разрабатываться приложения, всегда будет существовать необходимость в услугах программистов. Со временем программирование может быть успешно внедрено в школьные и другие учебные программы так, что исчезнет необходимость преподавать его как отдельную дисциплину. Вместо упрощения программирования до той степени, которая позволит отказаться от услуг программистов, уровень государственного образования мог бы быть повышен так, что в таком упрощении не было бы необходимости! Важным итогом всех этих рассуждений является то, что роль эксперта в предметной области и роль программиста всегда будут отделены друг от друга, хотя иногда эти роли исполняет один и тот же человек. В конце концов, графические метапрограммы все еще являются программами , таким образом, они требуют от программиста их правильной реализации. Работа с несколькими уровнями абстракцииОдной из самых больших проблем в метапрограммировании является тот факт, что программисту почти всегда приходится работать с несколькими уровнями абстракции. Он должен не просто знать обо всех деталях программы, предметно-ориентированных языках и языках общего назначения, но также должен знать следующее:
Часто для выполнения поставленной задачи можно при написании кода использовать доступные инструменты метапрограммирования, но самая сложная часть наступает тогда, когда их нужно совместить. Например, если система метапрограммирования автоматически генерирует метод внутри класса, а впоследствии вам нужно будет несколько изменить этот метод, как вы реализуете нечто подобное? В некоторых случаях, а также при использовании некоторых инструментов изменение сгенерированного кода немедленно удаляет программу из области действия системы метапрограммирования. Метапрограмма перестает быть сколько-нибудь полезной, поскольку изменение должно быть сделано на более низком уровне. Существует несколько способов решения этой проблемы, но, в конечном счете, преодолеть ее полностью очень сложно или же вообще невозможно. Лучшими системами метапрограммирования являются те, которые позволяют вам работать с несколькими уровнями абстракции внутри самой системы. Например, во второй статье этой серии обсуждалось, как система макросов языка Scheme позволяет легко совмещать код макроса с остальным кодом. В идеале вам необходимо работать как на высоком, так и на низком уровнях внутри самой системы метапрограммирования и просто указывать ей, в каких местах требуется переходить на более низкий уровень. Теперь давайте рассмотрим архитектуру OMG's Model Driven Architecture и те проблемы, в решении которых она может помочь. Рассмотрение Model Driven Architecture на высоком уровне Теперь, когда вы лучше ознакомились с возможностями инструментов метапрограммирования, давайте обратимся к концепции корпоративного метапрограммирования и посмотрим, какие она имеет сходства и отличия от других методов метапрограммирования. Корпоративное метапрограммирование, в конечном счете, является обычным метапрограммированием. Отличия состоят лишь в следующем:
Проблемы, решаемые с помощью MDAПервое различие между традиционным и корпоративным метапрограммированием заключается в тех проблемах, которые решаются с их помощью. Традиционное метапрограммирование в основном решает следующие задачи:
Корпоративное метапрограммирование тоже затрагивает эти моменты, но также охватывает и другие. Прежде всего, всегда существовала одна проблема, когда модели часто разрабатывались в начале проекта, становясь несоответствующими по мере его развития. С точки зрения программирования это означает, что модель является не совсем точной, а ее постоянное изменение только тормозит выполнение проекта. Разработать модель в начале проекта, а затем не использовать ее кажется расточительным. Также кажется расточительным разработать модель в программе построения диаграмм, а позже переписывать ее в виде кода. Поэтому архитектура Model Driven Architecture ставит своей целью сделать разработанные в начале проекта модели частью самого кода так, чтобы они оставались в актуальном состоянии и не были лишними в процессе написания кода. Другой связанной проблемой является проблема передачи информации. Для человека, не являющегося программистом, очень сложно понять код программы. Однако если код представлен в графическом виде, непрограммистам оказывается существенно легче обсуждать предмет программирования. Это, конечно, может усложнить процесс написания кода, поскольку в него приходится вносить элементы эстетики, но, в конечном счете, эффективность взаимодействия между программистом и экспертом в предметной области существенно повышается, поскольку эксперт может самостоятельно комментировать код, если он представлен в графическом, удобном для восприятия виде. Следующей проблемой является перенос программ между различными платформами. Часто различные представители бизнеса используют самые разнообразные инструменты. Это не обязательно происходит из-за технической непредусмотрительности, а просто имеет место по следующим причинам:
В силу вышесказанного, нужно просто допускать то, что в большой организации всегда будет иметься ряд различных технологий, которые должны быть объединены вместе. Поэтому система метапрограммирования должна быть настраиваемой и обеспечивать вывод результатов, которые могли бы использоваться в самых разнообразных системах. И последней проблемой является проблема поддержки. Недостаточно просто писать приложения - их также необходимо поддерживать. Поскольку модель напрямую внедрена в сам код, поддержка упрощается. Программисты могут оставлять информацию для будущих разработчиков в графическом виде и использовать для объяснения своих программ не только текст, но также графические средства и схемы. Фактически, во многих случаях графики и схемы будут являться программой! Платформо-ориентированные и платформо-независимые моделиКлючевой концепцией Model Driven Architecture, которая может решить или облегчить все вышеупомянутые проблемы, является платформо-независимая модель . По существу, архитектура MDA имеет три уровня:
Иметь модель PIM, которую можно транслировать в несколько моделей PSM, оказывается полезным по следующим причинам:
Вторая причина является гораздо более важной по сравнению с первой. Давайте, например, предположим, что у вас есть модель данных, которую вы хотите использовать в программе управления базой данных, написанной на языке C++. В случае с платформо-независимой моделью вы можете написать единственный исходный файл и транслировать его во множество различных компонентов конечной системы. Например, модель данных может быть транслирована в следующие компоненты:
Итак, из одной модели PIM вы могли бы получить три отдельных модели PSM. Обратите внимание на то, что разница между моделью PSM и кодом состоит лишь в их уровне (думайте о языке программирования как о модели PSM для его объектного кода). Важная идея заключается в трансляции одного исходного файла в несколько платформо-ориентированных, каждый из которых охватывает различные аспекты системы. Чтобы программировать в модели Model Driven Architecture, необходимо уметь программировать на всех трех ее уровнях в зависимости от поставленной задачи и, возможно, даже уметь писать транслирующие программы между исходными и конечными моделями:
Преимущества модели Model Driven Architecture заключаются в следующем:
Пример: построение кода из диаграмм программы DiaОдной из наиболее интересных особенностей MDA является то, что, хотя в нее включены определенные спецификации, в своей основе она является идеей, концепцией и процессом. Инструмент является инструментом MDA в том случае, если в нем реализованы некоторые или все концепции MDA. Конечно, являясь стандартом OMG, унифицированный язык UML (Unified Modeling Language) является предпочтительным языком моделирования, однако концепция MDA в чрезвычайной степени замещает собой технологии, которые она использует.
В нашем примере мы создадим инструмент MDA, который на основе диаграммы класса, созданной в программе Dia, генерирует код SQL для таблиц базы данных, а также код языка C++ для простого класса C++. Это не оправдывает полных ожиданий от инструментов MDA, однако служит хорошим примером генерирования нескольких моделей PSM (в нашем случае мы сгенерируем действующий код) из одной модели PIM. Создание диаграммыДля создания диаграммы запустите программу Dia и используйте ее графические возможности UML. Когда вы запустите Dia, вы увидите окно, подобное изображенному ниже. В главной панели инструментов расположено меню типов объектов. Выберите набор объектов UML. Первым объектом в этом наборе является класс UML. Выберите его и добавьте к вашей диаграмме, которая будет выглядеть примерно так, как изображено на следующем рисунке. Рисунок 3. Класс UML в новой схеме Если вы дважды щелкнете на значке нового класса, вы увидите следующий экран: Рисунок 4. Основная информация о классе Диалоговое окно позволяет вам указать информацию о классе. Поскольку мы используем ограниченный пример, то в нашем случае используется только поле Name. Наш класс будет называться Person. Далее нужно добавить атрибуты - для этого перейдите на вкладку Attributes. Здесь мы добавим три поля: id (тип int), name (тип text) и address (тип text). Вы должны видеть на вашем экране следующее: Рисунок 5. Редактирование атрибутов класса Нажмите кнопку OK диалогового окна, чтобы закончить. Если захотите, Вы можете добавить дополнительные классы. Когда вы закончите, сохраните диаграмму с помощью следующего диалогового окна: Рисунок 6. Диалоговое окно сохранения диаграммы При сохранении диаграммы убедитесь, что флажок "compress diagram files" снят. Краткий обзор формата файла программы DiaФайл программы Dia является простым файлом формата XML, использующим собственные схему и пространство имен Dia. Этот файл может быть как сжатым, так и несжатым (наша программа имеет дело с только с несжатыми файлами). Формат файла достаточно простой. Ниже приведены некоторые фрагменты файла, который мы только что создали.
В файле содержится много информации, но только малая ее часть является для нас полезной. Обратите внимание на блоки XML, начинающиеся с тегов, подобных тегу Имя класса содержится в атрибуте с именем name . Все атрибуты содержатся в ветке с названием attributes , каждый атрибут является атрибутом класса umlatrribute с соответствующими полями name и type. По этой причине среди огромного множества тегов XML сосредоточьте внимание только на тех их них, которые представляют интерес. Реализация MDAРеализация MDA - это простой парсер SAX, написанный на языке Scheme с использованием модуля SSAX. Парсер считывает данные из одного файла с расширением .dia и записывает данные в файл SQL, а также в исходный файл C++. Для каждого класса создается класс C++ и таблица базы данных. Для максимального упрощения в нашем примере поддерживаются только атрибуты (не операции), и не реализованы функции загрузки/сохранения базы данных. Тем не менее, для добавления этого функционала нужно выполнить лишь несколько дополнительных шагов, добавив их к парсеру, приведенному в листинге 4. Ниже приведен код приложения MDA, написанный для использования с компилятором Chicken Scheme (другие схемы, вероятно, потребуют лишь незначительной модификации в строке загрузки модуля SSAX). Листинг 4. Полный листинг программы для приложения MDA
Для простоты имена входного и выходных файлов жестко запрограммированы, поэтому убедитесь, что вы сохраняете файл программы Dia в ту же папку, что и файл tables.dia. Сохраните программу под именем mda.scm. Для ее запуска просто выполните команду Листинг 5. Выходные данные SQL, полученные в результате выполнения программы MDA
Выходные данные C++ выглядят следующим образом: Листинг 6. Выходные данные C++, полученные в результате выполнения программы MDA
Итак, ценой почти двухсот строк кода вы можете создавать диаграммы вместо того, чтобы писать код SQL и C++. Конечно, получается еще веселее, когда программу преобразования пишет кто-то другой. ЗаключениеModel Driven Architecture является мощной концепцией, основанной на крепких традициях метапрограммирования. Используя идею платформо-независимых моделей, MDA пока еще выходит за рамки традиционных методов.
|
|