На этом шаге рассмотрим общие механизмы UML.
Применение языка UML существенно упрощает последовательное использование следующих механизмов.
Спецификации. UML – нечто большее, чем просто графический язык. За каждой частью его графической нотации стоит спецификация (specification), содержащая текстовое представление синтаксиса и семантики определенного строительного блока.
Например, пиктограмме класса соответствует спецификация, полностью описывающая набор его атрибутов, операций (включая их полные сигнатуры) и поведение, но визуально пиктограмма может отображать лишь малую часть этой спецификации. Более того, может существовать другое представление этого класса, отражающее совершенно другие его аспекты, тем не менее соответствующие все той же спецификации.
С помощью графической нотации UML вы визуализируете систему, с помощью спецификаций UML описываете ее детали. Таким образом, допускается последовательное построение модели – шаг за шагом, когда сначала рисуются диаграммы, а затем добавляется семантика к спецификациям модели, – или же напрямую, когда в первую очередь создаются спецификации (возможно, при выполнении обратного проектирования существующей системы), а затем рисуются диаграммы, представляющие их проекции.
Спецификации UML создают семантический задний план, который включает в себя все составные части всех моделей системы, согласованные между собой. Таким образом, диаграммы UML – это простые визуальные проекции на этот задний план, при этом каждая из них раскрывает некоторый существенный аспект системы.
Дополнения (adornments). Большинство элементов UML имеют уникальную и прямую графическую нотацию, которая дает визуальное представление наиболее важных аспектов элемента.
Например, обозначение класса разработано так, что его легко рисовать, потому что класс – это часто употребляемый элемент при моделировании объектно-ориентированных систем. Нотация класса также показывает его наиболее важные аспекты: имя, атрибуты и операции.
Спецификация класса может содержать и другие детали, такие как видимость атрибутов и операций. Многие из этих деталей могут изображаться в виде графических или текстовых дополнений к базовому прямоугольнику, представляющему класс. Например, рис. 1 демонстрирует класс, в обозначение которого включены дополнения, указывающие на то, что этот класс абстрактный, имеет две открытые, одну защищенную и одну закрытую операции.
Рис.1. Дополнения
Каждый элемент в нотации UML начинается с базового символа, к которому могут быть добавлены разнообразные специфичные для него дополнения.
Принятые разделения (common divisions). При моделировании объектно-ориентированных систем представление о предметной области может быть разделено несколькими способами.
Во-первых, существует разделение на классы и объекты. Класс представляет собой абстракцию, а объект – конкретную ее материализацию. В UML вы можете моделировать как классы, так и объекты (рис. 2). В графическом представлении объекта UML использует тот же символ, что и для его класса, но с подчеркиванием имени объекта.
Рис.2. Классы и объекты
На рис. 2 показан один класс Customer (Покупатель) вместе с тремя объектами: Jan (Джен), который помечен, как объект, явно являющийся объектом класса Customer, :Customer (анонимный объект класса Customer) и Elyse (Элиза), спецификация которого от носит его к классу Customer, хотя это не отображено явно.
Почти каждый строительный блок UML характеризуется подобной дихотомией "класс/объект". Например, существуют варианты использования и экземпляры вариантов использования, компоненты и экземпляры компонентов, узлы и экземпляры узлов и т.д.
Во-вторых, существует разделение интерфейса и реализации. Интерфейс определяет соглашение, а реализация представляет его конкретное воплощение и обязуется точно следовать полной семантике интерфейса. В UML вы можете моделировать как интерфейсы, так и их реализации (рис. 3).
Рис.3. Интерфейсы и реализации
На этом рисунке присутствует один компонент по имени SpellingWizard.dll (МастерПроверкиОрфографии.dll), который реализует два интерфейса – IUnknown (IНеизвестноеСлово) и Ispelling (IНаписание). Он также запрашивает интерфейс Idictionary (IСловарь), который должен быть предоставлен другим компонентом.
Почти каждый строительный блок UML обладает дихотомией "интерфейс/реализация". Например, варианты использования реализуются кооперациями, а операции – методами.
В-третьих, существует разделение на тип и роль. Тип декларирует класс сущности, например объект, атрибут или параметр. Роль описывает значение сущности внутри контекста, такого как класс, компонент или кооперация. Любая сущность, формирующая часть структуры другой сущности (к примеру, атрибут), обладает обеими характеристиками. Она наследует некоторый смысл от типа, которому принадлежит, а другой смысл – от его роли в данном контексте (рис. 4).
Рис.4. Часть с ролью и типом
Механизмы расширения (extensibility mechanisms). UML – это стандартный язык разработки "чертежей" программного обеспечения, но ни один замкнутый язык не может быть настолько выразительным, чтобы охватить все нюансы всех возможных моделей во всех областях применения в любое время. UML является открытым языком, который дает возможность вводить контролируемые расширения. Механизмы расширения UML включают: стереотипы, помеченные значения, ограничения.
Стереотип (stereotype) расширяет словарь UML, позволяя создавать новые виды строительных блоков, которые наследуются от существующих, но при этом специфичны для решения конкретной проблемы. Например, если вы работаете с языком программирования, таким как Java или C++, вам часто приходится моделировать исключения (exceptions). В этих языках исключения – это обычные классы, хотя и трактуемые особым образом. Обычно требуется, чтобы исключения можно было возбуждать и перехватывать, и ничего более. Вы можете пометить исключения соответствующим стереотипом, тем самым сделав их подобными базовым строительным блокам. На рис. 5 это показано на примере класса OverFlow.
Рис.5. Механизмы расширения
Помеченное значение (tagged value) расширяет свойства стереотипа UML, позволяя включать новую информацию в спецификацию стереотипа. Например, если вы работаете над "коробочным" продуктом и выпускаете много версий, вам часто приходится отслеживать версию и автора определенных важных абстракций. Ни версия, ни автор не являются примитивами UML. Они могут быть добавлены к любому строительному блоку, такому как класс, за счет введения в него новых помеченных значений. Так, например, на рис. 5 класс EventQueue расширяется явной пометкой его версии и автора.
Ограничения расширяют семантику строительного блока UML, позволяя добавлять новые правила или модифицировать существующие. Предположим, вам понадобилось ограничить класс EventQueue так, чтобы все события добавлялись в очередь по порядку. Как видно на рис. 5, для этого можно добавить ограничение, явно задающее такое правило для операции add.
Все эти три механизма расширения языка совместно позволяют модифицировать UML в соответствии с требованиями вашего проекта. Кроме того, они дают возможность адаптировать UML к новым программным технологиям, например к вероятному появлению более мощных языков распределенного программирования. Вы можете добавлять новые строительные блоки, модифицировать спецификацию существующих и даже изменять их семантику.
На следующем шаге рассмотрим моделирование системной архитектуры.