UML и способы его использования
Аббревиатура UML расшифровывается как “Unified Modelling Language”, то есть унифицированный язык моделирования. Это определение полезно разобрать по частям.
Язык — это знаковая система для хранения и передачи информации.
Если говорить на человеческом, то язык (в частности формальный искусственный язык) состоит из трёх частей:
- Синтаксис (правила составления конструкций);
- Семантика (правила присваивания смысла конструкциям);
- Прагматика (правила использования конструкций для достижения каких-то целей).
То есть язык описывает, что мы можем использовать для передачи смысла, какой в целом смысл мы можем вкладывать и какие цели достигаются.
Модель — это описание объекта или явления, в котором мы убираем детали, которые нам не критичны в рамках задач, для которых используется данное описание.
Этим, в целом, всё сказано: мы пытаемся показать нужные нам элементы и характеристики системы.
В чём заключается унификация: UML объединил несколько подходов к объектно-ориентированному моделированию, которые авторы языка (Гради Буч, Ивар Якобсон и Джеймс Рамбо) привели к относительно единой структуре. За основу был взят объектно-ориентированный подход, вокруг которого построились остальные средства языка.
Авторы нотации дают ей следующее определение:
UML — это графический язык моделирования общего назначения, предназначенный для спецификации, визуализации, проектирования и документирования всех артефактов, создаваемых при разработке программных систем.
В целом, каждое слово в этом определении, а именно “спецификация”, “визуализация”, “проектирование” и “документирование”, связано с задачами моделирования.
Как в целом можно использовать UML:
- Рисование картинок;
- Обмен информацией;
- Спецификация систем;
- Повторное использование архитектурных решений;
- Генерация кода;
- Имитационное моделирование;
- Верификация моделей.
Отдельно отметим, что курс анализа и проектирования на UML нацелен прежде всего на развитие навыков анализа и проектирования и только потом на документирование полученных проектных решений в виде набора диаграмм. Поэтому для каждой диаграммы важно понимать три вещи: какой вопрос она закрывает, из каких предыдущих артефактов появляется и чем потом проверяется.
| Вопрос | Диаграмма или артефакт |
|---|---|
| Кто и зачем использует систему? | контекст системы, требования, диаграмма использования |
| Как выполняется процесс? | сценарий, спецификация use case, диаграмма деятельности |
| Какие понятия важны в предметной области? | словарь, бизнес-правила, концептуальная диаграмма классов |
| Как предметная модель может быть реализована в ПО? | техническая диаграмма классов, пакеты |
| Из каких крупных частей состоит система? | диаграмма компонентов |
| Где и как система развёрнута? | диаграмма развёртывания |
| Как меняется состояние важного объекта? | диаграмма состояний |
| Как объекты взаимодействуют во времени? | диаграмма последовательности |
UML как единый язык
Заголовок раздела «UML как единый язык»Если смотреть на UML только как на набор разных диаграмм, может показаться, что каждая диаграмма живёт отдельно: у одной есть овалы и акторы, у другой — классы и ассоциации, у третьей — сообщения и линии жизни. В этом есть доля правды, но это не главное. UML задуман не как библиотека картинок для презентаций, а как язык моделирования. У языка есть синтаксис, семантика, правила расширения и внутренняя структура.
Разные диаграммы являются представлениями одной модели. Диаграмма использования показывает систему с точки зрения акторов. Диаграмма деятельности раскрывает сценарий как процесс. Диаграмма классов фиксирует классификаторы, признаки, ассоциации и ограничения. Диаграмма последовательности описывает трассы взаимодействия. Если элементы согласованы между собой, эти представления работают как части одного языка.
Диаграмма не равна модели
Заголовок раздела «Диаграмма не равна модели»Начнём с различия, которое кажется очевидным, но постоянно ломает учебные и реальные модели: диаграмма не равна модели.
Когда мы открываем UML-инструмент, мы видим лист, фигуры, линии, подписи и значки. Это похоже на графический редактор, поэтому возникает соблазн думать, что UML-модель и есть набор нарисованных картинок. Но в UML всё устроено иначе. Модель состоит из элементов, их свойств и отношений между ними. Диаграмма только показывает часть этой модели в графическом виде.
Например, в модели может быть класс Order. Этот класс можно показать на концептуальной диаграмме классов как предметное понятие. Потом тот же смысловой объект может появиться на технической диаграмме классов как entity или model. Далее он может стать объектом с жизненным циклом на диаграмме состояний. На диаграмме последовательности мы можем показать lifeline экземпляра заказа. В матрице трассируемости этот же элемент будет связан с требованиями и сценариями.
Если всё сделано аккуратно, это не пять разных заказов, а один элемент модели, рассмотренный с разных сторон. Диаграммы становятся разными представлениями одной проектной реальности.
Именно здесь UML начинает отличаться от обычного рисования. Если удалить фигуру с диаграммы, это не всегда означает удаление элемента из модели. Иногда мы просто убрали одно представление. Если переименовать элемент на одной диаграмме, инструмент может переименовать его везде, потому что меняется не подпись на картинке, а сам элемент модели. Если на двух диаграммах есть два прямоугольника с одинаковым именем, это ещё не гарантирует, что инструмент считает их одним и тем же классом.
На практике это объясняет многие странности UML-инструментов. То, что кажется “капризом программы”, часто является следствием различия между элементом модели и его графическим представлением.
Отсюда появляется первое важное правило: в UML нужно по возможности создавать и настраивать элементы модели, а не имитировать их обычными фигурами и свободным текстом.
Синтаксис, семантика и прагматика
Заголовок раздела «Синтаксис, семантика и прагматика»Любой язык можно рассматривать на нескольких уровнях. Для UML особенно полезны три уровня: синтаксис, семантика и прагматика.
Синтаксис отвечает на вопрос “как это изображается”. Например, ассоциация на диаграмме классов обычно выглядит как сплошная линия между классификаторами. Guard на диаграмме деятельности записывается в квадратных скобках на ребре. Обобщение рисуется сплошной линией с пустым треугольником.
Семантика отвечает на вопрос “что это означает”. Ассоциация означает возможные связи между экземплярами классификаторов. Guard означает условие, при котором токен может пройти по ребру. Обобщение означает отношение общего и специального классификатора.
Прагматика отвечает на вопрос “зачем мы это используем в проектировании”. Ассоциация помогает показать предметную или техническую связанность объектов. Guard часто фиксирует бизнес-правило или условие ветвления сценария. Обобщение помогает показать классификацию понятий, если она действительно важна для модели.
Если студент работает только на уровне синтаксиса, он пытается нарисовать “похоже на UML”. Это уже лучше, чем хаотичная блок-схема, но всё ещё недостаточно. Хорошая UML-модель появляется тогда, когда студент понимает семантику элемента и использует его по делу.
Например, можно нарисовать пунктирную стрелку между двумя овалами и подписать её include. Синтаксически это может выглядеть правдоподобно. Но если эта стрелка используется для показа следующего шага процесса, семантика нарушена. Для порядка действий нужна диаграмма деятельности или сценарий, а не include.
Абстрактный и конкретный синтаксис
Заголовок раздела «Абстрактный и конкретный синтаксис»В спецификации UML есть различие между абстрактным и конкретным синтаксисом.
Абстрактный синтаксис описывает, какие элементы существуют в модели и как они могут быть связаны. Это уровень метамодели. Там говорится, что есть Class, Actor, UseCase, Association, Dependency, ActivityNode, Lifeline и другие элементы.
Конкретный синтаксис описывает, как эти элементы можно показывать человеку. Класс обычно показывается прямоугольником с compartments. Actor можно показать “человечком”, а можно прямоугольником с ключевым словом «actor». Use case показывается овалом. Association — сплошной линией. Dependency — пунктирной стрелкой.
Это различие важно, потому что одна и та же семантика может иметь несколько допустимых вариантов нотации. Например, интерфейс можно показать отдельным прямоугольником с «interface», а можно lollipop-нотацией. Внешний вид разный, но модельный смысл связан с интерфейсом.
Бывает и обратная ситуация: похожая картинка не означает одинаковую семантику. Пунктирная стрелка может обозначать обычную dependency, include, extend, template binding, manifestation или deployment. Внешне отношения похожи, но в метамодели это разные вещи. Поэтому недостаточно сказать “там же пунктирная стрелка”. Нужно понимать, какое именно отношение стоит за этой стрелкой.
Почему UML-инструменты ведут себя странно
Заголовок раздела «Почему UML-инструменты ведут себя странно»Когда человек впервые работает с UML-инструментом, многие вещи кажутся неудобными. Почему нельзя просто нарисовать линию? Почему инструмент просит выбрать тип отношения? Почему одно переименование меняет элемент на нескольких диаграммах? Почему скрытие compartment не удаляет операции?
Ответ один: инструмент работает не только с картинкой, но и с моделью.
Если класс создан один раз и показан на нескольких диаграммах, переименование класса меняет сам элемент модели. Все его представления получают новое имя. Это нормальное поведение.
Если на диаграмме класса скрыть список операций, операции не исчезнут из модели. Они просто не отображаются на данном представлении. Это тоже нормально: одна диаграмма может показывать только предметные атрибуты, другая — технические операции, третья — связи между пакетами.
Если кратность ассоциации написана обычным текстом, инструмент может не понимать её как multiplicity. Если guard написан рядом со стрелкой как свободный комментарий, он может не быть свойством ребра. Визуально разница мала, но для модели она принципиальна.
Отдельный пример — экспорт. PNG или SVG сохраняет изображение. XMI сохраняет модельные элементы, свойства и связи. На практике XMI между разными инструментами переносится не идеально, но сама идея важна: UML-модель — это данные, а не только рисунок.
Как читать спецификацию UML
Заголовок раздела «Как читать спецификацию UML»Спецификацию UML не нужно читать подряд как учебник. Она для этого слишком большая и слишком формальная. Её полезнее использовать как справочник, когда возникает спорный вопрос.
Обычно разделы спецификации устроены предсказуемо. Сначала даётся обзор, потом абстрактный синтаксис, затем семантика, нотация, примеры и правила корректности. Если непонятно, как рисовать элемент, нужно смотреть notation. Если непонятно, что элемент означает, нужно смотреть semantics. Если непонятно, может ли один элемент быть связан с другим, нужно смотреть abstract syntax и well-formedness rules.
Например, если возник спор о направлении стрелки include, нужно смотреть раздел про Include, а не общую статью про use case diagrams. Если непонятно, является ли Node классификатором, нужно смотреть метамодель Node. Если непонятно, является ли «bind» реализацией, нужно смотреть TemplateBinding.
Такой способ чтения спецификации помогает не превращать UML в набор мнений. В спорной ситуации можно проверить: это действительно правило UML или просто привычка конкретного инструмента, автора учебника или команды.
Практические правила
Заголовок раздела «Практические правила»Раздел сводится к нескольким практическим правилам.
Во-первых, диаграмма — это представление модели, а не вся модель. Во-вторых, похожая линия не всегда означает одно и то же отношение. В-третьих, свойства UML-элементов нужно задавать как свойства модели, а не имитировать текстом. В-четвёртых, стереотип уточняет существующий элемент UML, но не отменяет его базовую семантику. В-пятых, constraint является частью модели, а не декоративным комментарием.
Если диаграмма выглядит красиво, но противоречит семантике UML, это плохая UML-модель. Если диаграмма выглядит проще, но корректно фиксирует элементы, отношения и ограничения, это обычно гораздо полезнее.
Как использовать этот раздел?
Заголовок раздела «Как использовать этот раздел?»Этот раздел помогает иначе посмотреть на разные UML-диаграммы.
Диаграмма использования — это не просто овалы и человечки, а модель акторов, субъектов и поведения, полезного заинтересованным лицам.
Диаграмма деятельности — это не просто блок-схема, а модель выполнения через токены.
Диаграмма классов — это не просто прямоугольники, а модель классификаторов, признаков, ассоциаций и ограничений.
Диаграмма последовательности — это не просто вызовы операций сверху вниз, а модель допустимых трасс взаимодействия.
Диаграмма развёртывания — это не просто схема серверов, а модель артефактов, узлов и отношений deployment.
Именно это отличает UML-модель от набора иллюстраций в презентации.