Искусственный язык должен быть как-то описан. Искусственный язык, претендующий на массовое использование, должен быть описан так, чтобы притягивать, а не отпугивать потенциальных пользователей. А это сделать не так просто.
История языков программирования насчитывает более полувека и столько же продолжается развитие методов их определения. На этом пути были прорывы (определения Алгола 68, Паскаля), были и неудачи (PL/1) . От определения искусственного языка требуется, чтобы оно было:
Между тем, эти требования зачастую исключают друг друга. В некоторых случаях во главу угла ставится что-либо одно, но результат редко оканчивается удачей. Например, определение Алгола 68, где все было нацелено на формальную точность, явилось новым словом в методах определения языков и оказало большое влияние на развитие теории. В то же время, это описание оказалось настолько непонятным рядовым пользователям, что отпугнуло их от потенциально многообещающей разработки. Другой пример: с целью "понятности" первые диалекты Кобола описывались совершенно неформально, в результате получалось плохо, потому что для достижения минимальной необходимой точности и полноты неформальное описание приходилось делать очень длинным, а потому непонятным.
Наиболее удачными оказались компромиссные решения, и авторы UML пошли именно по этому пути.
В основу описания UML положен метод раскрутки, то есть использование определяемого языка для определения этого языка. А именно, основные конструкции UML формально определены с помощью UML. Конечно, с чего-то раскрутку нужно начать, и это описано в UML неформально, с помощью текстов на естественном (английском) языке.
Метод раскрутки часто применяется при определении формальных языков. Например, можно очень изящно определить операционную семантику языка программирования, если написать транслятор или интерпретатор данного языка на этом же языке. Одним из первых этот прием использовал Н. Вирт, создавая язык Паскаль.
В описании UML используются три языковых уровня.
Это кажется нагромождением сущностей без нужды, но на самом деле только использование ученой приставки мета (от греческого μετα, что означает "между", "после", "через") может быть несколько непривычным. Действительно, рассмотрим описание какого-либо из обычных языков программирования. Чтобы никого не обидеть, пусть этот язык называется X. Если описание хорошее, то в самом начале указывается язык (иногда его так и называют ‒ метаязык), который используется для описания языка X. Например, приводится фраза такого типа: "синтаксис языка X описан с помощью контекстно-свободной грамматики, правила которой записаны в форме Бэкуса-Наура (БНФ), контекстные условия и семантика описаны на естественном языке". Если описание не очень хорошее, то такая фраза может и отсутствовать, но она все равно неявно подразумевается и от читателя требуется понять используемый метаязык по контексту. Далее с помощью метаязыка более или менее формально описываются конструкции языка X; все, что не удается описать формально, описывается на естественном языке (при этом зачастую вводится большое количество "новых" терминов и используются трудные для чтения канцеляризмы). Все это, как правило, сопровождается многочисленными конкретными примерами фрагментов текстов на языке X. Чтобы читатель не путался, где текст на языке X, а где текст на метаязыке, или где общее описание, а где конкретный пример, применяются различные полиграфические приемы: изменение гарнитуры и начертания шрифта, отступы, подчеркивание и т.д. В результате получается неплохо: многоязыковая смесь становится вполне удобочитаемой (при минимальном навыке).
Таким образом, основная идея описания UML вполне традиционна и согласуется с общепринятой практикой: мета-метамодель ‒ это описание используемого формализма; метамодель ‒ это и есть собственно описание языка (элементов моделирования); там, где формализм не срабатывает, на помощь приходит естественный язык и все это сопровождается примерами фрагментов моделей.
Весь текст описания UML каждой версии находится в свободно распространяемых документах, доступных по адресу www.omg.org. В таблице перечислены основные документы, входящие в комплект документации для версии UML 2.4.1 (август 2011).
Документ и его содержание | Количество страниц |
---|---|
|
230 |
|
748 |
|
86 |
|
244 |
1308 |
Без специальной предварительной подготовки читать в этих документах имеет смысл только вводные разделы, примерно соответствующие по задачам этой главе, и последние разделы, в которых собраны толкования основных терминов, примерно соответствующие по задачам последней главе этой книги. Остальное предназначено не для ознакомительного чтения пользователями, а для скрупулезного изучения разработчиками инструментов моделирования. По замыслу авторов языка для пользователей должны быть написаны другие книги, и они написаны, как самими авторами, так и любителями UML. Один из примеров перед вами.
В описании языка самым важным является раздел описания семантики. Семантика описана следующим образом. Для определяемого элемента моделирования задается абстрактный синтаксис (в форме диаграммы классов UML) и указываются ограничения, которым должен удовлетворять описываемый элемент в форме выражений языка OCL. Все остальное, включая прагматику, описывается на естественном языке, который авторы называют "plain English".
Далее для каждого элемента моделирования указывается, как его рекомендуется изображать в графическом виде. Фактически, этот раздел соответствует разделу описания синтаксиса для обычного языка программирования. Но UML не обычный язык, а графический! Пока что для описания синтаксиса графических языков не придумано столь же удобного механизма, как формальные грамматики, поэтому в этом разделе стандарта приведены довольно многословные описания в следующем стиле: "Состояние автомата изображается прямоугольником со скругленными углами, внутри которого указывается имя состояния в виде строки текста, а также, возможно…" и так далее. К счастью, графический синтаксис UML довольно прост и тщательно продуман, так что, если вы отличаете окружность от квадрата, то разобраться не трудно.
Большая часть содержания этой книги посвящена неформальному пересказу и обсуждению того, что формально описано в основном документе "UML Superstructure". Прочие же разделы стандарта здесь фактически не рассматриваются, и не потому, что они длинные, а потому, что знание их содержания практически не влияет на достижение главной цели книги: объяснить, как, когда и почему можно и нужно использовать UML при разработке программного обеспечения.
Как уже было сказано, читать стандарт для первого знакомства с языком бесполезно. Но если вы уже знаете UML, то изучение того, как именно авторы используют UML для описания самого UML, является чрезвычайно полезным упражнением. Дело в том, что авторы UML мастерски используют UML, поэтому рассматривание диаграмм в стандарте в процессе изучения UML подобно чтению кода, написанного хорошим программистом, в процессе изучения языка программирования.
Проблема терминологии является одной из самых болезненных при обсуждении языка UML.
Во-первых, авторы UML старались сделать язык независимым от конкретных языков программирования, моделей вычислимости и тому подобного. С этой целью они зачастую вводили новые термины для определяемых понятий, чтобы случайное совпадение со старым термином, уже занятым в какой-либо смежной области программирования, не вводило в заблуждение пользователя. Кроме того, в UML унифицированы многие различные подходы и методы, каждый со своей терминологической традицией и их все необходимо было учесть и иногда пойти навстречу. Как всякий компромиссный вариант, терминология UML получилась довольно замысловатой и не всегда последовательной.
Во-вторых, эта книга написана по-русски и для русскоязычного читателя. Стало быть, термины UML должны так или иначе быть переданы кириллическими буквосочетаниями. Язык UML сравнительно молод (но уже моден), бум публикаций в отечественной литературе начался только сейчас (с опозданием на десять-пятнадцать лет, как обычно), поэтому устоявшейся терминологической традиции пока нет. Хотелось бы использовать хорошие русские слова ‒ "эктор" и "персистентный" решительно отметаются. Словарь в таких случаях бесполезен (хотя им многие пытаются пользоваться). Остается фантазировать, опираясь на вышедшие из печати труды коллег, отечественные программистские традиции и собственный опыт. Основной критерий, который использован нами при выборе переводов терминов: как можно точнее передать смысл исходного термина (но не звучание, не морфологию и не буквальное значение).
Чтобы подчеркнуть, что UML язык графический, авторы называют правила записи (рисования) моделей не синтаксисом, а нотацией. Видимо, это вполне оправдано.
При разработке UML были предложены и приняты разумные рекомендации по выбору нотации. Авторы исходили из того, что UML будет использоваться по-разному: начиная от не очень аккуратного рисования от руки на листке бумаги, печати черно-белых изображений в книгах и заканчивая созданием сложных диаграмм с помощью компьютера. Поэтому в качестве основных графических элементов были выбраны такие, которые было бы легко использовать во всех случаях. Типов элементов нотации пять:
Фигуры (shape) в UML используются двумерные (т.е. их можно нарисовать на плоскости) и замкнутые (т.е. есть внутренняя и внешняя части). Фигуры могут менять свои размеры и форму, сохраняя при этом свои интуитивные отличительные признаки. Например, среди фигур UML есть прямоугольники и эллипсы. Они могут быть изображены многими способами: разного размера, с разным соотношением длин сторон (или, соответственно, полуосей), по-разному ориентированы относительно границ страницы и т.д., но всех случаях прямоугольник отличен от эллипса и не может быть с ним спутан. Внутри фигур могут помещаться другие элементы нотации: тексты, линии, значки и даже другие фигуры. Единственное требование: должно быть однозначно понятно, что элемент нотации находится внутри фигуры, в частности, его изображение не должно пересекать границу фигуры.
Линии (line) в UML, естественно, одномерные. Линии всегда присоединяются своими концами к фигурам или значкам, они не могут быть нарисованы сами по себе. Что значит "присоединяются" ‒ формально определить довольно трудно, но неформально (а нотация UML не формальна) все совершенно ясно: линия должна быть нарисована так, чтобы любому нормальному человеку было ясно, присоединяется данная линия к данной фигуре, или нет. Форма линий произвольна: это могут быть прямые, ломаные, плавные кривые ‒ значения это не имеет. Толщина линий также произвольна. А вот стиль линии имеет значение. К счастью, в UML используется только два стиля линий, которые трудно спутать: сплошные и пунктирные линии. К линиям могут быть пририсованы различные дополнительные элементы: стрелки на концах, тексты и т.д. Единственное требование: должно быть ясно, что дополнительный элемент относится именно к данной линии. Линии могут пересекаться, и это ничего не значит, но рекомендуется избегать таких случаев, поскольку это затрудняет восприятие.
Значки (icon) в UML похожи на фигуры тем, что они двумерные, а отличаются тем, что не имеют внутренности, в которую можно что-то поместить, и, как правило, не меняют свою форму и размеры. Впрочем, значки в UML используются очень умеренно, а потому сохраняют свою основную функцию однозначно воспринимаемого иероглифа.
Тексты (text) в UML ‒ это, как обычно, последовательности различимых символов некоторого алфавита. Алфавит не фиксирован ‒ он только должен быть понятен читателю модели. Гарнитура, размер и цвет шрифта не имеют значения, а вот начертание шрифта имеет: в UML различаются прямые, курсивные и подчеркнутые тексты. Предполагается, что читатель сумеет их различить.
Рамки (frame) появились в UML 2. Рамка ‒ это частный случай фигуры, которая используется исключительно как контейнер для других фигур, линий, значков и текстов. Пустые рамки не применяются. Рамка имеет прямоугольную форму и, как правило, ярлычок в левом верхнем углу, в котором указывается тип и имя рамки.
В общем, нотация UML довольно свободная: рисовать можно как угодно, лишь бы не возникало недоразумений. Поставщики инструментов, поддерживающих UML, пользуются этой свободой кто во что горазд. Использование цветов для заливки фигур и раскрашивания линий, тени у значков и фигур, разные шрифты в текстах, наконец, анимация изображений ‒ все это, конечно, полезные вещи, поскольку повышают наглядность картинок. Важно при этом знать меру, а мера очень проста и даже имеет название ‒ каноническая нотация (canonical notation). Согласно ей любая модель может быть описана монохромными рисунками с текстовыми пояснениями. При этом рисунки должны оставаться вразумительными после печати на черно-белом принтере.
В бумажной книге мы использовали каноническую нотацию, но в электронной книге подобное самоограничение было бы нелепым. В диаграммах мы активно используем цвета, причем придерживаемся определенной палитры цветов, отражающей выбранное представление модели (см. параграф 1.7.3):