Здравствуйте, не могу найти ссылку на скачивание курса «Визуальное моделирование: теория и практика»
Номер платежа 6400454020565 |
Пример предметно-ориентированного визуального языка
Абстрактный синтаксис в форме метамодели
Метамоделирование - это техника описания абстрактного синтаксиса языка с помощью диаграмм классов. Здесь могут использоваться либо диаграммы классов UML, либо какие-то более специализированные формализмы, как например, в Microsoft DSL Tools. Метамоделирование, по сравнению с грамматиками в форме Бэкуса-Наура, позволяет глубже формализовывать структуру языка, создавать более сложные отношения между конструкциями, используя, например, ассоциации, а также естественно реализовывать ссылочную целостность. Однако с помощью метамоделирования неудобно создавать объемные спецификации, состоящие из большого числа однотипных элементов. Например, допустимые в языке символы удобнее определять с помощью грамматики в форме Бэкуса-Наура.
Ссылочная целостность - это механизм, гарантирующий, что значения всех ссылок в текстах языка корректны. Ее можно реализовать на уровне схемы, метамодели, грамматики - т.е. статически. Все связи имеют соответствующие типы, так что значение неправильного типа просто невозможно подставить в спецификацию - она не будет соответствовать схеме. Однако часто реализовывать ссылочную целостность статически, на уровне синтаксиса, оказывается затруднительно - например, описание синтаксиса становится слишком громоздким. Тогда ссылочная целостность реализуется динамически - при автоматизированной обработке текстов. Метамоделирование является статическим способом реализации ссылочной целостности формальной спецификации абстрактного синтаксиса языка.
На рис. 12.3 представлена метамодель, описывающая SCL. Посмотрим, как она соответствует построенной выше грамматике в форме Бэкуса-Наура.
Все нетерминалы грамматики превратились в классы метамодели, включение одних конструкций в другие переходит в агрегирование, операторы '*', '+', '[ ]' выражены через множественность агрегирования - 0..*, 1..*, 0..1 соответственно. Конец ассоциаций со значком агрегирования во многих случаях назван именем Owner. В случае класса component даны имена противоположным концам агрегирования. Имена концов ассоциаций понадобятся для составления формальных ограничений на метамодель1В лекциях, посвященных UML, говорилось о том, что имена концам ассоциаций и самим ассоциациям можно давать, а можно и нет, в зависимости от потребностей и удобств чтения диаграммы.. Ссылки выражены направленными ассоциациями и имеют имена на концах со стрелками (это также понадобится для составления ограничений). В случае ссылки конечного автомата на содержащую его компоненту (конструкция <state_ref> у <statechart> ) роль такой ссылки выполняет агрегирование - по этой связи можно добраться от конечного автомата до его компоненты-владельца.
Идентификаторы обозначены в метамодели атрибутами классов с именем name. Наконец, оператор альтернативы '| ' выражен наследованием: абстрактный класс имеет несколько альтернативных наследников.
OCL-ограничения на метамодель
Некоторая информация об абстрактном синтаксисе SCL не вошла ни в грамматику, ни в метамодель. Ниже эта информация сформулирована в виде утверждений на языке OCL.
- Методы, вызываемые из переходов автомата, должны обязательно быть методами этой компоненты.
context handle_invocation inv: self.method_ref.owner == self.owner.owner.owner. owner.owner
- Не может быть пустых компонент, не имеющих ни методов, ни атрибутов, ни конечного автомата.
context component inv: not (self.attributes-> isEmpty() and self.methods ->isEmpty() and self.statecharts->isEmpty())
-
Параметры компоненты являются целыми неотрицательными числами, причем первый параметр меньше либо равен второму.
context component inv: self.init >=0 and self.init < = self.num
Попытка выразить эту информацию на метамодели существенно усложнила бы формальное описание абстрактного синтаксиса SCL (попытайтесь это сделать в качестве упражнения!).
Теперь несколько слов о самом языке OCL. Каждое OCL-утверждение должно иметь контекст - класс, ассоциацию или операцию. Например, первое утверждение из представленных выше примеров читается так: для любого экземпляра класса handle_invocation справедливо следующее утверждение… Ключевое слово self обозначает экземпляр той сущности метамодели, которая объявлена контекстом утверждения. Пользуясь точкой, можно обращаться к значениям классов атрибутов (например, self.init ), а также к противоположным концам ассоциаций, если те имеют имена (ведь концы ассоциаций очень похожи на атрибуты класса, как обсуждалось в лекциях по UML ). Через имена концов ассоциаций можно "ходить" по модели и таким образом расширять контекст, к которому применяется OCL-ограничение. Но исходная точка, от которой происходит "хождение" и к которой в любой момент можно вернуться через ключевое слово self, неизменна для всего утверждения.
Язык OCL имеет ряд вcтроенных функций (например, функция isEmpty ), а также средства для работы с коллекциями, квантор всеобщности с заданием связной переменной и т. д.
В средах типа Microsoft DSL Tools из языка OCL взята лишь сама идея - накладывать логические ограничения на метамодель, дополнительно контролируя пользователя будущего редактора, не позволяя делать ему некоторых вещей, явно не определенных в метамодели. Однако сами ограничения там задаются на языке C#. Это гораздо практичнее, так как иначе пользователям среды пришлось бы дополнительно изучать новый язык ( OCL ), а авторам - создавать для него транслятор все в тот же С#.
Конкретный синтаксис
Одним из способов задать конкретный синтаксис - графические грамматики. Они надстраиваются над грамматикой в форме Бэкуса-Наура. Получается, что конкретный синтаксис включается в абстрактный, определяя графические символы для ряда конструкций языка2Пример такой грамматики можно посмотреть в [12.2]..
В SCL существуют следующие графические символы:
Грамматика в форме Бэкуса-Наура расширяется следующими операторами:
- contains - бинарный оператор, который обозначает тот факт, что первая графическая конструкция (левый аргумент) содержит вторую (правый аргумент);
- is associated with - бинарный оператор определяющий, что первая графическая конструкция (левый аргумент) должна быть ближе ко второй (правый аргумент), чем любой другой символ на диаграмме; данный оператор используется для "привязки" надписей к линиям, к границам прямоугольников, а также для связи одной графической фигуры с другой (та, другая, должна быть соединена с линией, один конец которой свободен);
- is followed by - бинарный оператор, который обозначает, что за первой графической конструкцией (левый аргумент) следует вторая (правый аргумент) и, связаны они направленной линией;
- is connected to - бинарный оператор, который определяет, что первая графическая конструкция (левый аргумент) соединяется со второй (правый аргумент), причем одна из них - линия;
- set - постфиксный оператор, обозначающий, что графические символы, являющиеся его аргументами, могут располагаться на диаграмме в произвольном порядке.
Определение диаграммы компонент SCL может выглядеть следующим образом:
<component_diagram> ::= {<signal_list>+ <component>+ <statechart_diagram>+} set
Это означает, что на диаграмме компонент должен присутствовать один или более списков сигналов, один или более компонент диаграмм конечных автоматов для компонент, и все эти конструкции располагаются в произвольном порядке.
Определение компоненты можно изобразить так:
<component> ::= <component_symbol> contains {component_name><parameters> <attribute_area> <method_area>}
Графический символ компоненты содержит область, структура которой задана вторым операндом оператора contains: имя компоненты и ее параметры, набора атрибутов и методов. Диаграмма конечных автоматов (конструкция <statechart_diagram> определяется так:
<statechart_diagram> ::= {<statechart_symbol> contains { <component_ref> {<state>+} set}
То есть в прямоугольнике <statechart_diagram> сначала можно увидеть имя компоненты, к которой относится этот автомат (конструкция <component_ref> ), а затем идет и сам автомат (что точно обозначает "сначала" и "затем" не определяются грамматикой; считается, что они однозначно определяются либо по умолчанию, либо контекстом, либо, если все таки возникает неоднозначность, то это не важно…). Автомат состоит из состояний, которые расположены на диаграмме в произвольном порядке (это задает оператор set ).
Cостояние определяется так:
<state> ::= {<state_symbol> contains <state name>}is associated with <input_area>
Эта строка читается следующим образом: <state_symbol> содержит в себе <state name> и находится ближе всех других графических символов к графическому агрегату <input_area>.
Конструкция <input_area> определяется так:
<input_area>::= {[<input>]/<action> {; <action>}*}} is associated with <transition_area>
Она состоит из текстовой надписи, которая задается фрагментом грамматики [<input>]/<action> {; <action>}*}, и графического агрегата <transition_area>. При этом надпись "прилеплена" к <transition_area>.
Конструкция <transition_area> задается как линия, конец которой присоединен к графическому агрегату <next_state_area>:
<transition_area>::= <transition_symbol> is connected to <next_state_area>
Конструкция <next_state_area> – это символ состояния с текстовым именем внутри:
<next_state_area> ::= <state_symbol> contains <state name>
Выше были представлены лишь фрагменты, которые нужно формально соединить с грамматикой абстрактного синтаксиса SCL. Это не было выполнено, чтобы не усложнять пример, однако читатель может попробовать это сделать в качестве упражнения.