С момента своего создания несколько лет назад язык Unified Modeling Language (UML) привлек внимание многих представителей отрасли благодаря своей роли универсального языка для моделирования программных систем. Хотя на первых этапах процесса разработки UML дает неплохие результаты, в нем отсутствуют компоненты, необходимые для этапов проектирования и реализации систем, в частности, структурные и «поведенческие» конструкции. Обсуждаемое объединение UML и языка Specification and Description Language (SDL) позволит увеличить потенциал UML как языка графического программирования.

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

Что касается перспективы стандартизации языка, то подобный процесс предполагает участие международных организаций по стандартам, таких как Object Management Group и Международный союз электросвязи (ITU). Поддержка этих языков по отдельности влияет на их эволюцию и способствует совершенствованию их обоих. Кроме того, бесконфликтное взаимодействие двух языков подсказывает естественный вывод о том, что в определенный момент отличить их друг от друга станет невозможно.

Объединение UML и SDL

Язык моделирования должен развиваться параллельно с технологическими достижениями. Этот процесс развития может происходить либо в изоляции, либо кумулятивно, на основе результатов совершенствования другого языка моделирования. Как язык SDL [1] представляется более согласованным, чем UML [2] и имеет более четкую семантическую основу. С другой стороны, UML более выразительный и широко используемый. Цель объединения двух языков состоит в том, чтобы позволить использовать выразительные возможности UML в сочетании с достоинствами SDL, к которым в первую очередь относятся согласованность и семантика.

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

Версии SDL

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

Рекомендация ITU Z.109, называемая «SDL, объединенный с UML» (SDL Combined with UML) [3] отражает основной объем работы, проделанной в рамках объединения двух языков. В данной рекомендации определено подмножество UML, которое семантически осмысленно для SDL. Программисты, работающие с UML, могут использовать это подмножество, общую часть любого профайла UML, для создания модели, которую они могут интерпретировать как SDL. Обычно, эта возможность сама по себе слишком ограничена, чтобы оказаться полезной; в силу чего, моделирование всего SDL с помощью UML становится практически осуществимым только тогда, когда оно сочетается с конструкциями моделирования SDL. Рекомендация ITU уже включает в себя некоторые части профайла; другие, как предполагается, будут предложены в дальнейшем.

Семантика действий в UML

Работа над созданием точной семантики действий для UML [4] уже ведется и включает в себя построение соответствий с SDL. Семантика действий предусматривает определение действий, которые могут возникать в машинах состояний или в операциях классов и которые более детальны и точны, чем определения, сейчас имеющиеся в UML.

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

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

Помимо определения профайла SDL для UML и работы над семантикой действий сообщество специалистов, использующих язык SDL, принимает активное участие в разработке UML 2.0 [5]. В этой работе основную роль играет структурное моделирование, а также моделирование поведения в виде машин состояний и взаимодействий, а именно, диаграмм последовательностей.

Иерархическая декомпозиция структур

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

Создание профайла

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

Чтобы определить контекст для стереотипов, которые входят в состав профайла, и показать, как они взаимодействуют друг с другом, использовалась виртуальная, или концептуальная, метамодель. Хотя она не является корректной метамоделью UML, ее, тем не менее, можно использовать для реализации всех практических целей с тем же успехом, как если бы она была таковой. Как показано на рис. 1, эта концептуальная модель использует агента и вентиль в качестве конструкций UML так же, как, к примеру, класс. Более того, каждый стереотип наследует все свойства своего базового элемента модели, в том числе, его атрибуты и связи.

Рис. 1. Часть концептуальной метамодели SDL

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

Логические компоненты и интерфейсы

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

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

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

Вентили поддерживают двунаправленные интерфейсы, которые определяют контракты между агентами. Контракты составляют важную часть инфраструктуры моделирования; профайл допускает взаимодействие только между парами реализованных и требуемых интерфейсов. Каждый вентиль может реализовывать несколько интерфейсов, которые должны выполняться агентом, которому принадлежит вентиль. Кроме того, вентиль может требовать, чтобы интерфейсы реализовывали другие агенты. На рис. 2 показан пример нотации для агентов и вентилей. Эта нотация была использована для присваивания альтернативных пиктограмм стереотипам, чтобы выделить их и сделать диаграмму более понятной.

Рис. 2. Пример нотации для агентов и вентилей

Вентили поддерживают двунаправленные интерфейсы, которые определяют контракты между агентами. SDL допускает взаимодействие только между парами реализованных и требуемых интерфейсов. Каждый вентиль может реализовывать несколько интерфейсов. Нотация lollipop, первоначально использовавшаяся для интерфейсов UML, соответствует особому случаю, при котором вентиль реализует только один интерфейс. Стрелки подчеркивают роль вентилей в установке путей взаимодействия и дают визуальное представление о том, что происходит. Использование вентилей в агентах делает их автономными.

Структура времени исполнения

Структура времени исполнения описывает, как агенты взаимодействуют друг с другом. Агент может содержать машину состояний и подструктуру, включающую в себя других агентов. Чтобы увидеть, каким образом машина состояний и агенты, которых он содержит, взаимодействуют (т.е. роли, которые они играют как часть агента), необходимо не только знать о свойствах «черного ящика» агента, но и представлять его внутреннее содержание. Рис. 3 показывает внутреннюю структуру агента. В данном случае поведение машины состояний игнорируется за исключением моментов, определяющих ее взаимодействие с агентами, составляющими часть подструктуры, и управления ими.

Рис. 3. Внутренняя структура агента

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

Визуализация поведения

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

Представление, ориентированное на преобразование

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

Машины состояний UML не уделяют преобразованиям того внимания, которого те заслуживают, что проявляется в отсутствии четкой нотации для их действий. Поскольку диаграммы состояний UML, в общем и целом, ориентированы на состояние, они «игнорируют» то, что происходит во время преобразований. В SDL ситуация практически полностью противоположная — представление SDL ориентировано на преобразования, так что оно сосредоточено на действиях. Эти два представления в значительной степени дополняют друг друга: ориентация UML на состояние дает прекрасную возможность получить общее представление, а ориентация на преобразование в SDL позволяет углубиться в детали и в то же время сохраняет контекст.

Рис. 4. Преобразования с действиями

Преобразование состоит из операторов, заключенных в своего рода скобки из символов, которые несут в себе информацию о действиях и имеют семантическое значение. Символ ввода указывает сигнал или операцию, которые инициируют преобразование и могут содержать список параметров; символ задачи обычно указывает на присваивание; символ вывода показывает сообщение, которое агент посылает определенному объекту; символ сохранения определяет сигналы, которые необходимо отслеживать; «звездочка» в символе сохранения служит указанием на сигналы и операции, для которых состояние точно не определено, и показывает, что они должны быть обработаны в последующих состояниях. Символ замечания содержит декларации атрибутов (переменных) и ему предшествует ключевое слово DCL, что позволяет отличить замечание от обычных комментариев.

Итак, особое внимание в проекте уделялось процедурам как части преобразования, но для процедур, которые являются частью операций, принципы остаются теми же. Рис. 4 показывает действия SDL на основе семантики действий UML. Преобразование содержит несколько операторов, заключенных в своего рода скобки из символов разных типов. Эти символы несут в себе информацию о действиях и имеют семантическое значение, которое помогает составить визуальное представление о том, что происходит во время преобразования. Большинство символов представляет один оператор, такой как ввод, вывод, цикл, решение и вызов операции. Обобщенный символ задачи, который имеет свою сферу применения, может содержать любое количество действий, но обычно представляет присваивания. Некоторые символы знакомы из UML, где они применяются в диаграммах работы. Символ ввода указывает сигнал, который инициирует преобразование; он также может содержать список передаваемых параметров. Символ задачи указывает на присваивание, а символ вывода показывает сообщение, которое агент посылает определенному объекту. Символ сохранения определяет сигналы, которые машина состояний должна отслеживать, т.е. превращать указанные сигналы в последовательные состояния. «Звездочка» в символе сохранения указывает на сигналы и операции, состояние которых точно не определяется. Символы влияют на действия, увеличивая точность тех из них, которые являются частью преобразований.

Другие важные моменты

Существует еще ряд аспектов, на которые следует обратить внимание при рассмотрении вопроса об объединении SDL и UML. Это специализация преобразований, графическое представление стандартных и определенных пользователем исключений, а также использование шаблонов для данных и структур. Еще один важный вопрос — это модель данных, в том числе типы данных, которыми может пользоваться программист, и то, каким образом модель разрешает выражения. Отображение на семантику действий позволяет решить часть этих вопросов. Кроме того, отображение языков на семантику действий затрагивает и другие перечисленные выше аспекты. Граница между языком моделирования и языком программирования очевидна. Но при добавлении значительного числа деталей к языку моделирования он начинает выглядеть как язык программирования.

Результаты графического программирования

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

Подходы к моделированию

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

  • Они моделируют систему на UML, а затем используют привычный для себя язык программирования для реализации системы вручную. В этом случае программисты обычно забывают о модели сразу же, как только написан реальный код.
  • Они моделируют систему на UML, а затем используют привычный для себя язык программирования для генерации кода-заглушки. Инструментальные средства обычно предлагают механизмы для синхронизации модели с кодом, если внесены изменения — так называемое «взаимообратное проектирование». Если программисты не используют синхронизацию, иногда они сохраняют модель для подготовки документации, но могут и отказаться от нее сразу после генерации кода-заглушки.
  • Они моделируют систему на UML и используют специализированные абстракции (такие как сигнал), для того чтобы обеспечить реализацию напрямую, обычно на C++. Такой подход аналогичен генерации кодов-заглушек, за исключением того, что программист либо скрывает добавленный код за преобразованиями, что приводит к «лоскутному» программированию, либо отображает код параллельно с преобразованием, что приводит к появлению довольно запутанных диаграмм.

Создание приложений

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

Программу можно компилировать сразу после проверки синтаксической и семантической корректности; однако, более гибкий подход предусматривает использование обычных языков программирования, таких как C++ и Java, в качестве промежуточных форматов. Вместо того чтобы вносить изменения в уже сгенерированный код, можно интегрировать внешний код или библиотеки в систему или использовать определенный кросс-компилятор.

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

Влияние процесса разработки

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

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

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

Литература

[1] ITU-T, ITU Recommendation Z.100: «The Specification and Description Language (SDL),» ITU, Geneva, 2000

[2] OMG, «OMG Unified Modeling Language Specification,» Version 1.3, OMG, ad/99-06-08, June 1999

[3] ITU-T, ITU Recommendation Z.109: «SDL Combined with UML»; http://www.itu.int/itu-doc/itu-t/rec/z/index.html

[4] OMG, «Action Semantics for the UML, Request for Proposal,» OMG, ad/99-11-01, 1998; http://www.omg.org

[5] OMG, «UML 2.0 Superstructure, Request for Proposal,» ad/2000-09-02, 2000; http://www.omg.org


Graphical Programming Using UML and SDL, Morgan Bjorkander, IEEE Computer, December 2000, pp. 30-35. Copyright IEEE CS, 2000, Reprinted with permission. All rights reserved.