Что такое диаграмма классов uml
UML-диаграммы классов
UML – унифицированный язык моделирования (Unified Modeling Language) – это система обозначений, которую можно применять для объектно-ориентированного анализа и проектирования.
Его можно использовать для визуализации, спецификации, конструирования и документирования программных систем.
Словарь UML включает три вида строительных блоков:
Сущности – это абстракции, которые являются основными элементами модели, связи соединяют их между собой, а диаграммы группируют представляющие интерес наборы сущностей.
Диаграмма – это графическое представление набора элементов, чаще всего изображенного в виде связного графа вершин (сущностей) и путей (связей). Язык UML включает 13 видов диаграмм, среди которых на первом месте в списке — диаграмма классов, о которой и пойдет речь.
Диаграммы классов показывают набор классов, интерфейсов, а также их связи. Диаграммы этого вида чаще всего используются для моделирования объектно-ориентированных систем. Они предназначены для статического представления системы.
Большинство элементов UML имеют уникальную и прямую графическую нотацию, которая дает визуальное представление наиболее важных аспектов элемента.
Сущности
Диаграммы классов оперируют тремя видами сущностей UML:
Поведенческие сущности – динамические части моделей UML. Это «глаголы» моделей, представляющие поведение модели во времени и пространстве. Основной из них является взаимодействие – поведение, которое заключается в обмене сообщениями между наборами объектов или ролей в определенном контексте для достижения некоторой цели. Сообщение изображается в виде линии со стрелкой, почти всегда сопровождаемой именем операции.
Структурные сущности — классы
Класс – это описание набора объектов с одинаковыми атрибутами, операциями, связями и семантикой.
Графически класс изображается в виде прямоугольника, разделенного на 3 блока горизонтальными линиями:
Для атрибутов и операций может быть указан один из трех типов видимости:
Видимость для полей и методов указывается в виде левого символа в строке с именем соответствующего элемента.
Каждый класс должен обладать именем, отличающим его от других классов. Имя – это текстовая строка. Имя класса может состоять из любого числа букв, цифр и знаков препинания (за исключением двоеточия и точки) и может записываться в несколько строк.
На практике обычно используются краткие имена классов, взятые из словаря моделируемой системы. Каждое слово в имени класса традиционно пишут с заглавной буквы (верблюжья конвенция), например Sensor (Датчик) или TemperatureSensor (ДатчикТемпературы).
Для абстрактного класса имя класса записывается курсивом.
Атрибут (свойство) – это именованное свойство класса, описывающее диапазон значений, которые может принимать экземпляр атрибута. Класс может иметь любое число атрибутов или не иметь ни одного. В последнем случае блок атрибутов оставляют пустым.
Атрибут представляет некоторое свойство моделируемой сущности, которым обладают все объекты данного класса. Имя атрибута, как и имя класса, может представлять собой текст. На практике для именования атрибута используются одно или несколько коротких существительных, выражающих некое свойство класса, к которому относится атрибут.
Можно уточнить спецификацию атрибута, указав его тип, кратность (если атрибут представляет собой массив некоторых значений) и начальное значение по умолчанию.
Статические атрибуты класса обозначаются подчеркиванием.
Операция (метод) – это реализация метода класса. Класс может иметь любое число операций либо не иметь ни одной. Часто вызов операции объекта изменяет его атрибуты.
Графически операции представлены в нижнем блоке описания класса.
Допускается указание только имен операций. Имя операции, как и имя класса, должно представлять собой текст. На практике для именования операции используются короткие глагольные конструкции, описывающие некое поведение класса, которому принадлежит операция. Обычно каждое слово в имени операции пишется с заглавной буквы, за исключением первого, например move (переместить) или isEmpty (проверка на пустоту).
Можно специфицировать операцию, устанавливая ее сигнатуру, включающую имя, тип и значение по умолчанию всех параметров, а применительно к функциям – тип возвращаемого значения.
Абстрактные методы класса обозначаются курсивным шрифтом.
Статические методы класса обозначаются подчеркиванием.
Изображая класс, не обязательно показывать сразу все его атрибуты и операции. Для конкретного представления, как правило, существенна только часть атрибутов и операций класса. В силу этих причин допускается упрощенное представление класса, то есть для графического представления выбираются только некоторые из его атрибутов. Если помимо указанных существуют другие атрибуты и операции, вы даете это понять, завершая каждый список многоточием.
Чтобы легче воспринимать длинные списки атрибутов и операций, желательно снабдить префиксом (именем стереотипа) каждую категорию в них. В данном случае стереотип – это слово, заключенное в угловые кавычки, которое указывает то, что за ним следует.
Отношения между классами
Существует четыре типа связей в UML:
Эти связи представляют собой базовые строительные блоки для описания отношений в UML, используемые для разработки хорошо согласованных моделей.
Первая из них – зависимость – семантически представляет собой связь между двумя элементами модели, в которой изменение одного элемента (независимого) может привести к изменению семантики другого элемента (зависимого). Графически представлена пунктирной линией, иногда со стрелкой, направленной к той сущности, от которой зависит еще одна; может быть снабжена меткой.
Ассоциация – это структурная связь между элементами модели, которая описывает набор связей, существующих между объектами.
Ассоциация показывает, что объекты одной сущности (класса) связаны с объектами другой сущности таким образом, что можно перемещаться от объектов одного класса к другому.
Например, класс Человек и класс Школа имеют ассоциацию, так как человек может учиться в школе. Ассоциации можно присвоить имя «учится в». В представлении однонаправленной ассоциации добавляется стрелка, указывающая на направление ассоциации.
Двойные ассоциации представляются линией без стрелок на концах, соединяющей два классовых блока.
Ассоциация может быть именованной, и тогда на концах представляющей её линии будут подписаны роли, принадлежности, индикаторы, мультипликаторы, видимости или другие свойства.
Пример кода и диаграммы классов для него
Программа получает данные с датчика температуры (вводятся с консоли) — по 5 измерений для каждого из двух объектов класса TemperatureMeasure и усредняет их. Также предусмотрен класс ShowMeasure для вывода измеренных значений.
UML для самых маленьких: диаграмма классов
Аве, Кодер! Диаграмма классов UML иллюстрирует структуру системы, описывая классы, их атрибуты, методы и отношения между объектами.
Даже самые малые детки знают, что UML происходит от Unified Modeling Language, если по- русски, то — унифицированный язык моделирования, который, как гласит легенда, разработали, когда серьезные дяди и тети в конец задолбались плавать в разнообразии кружочков, черточек и облачков.
Для тех, кому лень читать:
Главное действующее лицо
Для начала напомним себе что такое класс? Если в двух словах, то класс представляет собой шаблон для создания объектов, обеспечивающий начальные значения состояний: инициализацию полей-переменных и реализацию поведения полей и методов.
По сути, класс описывает то, каким объект может быть.
Класс представляет концепт, который описывает состояние (атрибуты) и поведение (методы). Каждый атрибут имеет свой тип, каждый метод — свою сигнатуру, но в диаграмме классов только имя класса является обязательной информацией к заполнению, что и логично — даже лучшие экстрасенсы мира не смогут понять, что это за безымянный квадрат и к чему он вообще относится.
Имя класса пишется в самом верхнем делении, затем идут атрибуты класса, типы которых записываются после двоеточия и, наконец, в нижнем делении идут методы.
Тип, который может возвращать метод, записывается после двоеточия в самом конце сигнатуры метода. Модификаторы области видимости изображены перед атрибутами класса и методами.
Каждый параметр в методе может также иметь описание направленности метода: in, out, inout.
На этой иллюстрации, method1 использует p1, как входной параметр и значение p1, каким-то образом, используется методом, а метод не изменяет p1.
Method2 принимает p2, как параметр ввода/вывода, значение p2, каким-то образом, используется методом и принимает выходное значение метода, но сам метод также может изменять p2.
Method3 использует p3, как выходной параметр, иными словами, параметр служит хранилищем для выходного значение метода.
Перспективы диаграммы классов в жизненном цикле разработки программного обеспечения
Мы можем использовать диаграммы классов на разных этапах жизненного цикла разработки программного обеспечения и, как правило, постепенно моделируя диаграммы классов с трех разных точек зрения по мере нашего продвижения по уровням детализации.
Концептуальная перспектива — это когда диаграммы интерпретируются как описание вещей в реальном мире. Таким образом, если мы берем концептуальную перспективу, мы рисуем диаграмму, которая представляет концепции в изучаемой области. Эти концепции относятся к классам, которые их реализуют. Концептуальная перспектива считается независимой от языка.
Спецификационная перспектива — это когда диаграммы интерпретируются, как описание абстракций программного обеспечения или компонентов со спецификациями и интерфейсами, но без привязки к конкретной реализации.
Имплементационная перспектива — это когда диаграммы интерпретируются, как описание реализаций программного обеспечения на определенной технологии и языке.
Таким образом, если ты берешь имплементационную перспективу, ты смотришь на реализацию программного обеспечения.
Типы отношений
Далее, я приведу шесть основных типов обозначений отношений между классами, которые встречаются в UML схемах чаще всего.
Ассоциация.
Аналогично связям, соединяющим объекты, ассоциации соединяют классы. Для того, чтобы между объектами была связь, между ними должна быть ассоциация.
Если предположить, что у нас есть два класса, которые взаимодействуют друг с другом, между ними должна быть проведена непрерывная соединительная линия, обозначающая на схеме ассоциацию. Часто мы также можем увидеть глагол, передающий ее смысл.
Помимо этого, мы также можем указать кратность, то есть число объектов, которые могут принимать участие в отношениях. Кратность задается в виде разделенного запятыми списка интервалов, в котором каждый интервал представлен в виде минимум-максимум.
Например, один студент может учиться у множества преподавателей.
Но и преподаватель может учить множество студентов.
Или иногда его еще называют — генерализация.
Как следует из названия, это схематическое изображение отношения между родительским классом и его наследниками. Полая стрелка всегда направлена к классу «родитель».
Классический пример наследования: классы квадрат, прямоугольник и круг, которые являются наследниками родительского класса «фигура».
Мы вправе изображать наследование как отдельно для каждого класса, так и объединять их.
Если наследование происходит от абстрактного класса, то имя такого родительского класса записывается курсивом.
Обычно, под этим подразумевается отношение интерфейса и объектов, реализующих этот интерфейс.
Например, интерфейс Owner имеет методы для покупки и продажи частной собственности, а отношения классов Person и Corporation, реализующих этот интерфейс, на диаграмме будут обозначаться в виде пунктирной линии со стрелкой по направлению к интерфейсу.
Объект одного класса может использовать объект другого класса в своем методе.
Если объект не хранится в поле класса, то такой вид межклассовых отношений моделируется как зависимость.
Зависимость, по сути, является специальным случаем ассоциации двух классов, в этом случае, изменения в одном классе неумолимо повлекут за собой изменения в другом.
Например, у класса Person есть метод hasRead с входным параметром book, который возвращает true, если, к примеру, человек прочитал книгу.
Зависимость обозначается пунктирной линией со стрелкой, обращенной к классу, от которого зависят, например, методы другого класса.
Особый тип отношений между классами, когда один класс является частью другого.
Например, рабочее место программиста состоит из стула, стола, компьютера и вентилятора, но при удалении класса «рабочее место», у нас просто останутся все эти классы, только по отдельности.
Агрегация показана в виде непрерывной линии с полым ромбом направленным от классов, являющимися частью какого-либо класса к классу-агрегатору.
По сути, разновидность агрегации, только в этом случае, классы, являющиеся частью другого класса, уничтожают, когда уничтожается класс-агрегатор.
Например наше тело состоит из органов, но сами по себе они не жизнеспособны.
Композиция обозначается схожим с агрегацией способом, но ромб на этот раз полностью закрашен.
Финалочка
UML бывает очень полезен для новичков, находящихся на этапе понимания «что к чему долждно идти и от чего наследоваться». Как говорят наши англоязычные коллеги: «он помогает увидеть как выглядит весь лес за стволами деревьев».
Поэтому, перед началом твоего, пусть и небольшого, но сногсшибательного проекта, не хватайся сразу за код. Создай сперва архитектуру своего приложения в UML.
Использование диаграммы классов UML при проектировании и документировании программного обеспечения
Предисловие
Парадигма объектно-ориентированного программирования (далее просто ООП) повсеместно используется при создании современного программного обеспечения. Модель объектов, заложенная в данную парадигму, способна достаточно точно описывать свойства и возможности сущностей реального мира. Разумеется, эти объекты не существуют обособленно друг от друга, они взаимодействуют друг с другом для достижения какой-то глобальной цели разрабатываемой системы.
Стандартная библиотека некоторого языка программирования – замечательный сборник полезных утилит. Однако разнообразие решаемых программистами задач так велико, что одной только стандартной библиотекой ограничиться не получится. Программисту часто приходится самому создавать необходимый ему набор функциональности. Это можно сделать, создав пакет функций или набор классов.
Создание собственных классов при разработке программы добавляет в проект новый уровень абстракции, который позволяет определить некоторый функционал системы и работать в дальнейшем только с ним.
Чем выше уровень абстракции, которым пользуется программист, тем выше уровень его продуктивности при разработке приложения.
Использование ООП может существенно упросить жизнь программисту. Это достигается за счёт сокрытия особенностей внутренней реализации классов. Программисту остаётся лишь пользоваться её удобствами. Кажется, что ООП – панацея от всех проблем. Однако на практике, если не иметь чёткого представления о том, какие классы нужно реализовать и как ими потом пользоваться, в результате может получиться очень запутанная система, которая начнёт порождать спагетти-коду (от англ. “spaghetti code”), который будет лишь мешаться, когда вы захотите добавить что-то новое в систему.
Чтобы избежать большинства проблем, возникающих при использовании ООП, нужно:
Иметь некоторый опыт создания программ и использования классов.
Строить структурные диаграммы классов.
Первое придёт со временем, а со вторым я могу вас познакомить прямо сейчас. Сегодня мы разберём диаграмму классов UML.
Диаграммы классов UML
Введение и содержание
Диаграмма классов занимает центральное место в проектировании объектно-ориентированной системы. Нотация классов используется на разных этапах проектирования и строится с различной степенью детализации. Язык UML применяется не только для проектирования, но и с целью документирования, а также эскизирования проекта. Я (в отличии от Гради Буча) не являюсь сторонником разработки проекта с использованием всех видов UML диаграмм, а также детального проектирования. Чаще всего я применяю UML для эскизирования, а также для проектирования по процессу ICONIX [Rosenberg]. В статье описана часть нотации классов UML, применение которой достаточно в большинстве случаев. Тут не будет информации о кратности ассоциаций и атрибутов, особенностях изображения параллельных операций, шаблонах (параметризованных классах) и ограничениях. При необходимости всю эту информации можно посмотреть в других книгах [Buch, Leonenkov]. Мы же ограничимся базовой частью нотации и больше внимания уделим применению диаграммы классов.
1 Элементы диаграммы классов
На диаграмме классов с помощью специальных символов изображаются типы данных программы и отношения между ними, хотя в некоторых случаях могут использоваться и некоторые другие элементы — пакеты и даже экземпляры классов (объекты) [Leonenkov].
1.1 Символ класса
Символ класса на диаграмме может выглядеть различным образом в зависимости от детализации диаграммы:
Формат спецификации атрибута:
видимость имя : тип [кратность] = значение_по_умолчанию
Формат спецификации операции:
видимость имя(аргумент: тип) = тип_возвращаемого_значения
В зависимости от параметра видимости элемент может быть:
Виртуальная функция и имя абстрактного класса выделяются курсивом, а статическая функция — подчеркивается.
1.2 Отношения классов
Диаграмма классов допускает различные виды отношений, рассмотрим их на части диаграммы модели некоторой игры:
Другой вид отношений между классами — включение, в объектно-ориентированном программировании различают два вида этого отношения — композицию и агрегацию. Напомню, что композиция — это разновидность включения, когда объекты неразрывно связаны друг с другом (время их жизни совпадает), в случае агрегации, время жизни различно (например, когда объект вложенного класса может быть заменен другим объектом во время выполнения программы).
Шаблон проектирования Delegation (и все его разновидности) — хороший пример для демонстрации агрегации. В нашем случае состояние игрока может меняться за счет изменения объекта по указателю, т.е. время жизни объектов различается.
Очевидно, что не все виды отношений стоит отображать на диаграмме и одни отношения могут быть заменены другими. Так, я убрал бы из нашего примера отношения зависимости, однако при некоторых обстоятельствах (например при эскизировании на маркерной доске) они были бы вполне уместны. Расстановка кратности и имен связей тоже выполняется далеко не во всех случаях. Вообще, не стоит помещать на диаграмму лишнюю информацию. Главное — диаграмма должна быть наглядной.
2 Использование диаграммы классов
Мы рассмотрели основные обозначения, используемые на диаграммах классов — их должно быть достаточно в подавляющем большинстве случаев. По крайней мере, владея этим материалом вы легко сможете разобраться в диаграммах шаблонов проектирования и понять эскиз любого проекта. Однако, как правильно строить такие диаграммы? В каком порядке и с какой степенью детализации? — ответ зависит от целей построения диаграммы, поэтому приведенный материал будет разбит на подразделы в соответствии с целями моделирования.
Стоит отметить, что у Гради Буча советы по использованию UML даны в книге «Руководство пользователя» [Buch_Rambo], но в его «Объектно-ориементированном анализе» [Buch] можно найти хорошие примеры и критерии качества проекта. Леоненков [Leonenkov] и вовсе избегает этой темы, оставляя лишь ссылки на литературу, конкретные рекомендации я нашел у Лармана [Larman] и Розенберга [Rosenberg], часть материала основана на моем личном опыте. Фаулер рассматривает UML как средство эскизирования, поэтому у него свой (сильно отличающийся от Буча и Розенберга) взгляд на диаграмму классов [Fauler].
2.1 Диаграмма классов как словарь системы, концептуальная модель
Словарь системы формируется параллельно с разработкой диаграммы прецедентов, т.е. технического задания. Выглядит это следующим образом — вы задаете заказчику вопросы типа «что еще может сделать пользователь?», «что произойдет (должна выдать система) если пользователь сделает нажмет на кнопку?», а ответы на них записываете в виде описания прецедентов. Однако, заказчик, давая ответы может называть одни и те же вещи разными именами — из личного опыта: говоря «клетка», «пересечение», «узел» и «ячейка» заказчик может иметь ввиду одно и тоже. В вашей же системе все эти понятия должны быть представлены одной абстракцией (классом/функцией/…). Для этого при общении с заказчиком стоит фиксировать терминологию в виде словаря системы — очень хорошо с этим справляется диаграмма классов.
Гради Буч для построения словаря системы предлагает выполнять в следующем порядке [BuchRambo]:
В качестве примера рассмотрим словарь системы для игры «Сапер». На приведенной ниже диаграмме показан вариант, который получился в результате обсуждения задачи у моего студента. Видно, что на диаграмме изображены сущности и их атрибуты, понятные для заказчика, эту диаграмму стоит иметь перед глазами при составлении прецедентов чтобы не называть «Клетку» — «Полем», вводя всех в заблуждение. При построении словаря системы следует избегать нанесения на диаграмму функций классов, т.к. настолько детализированное распределение обязанностей лучше выполнять после построения диаграмм взаимодействия.
В процессе проектирования словарь системы может дополняться, Розенберг очень хорошо демонстрирует это в своей книге описывая итеративный процесс проектирования ICONIX [Rosenberg]. Например, после рассмотрения нескольких прецедентов может оказаться, что несколько классов реализуют один и тот же функционал — для решения проблемы надо более четко прописать обязанности каждого класса, возможно, добавить новый класс и перенести часть этих обязанностей ему.
2.2 Диаграмма классов уровня проектирования
В любом объектно-ориентированном процессе проектирования диаграмма классов является результатом, т.к. является моделью, наиболее близкой к реализации (коду). Существуют инструменты, способные преобразовать диаграмму классов в код — такой процесс называется кодогенерацией и поддерживается множеством IDE и средств проектирования. Например, кодогенерацию выполняет Visual Paradigm (доступно в виде плагинов для множества IDE), новые версии Microsoft Visual Studio, такие средств UML-моделирования как StarUML, ArgoUML и др. Чтобы построить по диаграмме хороший код, она должна быть достаточно подробной. Именно о такой диаграмме идет речь в этом разделе.
До Ларману [Larman] до начала построения диаграммы классов уровня проектирования должны быть построены диаграммы взаимодействия и концептуальная модель системы. При этом порядок построения диаграммы следующий:
Отношения, добавляемые на диаграмму классов уровня проектирования отличаются от тех, что были в концептуальной модели тем, что они могут быть не очевидны для заказчика (эту диаграмму он вообще смотреть не должен — она разрабатывается для программистов). Если на этапе анализа технического задания мы могли выделить основные сущности, не задумываясь о том, как это будет реализовано, то теперь обязанности между нашими классами должны быть окончательно распределены.
Пример выше утрированный и однозначно не является образцом хорошего проектирования — на класс PlayingGround возложено слишком много обязанностей, но могли ли мы учесть это при анализе технического задания? Сможем ли мы это сделать до разработки диаграмм взаимодействия для проекта любой сложности? — именно поэтому построение диаграммы классов является последним этапом проектирования.
2.3 Диаграмма классов для эскизирования, документирования
Под эскизированием понимают моделирование некоторой (интересной нам в данный момент) части системы. Например, эскизирование может выполняться на маркерной доске когда в вашу компанию попадет новый сотрудник и вы будете помогать ему «влиться» в существующий проект. Очевидно, что если если дать человеку диаграмму классов уровня проектирования — разбираться он будет долго. Суть эскизирования в избирательности — вы выносите на диаграмму только те элементы, которые важны для пояснения того или иного механизма.
Сторонником применения UML для эскизирования является Фаулер [Fauler], который считает, что целостный процесс проектирования с использованием UML слишком сложен. Эскизирование применяется очень часто (не только при объяснении проекта на маркерной доске):
Каких-либо конкретных рекомендаций к эскизам диаграмм классов предложить невозможно, кроме того, обычно это достаточно простая задача. Важно понимать суть — избирательность представления элементов снижает сложность восприятия диаграммы.
2.4 Диаграмма классов для моделирования БД
Частным случаем диаграммы классов является диаграмма «сущность-связь» (E-R диаграмма), используемая для моделирования логической схемы базы данных. В отличии от классических E-R диаграмм, диаграмма классов позволяет моделировать поведение (триггеры и хранимые процедуры).
Обычно ситуация выглядит следующим образом — вы разработали систему, состояние которой нужно сохранять между запусками, например:
Хранимые между запусками данные должны каким-то образом загружаться по запросу пользователя, т.е. должны задаваться параметры соответствующих классов. Например, приложение должно получить из базы данных список треков (маршрутов) и отобразить его в виде списка в меню программы. При выборе элемента списка — запросить в БД параметры трека, создать объект трека и отобразить его на карте. В любом случае, данные с базы используются при инициализации объектов программы — это важно понимать.
Для моделирования схемы БД с помощью диаграммы классов нужно [Buch_Rambo]:
Заключение и список литературы
В статье я постарался описать наиболее существенные элементы диаграммы классов, а также аспекты их применения. Просматривается, что диаграмма строится на начальном этапе проектирования (концептуальная модель) и является его результатом. На всех этапах проектирования созданная в начале диаграмма классов дорабатывается, т.е. я рассматриваю итеративный процесс (такой как RUP или ICONIX). Кроме того, показано, использование диаграммы классов в других целях — эскизирования, документирования, моделирования логической схемы БД. На других страницах этого блога вы можете найти множество примеров использования диаграммы классов.