Как составить диаграмму классов uml

Предисловие

Парадигма объектно-ориентированного программирования (далее просто ООП) повсеместно используется при создании современного программного обеспечения. Модель объектов, заложенная в данную парадигму, способна достаточно точно описывать свойства и возможности сущностей реального мира. Разумеется, эти объекты не существуют обособленно друг от друга, они взаимодействуют друг с другом для достижения какой-то глобальной цели разрабатываемой системы.

Стандартная библиотека некоторого языка программирования – замечательный сборник полезных утилит. Однако разнообразие решаемых программистами задач так велико, что одной только стандартной библиотекой ограничиться не получится. Программисту часто приходится самому создавать необходимый ему набор функциональности. Это можно сделать, создав пакет функций или набор классов.

Создание собственных классов при разработке программы добавляет в проект новый уровень абстракции, который позволяет определить некоторый функционал системы и работать в дальнейшем только с ним.

Чем выше уровень абстракции, которым пользуется программист, тем выше уровень его продуктивности при разработке приложения.

Чем выше уровень абстракции, которым пользуется программист, тем выше уровень его продуктивности при разработке приложения.

«Хорошая абстракция превращает практически неподъемную задачу в две, решить которые вполне по силам. Первая из этих задач состоит в определении и реализации абстракции, а вторая — в использовании этих абстракций для решения текущей проблемы.»

Э.С. Таненбаум

Использование ООП может существенно упросить жизнь программисту. Это достигается за счёт сокрытия особенностей внутренней реализации классов. Программисту остаётся лишь пользоваться её удобствами. Кажется, что ООП – панацея от всех проблем. Однако на практике, если не иметь чёткого представления о том, какие классы нужно реализовать и как ими потом пользоваться, в результате может получиться очень запутанная система, которая начнёт порождать спагетти-коду (от англ. “spaghetti code”), который будет лишь мешаться, когда вы захотите добавить что-то новое в систему.

Чтобы избежать большинства проблем, возникающих при использовании ООП, нужно:

  1. Иметь некоторый опыт создания программ и использования классов.

  2. Строить структурные диаграммы классов.

Первое придёт со временем, а со вторым я могу вас познакомить прямо сейчас. Сегодня мы разберём диаграмму классов UML.


Содержание

  1. Назначение диаграммы классов

  2. Постановка задачи и её анализ

  3. Класс

    1. Статический класс

    2. Абстрактный класс

  4. Поля класса

    1. Уровень видимости

    2. Идентификатор

    3. Тип поля

    4. Кратность

  5. Методы класса

  6. Классы, отвечающие за графику

  7. Виды отношений

    1. Отношение ассоциации

    2. Отношение зависимости

    3. Отношение наследования

    4. Отношение агрегации

    5. Отношение композиции

Назначение диаграммы классов

Диаграмма классов (от англ. «class diagram») предназначена для представления внутренней структуры программы в виде классов и связей между ними. 

Все сущности реального мира, с которыми собирается работать программист, должны быть представлены объектами классов в программе. При этом у каждого класса должно быть только одно назначение и уникально осмысленное имя, которое будет связано с этой целью.

Взаимосвязь диаграммы классов с другими диаграммами

Диаграмма классов UML тесно связана с другими диаграммами, поскольку в них используются экземпляры классов (объекты), описанные на диаграмме классов. Например, на диаграмме кооперации (англ. «cooperation diagram») показывается структурные связи при взаимодействии объектов, а на диаграмме последовательности (англ. «sequence diagram») изображается последовательность обмена сообщений между объектами.

Постановка задачи и её анализ

Представьте, что мы хотим разработать программу для построения графиков функций.  Давайте кратко изобразим основной функционал такой программы на диаграмме вариантов использования UML:

Зачем нужен вариант использования «построить график функции»

В своей программе я сделал ставку на то, что пользователь захочет сначала задать все функции, с которыми он захочет работать, а только после этого строить те, которые ему нужны в данный момент.

Разумеется, мы хотим, чтобы наше приложение обладало графическим интерфейсом. На данном этапе разумно будет разбить задачу построения диаграммы на две части:

  1. Построить диаграмму для классов, ответственных за работу с пользовательскими математическими функциями.

  2. Построить диаграмму для классов, ответственных за корректное отображение графических элементов в программе.

Зачем плодить множество диаграмм, когда можно сделать одну большую?

Диаграмма классов строится прежде всего для внесения ясности в будущий процесс разработки системы. На первый взгляд, удобно всё классы построить на одной диаграмме, однако это может вызвать путаницу у читателей диаграммы, так как деталей будет слишком много.

Более правильным подходом станет выделение групп классов под различные задачи. Для каждой такой группы можно будет строить свою диаграмму. Чем меньше программисту нужно знать деталей для работы с какой-то частью программы, тем быстрее он сможет решить задачу.

Впоследствии можно построить упрощённую диаграмму для отображения взаимосвязей между классами из разных диаграмм.

Классы, ответственные за работу с математическими функциями будут предоставлять возможность создавать объекты математических функций и подсчитывать таблицу значений.

Давайте определимся с тем, как мы собираемся работать с функциями. Во-первых, договоримся, что мы будем работать не напрямую с функциями, а только с их телами.

Именно поэтому в этой статье мы будем оперировать термином математическое выражение, а не термином функция.

Компьютер не может оперировать напрямую математическими выражениями, записанными в строке так же просто, как и обычными числами, записанными в коде программы.

Поэтому мы создадим набор классов, которые будут «знать», как работать с такими данными. Упрощённая схема создания математических выражений представлена на рисунке ниже.

Для того чтобы мы могли работать с телом функции, записанным в виде строки, необходимо разбить эту строку на элементарные части. Их чаще всего называют лексемами (от англ. «lexeme») или токенами (от англ. «token»). В данной статье мы будем использовать термин токен. Получить список токенов математического выражения можно, используя алгоритм сортировочной станции.

Затем из полученного списка токенов мы будем строить постфиксную запись выражения.

На этом этапе математическое выражение мы будем считать обработанным и готовым к работе. Чтобы вычислить значение этого выражения, мы будем подставлять вместе переменной какое-либо действительное значение.

Для удобства работы с нашим приложением нужно добавить возможность определения и использования именованных констант. Например, использование распространённых математических констант, таких как π = 3,141592.. или e = 2,71828.. будет очень удобным для пользователей.

В заключение, хочется отметить, что каждое серьёзной программе необходим механизм обработки ошибок. Наша программа не будет исключением. Пользовательские выражения будут проверяться на корректность математической записи.

Соглашение об именовании объектов и классов

Несмотря на то, что данную статью я пишу на русском языке, на диаграммах мы всё будем описывать на английском языке. Для этого есть две причины:

  1. Когда вы начнёте реализовывать классы, описанные на диаграмме, в коде, вы будете давать им название на английском языке. Разные программисты по-разному могут перевести одно и то же слово. Например, класс «МатематическоеВыражение» некоторые могут перевести как «MathExpression», другие, исходя из специфика задачи, как «Function» или просто как «Expression». Таким образом, когда вы начнёте сопоставлять написанные классы с элементами на диаграмме, вы можете запутаться.

  2. Технический английский язык обычно более ёмок, чем русский. Это позволит сократить объём текста на диаграмме.

Давайте подведём итог и выясним, какие классы нам будут нужны для решения поставленной задачи:

  • Класс для хранения математического выражения. Назовём его MathExpression.

  • Класс для разбиения строкового представления выражения на список токенов — MathParser.

  • Класс для построения постфиксной формы выражения из списка токенов — MathFormConverter.

  • Класс для работы с именованными константами — MathConstantManager.

  • Класс для проверки корректности пользовательского математического выражения — MathChecker.

  • Класс для подсчёта таблицы значений математического выражения — MathCalculator.

Почему все имена классов имеют префикс Math?*

Когда я разрабатывал это приложения, я решил, что некоторый функционал системы можно повторно использовать в других проектах. Следовательно, было бы полезно выделить эти функции в отдельную библиотеку. Чтобы подчеркнуть, что этот набор функций взаимосвязан, я и добавил в их имена префикс Math.

Более правильным решением было бы вынести все эти классы в пространство имён Math и убрать префикс из имён. Однако продолжим работать с нашим Legacy-кодом.

Класс

Класс — элемент диаграммы, обозначающий множество объектов, обладающих одинаковой внутренней структурой, поведением и отношениями с объектами других классов. Изображается класс на диаграмме в виде прямоугольника, разделённого на три секции:

  1. Имя класса

  2. Список полей класса

  3. Список методов класса

Выбор терминологии

В различной технической литературе вы можете встретить альтернативные названия для этих терминов:

  1. Поля (от англ. “field”) <=> свойства (от англ. “properties”), атрибуты (от англ. “attributes”)

  2. Методы (от англ. “method”) <=> функции (от англ. “functions”), операции (от англ. “operations”)

В данной статье мы будем использовать термины поле для внутренних переменных класса и метод для функций, которые являются частью класса. Тем не менее, имейте в виду, что в разных источниках могут встречаться другие термины, обозначающие то же самое.

Обязательным элементом класса является только его название.

Обязательным элементом класса является только его название.

Оранжевым цветом мы будем выделять обязательные части элементов.

Пример класса "Покупатель". У покупателя есть баланс (balance) денег и список желаемого (wishList). Пользователь может пополнять баланс на некоторую сумму денег (topUpBalance()), может совершать покупки (makePurchase()) и может добавлять товары в список желаемого (appendToWishList()). Также мы можем проверить, подтверждена ли электронная почта пользователя.

Пример класса «Покупатель». У покупателя есть баланс (balance) денег и список желаемого (wishList). Пользователь может пополнять баланс на некоторую сумму денег (topUpBalance()), может совершать покупки (makePurchase()) и может добавлять товары в список желаемого (appendToWishList()). Также мы можем проверить, подтверждена ли электронная почта пользователя.

Обычно в качестве имени класса выбирается существительное в единственном числе. Разумеется, это имя должно быть уникальным в пределах диаграммы. Если имя класса состоит из нескольких слов, мы ,по практическим соображениям, будем записывать их слитно в верблюжьем стиле (от англ. «CamelCase»).

Рекомендация по именованию классов

Определение класса схоже с определением актёра в том смысле, что оба эти элемента обозначают группу объектов и пользователей соответственно. В связи с этим оба эти элемента должны именоваться существительным в единственном числе.

Настало время изобразить наши классы на диаграмме. Пока что давайте изобразим только имена этих классов.

Первая версия диаграмма классов, которые отвечают за работу
с математическими выражениями.

Первая версия диаграмма классов, которые отвечают за работу
с математическими выражениями.

Пока что эта диаграмма не даёт никакого понимания того, как будет устроена наша система, однако к концу статьи диаграмма значительно преобразится.

Статический класс

Класс, в котором есть только статические поля и методы и на основе которого не создаются объекты,  называется статическим классом. Чтобы показать на диаграмме, что наш класс статический, нужно добавить к имени модификатор «utility».

Формально, такие модификаторы называется стереотипами. Стереотип – именованный набор свойств. В данном случае, стереотип «utility» означает, что объекты указанного класса не создаются.

По сути, название модификатора «utility» связано с тем, статический класс предоставляет набор утилит, которые могут быть использованы любыми классами, которые в них нуждаются.

В нашей системе классы MathParser, MathFormConverter, MathConstantManager являются статическими, потому что они представляют собой «сборник» полезных функций, которые мы объединили в класс. Давайте изобразим это на нашей диаграмме.

2 версия диаграммы

2 версия диаграммы

Абстрактный класс

Класс, который является базовым для других классов и объекты которого мы не собираемся создавать, называют абстрактным. Абстрактный класс на диаграмме изображается так же, как и обычной класс, однако имя такого класса должно быть записано курсивом.

В UML принято соглашение, согласно которому все элементы, относящиеся к абстрактному классу, должны быть помечены курсивом (жирный шрифт при этом сохраняется).

Поля класса

Вернёмся к нашему примеру с классом Customer. Обратите внимание на центральную секцию.

Давайте рассмотрим первую строчку. Что вообще означает запись «- balance: Integer»? Сейчас будем разбираться.

В общем случае, каждое поле класса должно описываться следующим образом:

Общий вид поля класса

Общий вид поля класса

Нами в данной статье не будет рассмотрено использование свойств в полях класса, поскольку это достаточно специфичная тема.

Уровень видимости

Уровень видимости (от англ. «visibility») — свойство поля, которое показывает, из какой части программы можно обратиться к данному полю.

В нашем случае, поле balance - закрытое

В нашем случае, поле balance — закрытое

Обычно может принимать следующие значения:

  • «+» — открытое поле. Аналог public в языках программирования. Означает, что к полю можно обратиться из любой части программы.

  • «-» — закрытое поле. Аналог private в языках программирования. Означает, что получить доступ к полю можно только внутри класса.

  • «#» — защищённое поле. Аналог protected в языках программирования. Означает, что получить доступ к полю можно внутри класса и внутри производных классов.

Может показаться, что как-то неудобно для каждого поля указывать его уровень видимости. Почему бы не группировать поля по уровню видимости? Например, именно такой подход используется в языке программирования C++. Давайте попробуем напрямую использовать ключевые слова public, private и protected.

Несмотря на удобство такого подхода, мы будем указывать уровень видимости для каждого элемента.

А что будет, если не указывать уровень видимости вовсе?*

В некоторых языках программирования, к примеру, в C++ или C# отсутствие уровня видимости поля или метода по умолчанию означает, что такой элемент считается закрытым. Тем не менее, обычно уровень видимости указывается для каждого поля, чтобы код становился более читабельным.

В UML, если уровень видимости не указан, то никакого значения по умолчанию не подразумевается. Таким образом, в данной статье мы всегда будем указывать уровень видимости для наших элементов.

Идентификатор

Идентификатор (от англ. «identificator») — название поля. Является обязательным элементом для описания переменной на диаграмме классов, поскольку однозначно её определяет (все идентификаторы на диаграммах уникальны).

Тип поля

Тип поля (англ. «type of field») показывает, какой тип имеет данное поле в нашей программе. На ранней стадии проектирования можно и не уточнять, какой тип имеет то или иное поле.

Типы полей обычно привязаны к какому-то конкретному языку программирования, например. Кроме того, в качестве типа поля может быть использован пользовательский тип данных.

Кратность

Кратность (от англ. «multiplicity») – интервал, определяющий диапазон количества элементов в массиве. Если для поля указана кратность, то его следует считать массивом. Количество элементов в таком массиве и будет определяться указанным интервалом.

Список желаемого - это массив, который может либо быть пустым, либо может хранить неограниченное число товаров.

Список желаемого — это массив, который может либо быть пустым, либо может хранить неограниченное число товаров.
Пояснение к использованию кратности

Multiplicity is a definition of an inclusive interval of non-negative integers to specify the allowable number of instances of described element.

Кратность определяет отрезок с неотрицательными целочисленными границами, который показывает допустимое количество объектов определённого типа.

“Кратность, если она присутствует, определяет данный атрибут как массив (определенной или неопределенной длины).”

Учебно-методическое пособие по дисциплине «Анализ и проектирование на UML». ИТМО.

Тем не менее, использование кратность уходит на второй план, поскольку в современных системах используют более сложные коллекции — списки, очереди, деревья.

Для кратности указывают одно или два значения:

  • [m..n] — интервал от m до n включительно (m <= n). Такая запись будет означать, что в коллекции может храниться от m до n значений включительно.

  • [n] – интервал, который можно рассматривать, как сокращённую запись [0..n].

Может случиться так, что мы захотим показать, что в массиве может храниться неограниченное количество элементов. В таком случае верхняя граница n заменяется символом *.

Примеры интервалов:

  • [1] — ровно один объект. То же самое, что и интервал [1..1]

  • [0..1] — ноль или один объект.

  • [0..*] — ноль или неограниченное количество объектов. Часто такой интервал обозначают просто как [*].

  • [1..*] — один или неограниченное количество объектов.

Наиболее часто используют кратность [0..*] или [1..*]. Можно заметить, что динамические структуры данных вообще очень удобны в использовании. В нашей статье мы откажемся от использования кратности, а будем использовать такие коллекции: связный список (List) и ассоциативный массив (Map).

С использованием кратности мы ещё столкнёмся, когда будем знакомиться с различными типами отношений. Теперь, когда мы немного познакомились с правилами описания полей классов, давайте опишем некоторые поля для классов нашего проекта.

3 версия диаграммы

3 версия диаграммы

Чтобы отличать статические элементы класса от обычных, статические поля и методы будут подчёркиваться.

Назначение каждого поля построенных классов

Диаграмма классов UML хорошо показывает отношения между классами, однако она не может многого сказать о назначении полей и методов в классах. Если вы хотите лучше понять, для чего нужно каждое поле на диаграмме, прочтите об этом ниже.

Класс MathExpression:

  • initial – строковое математическое выражение, записанное в инфиксной форме.

  • postfix – строковое математическое выражение, записанное в постфиксной форме.

  • parameters – параметры в математическом выражении. Всего параметров четыре: a, b, c, d. У каждого параметра могут быть произвольные действительные значения. Значения параметров хранятся в ассоциативном массиве.

Класс MathParser:

  • delimiters — список разделителей. С помощью этих разделителей удаётся простым образом разбить входное выражение на список токенов.

Класс MathFormConverter:

  • precedence — ассоциированный массив, хранящий приоритет каждой операции/функции. Это необходимо для перевода выражения из инфиксной формы в постфиксную.

Класс MathConstantManager:

  • userDefinedConstants — ассоциированный массив, хранящий значения определённых пользователем констант.

  • predefinedConstants — ассоциированный массив, хранящий значения предопределённых констант.

Класс MathChecker:

  • userExpression — строковое представление пользовательского математического выражения, которое будет проверяться.

  • errorPlace — участок строки, в котором содержится ошибка (например, неизвестный системе токен).

  • errorType — тип ошибки.

  • operations — список корректных операций.

  • functions — список корректных функций.

  • operandQuantity — ассоциированный массив, хранящий количество аргументов для каждой операции/функции.

Класс MathCalculator:

  • expression — объект математического выражения, значения которого будут подсчитываться.

Аналогичное примечание будет сделано и для методов классов.

Методы класса

Снова разберём наш пример с классом Customer. На этот раз обратим внимание на третью секцию — секцию методов.

Описание методов очень похоже на описание полей класса. На рисунке ниже представлен общий вид описания метода класса.

Аргументы методов в общем случае описываются следующим образом:

В случае, если у метода есть несколько аргументов, они указываются в скобках через запятую
в указанном формате.
В случае, если у метода есть несколько аргументов, они указываются в скобках через запятую
в указанном формате.

Теперь давайте добавим на нашу основную диаграмму  методы классов.

Назначение каждого метода построенных классов

Класс MathExpression:

  • setParameter(parameter, value) — устанавливает параметру parameter значение value.

  • setExpression(expression) — устанавливает новое тело функции математического выражения.

  • getStringRepresentation() — возвращает тело функции.

Класс MathParser:

  • CreateTokenList(expression) — разбивает математическое выражение на список токенов и возвращает его в виде списка строк.

Класс MathFormConverter:

  • InfixToPostfix(infixExpression) — переводит математическое выражение в постфиксную форму.

Класс MathConstantManager:

  • addConstant(constant, value) — добавляет в систему новую пользовательскую константу.

  • alterConstant(constant, newValue) — изменяет значение пользовательской константы constant на newValue.

  • deleteConstant(constant) — удаляет пользовательскую константу constant.

  • getConstantValue(constant) — возвращает значение пользовательской константы constant.

  • isConstant(token) — проверяет, является ли token константой.

Класс MathChecker:

  • areAllTokensCorrect() — проверяет все токены математического выражения на корректность.

  • areBracketsCorrespond() — проверяет все ли скобки расставлены правильно.

  • hasEmptyBrackets() — проверяет, есть ли в выражении пустые скобки

  • hasMissedOperations() — проверяет, есть ли в выражении пропущенные операции. Например, для отслеживания случаев «18 354» — между числами пропущена операция.

  • IsOperation(token) — проверяет, является ли токен корректной операцией.

Класс MathCalculator:

  • calculate(value) — подсчитывает значение математического выражения, когда значение переменной равно value

Классы, отвечающие за графику

Помните, мы в начале статьи договорились, что у нас будет две диаграммы: одна для классов, отвечающих за работу с функциями, другая – для классов, отвечающих за графику? Настало время построить вторую диаграмму. Результат представлен на картинке ниже.

Слишком много непонятных классов

Давайте вместе разбираться в этой куче классов:

  • QWidget – стандартный класс фреймфорка Qt, который является базовым почти для всех создаваемых виджетов (графических элементов). В нашем проекте все элементы созданы на основе этого класса.

  • QDialog – стандартный класс для создания диалоговых окон.

  • AboutProgramDialog – окно информации о программе. Такое окно есть почти в каждой программе. В нём находится краткое описание проекта, его авторы и, возможно, информация о лицензировании.

  • HelpDialog – окно справочной информации. В больших системах справочник просто необходим.

  • MainWindow – главное окно программы «Построитель графиков функций». В нём содержатся основные элементы программы: плоскость для построения графиков (PaintingArea), список блоков ввода функций (FunctionBoxList), список блоков ввода констант (ConstantBoxList).

  • PaintingArea – плоскость для построения графиков. Пользователь может захотеть нарисовать графики некоторых определённых им функций. За отображения этих графиков и отвечает данный класс.

Координатная плоскость для построения графиков. Является объектом класса PaintingArea. В качестве примера, на координатной плоскости построен график функции y=sin(x)

Координатная плоскость для построения графиков. Является объектом класса PaintingArea. В качестве примера, на координатной плоскости построен график функции y=sin(x)
  • Graph – график функции на координатной плоскости. Пример объекта класса Graph представлен на рисунке выше.

  • FunctionBox – блок ввода функции. Представлен на рисунке ниже.

  • FunctionBoxList – список блоков ввода функций.

  • ConstantBox – блок ввода константы. Представлен на рисунке ниже.

  • ConstantBoxList – список блоков ввода констант.

Виды отношений

Давайте начнём рассматривать различные отношения между классами на диаграмме. Нами будут рассмотрены следующие соединительные линии:

  • Отношение ассоциации

  • Отношение зависимости

  • Отношение обобщения, также известное как отношение наследования.

  • Отношение агрегации

  • Отношение композиции

Обозначение каждого вида отношения представлено на рисунке ниже. Далее мы начнём рассматривать каждое отношение в подробностях.

Рассматриваемые нами виды отношений

Рассматриваемые нами виды отношений

Отношение ассоциации

Отношение ассоциации используют, чтобы показать, что между классами (например, между двумя классами) существует некоторая связь. Обычно с помощью него на диаграмме классов показывают, что один класс пользуется функционалом другого класса.

Методы класса LogSystem используют метод Console::WriteLine() и, возможно, некоторые 
другие  для вывода результатов.

Методы класса LogSystem используют метод Console::WriteLine() и, возможно, некоторые
другие для вывода результатов.

В общем случае, использование отношения ассоциации выглядит следующим образом:

Как вы можете заметить, стрелка ассоциации направлена от класса пользователя к классу владельцу используемой функциональности. Для пояснения того, каким образом один класс использует другой класс, вы можете описать данный процесс в вспомогательном тексте.

Обратите внимание на кратность ассоциации, которая расположена под стрелкой. С кратностью мы уже встречались ранее. Здесь у нее несколько иное значение. Кратность ассоциации обозначает количество объектов, которые участвуют во взаимодействии. Как показано на рисунке выше, во взаимодействии могут участвовать от m до n пользователей и от q до r владельцев.

Клиенты могут подключаться к серверу. С помощью кратности ассоциации указывается допустимое количество объектов в таком взаимодействии.

Клиенты могут подключаться к серверу. С помощью кратности ассоциации указывается допустимое количество объектов в таком взаимодействии.

Если кратность ассоциации не указана, будет подразумеваться кратность [0..*]. В случае со статическими классами кратность не указывается (можно считать, что там указана кратность [1].

Избегайте использования отношения ассоциации в обе стороны, как это показано на рисунке ниже. Такое взаимодействие классов можно считать ярким примером спагетти-кода. В случае ошибки очень сложно будет обнаружить, что послужило ей причиной.

Обозначение отношения ассоциации

Строго говоря, отношение ассоциации изображают сплошной линией без стрелок. Например, на различных сайтах вы, скорее всего, могли видеть следующие примеры.

В таких стандартных примерах очевидно, что студент учится у преподавателей и что работник работает на компанию, и никак иначе. Однако людям, которые только начинают знакомиться с вашей программой, необходимо понимать, в какую сторону направлена стрелка. Таким образом, возникает потребность в использовании именно направленного отношения ассоциации. В дальнейшем мы будем обозначать ассоциацию сплошной линией со стрелкой.

Давайте добавим отношения ассоциации на наши диаграммы.

С помощью отношения ассоциации мы в общих чертах показываем, как взаимодействуют классы.

С помощью отношения ассоциации мы в общих чертах показываем, как взаимодействуют классы.
Когда пользователь создаёт блок ввода константы и заполняет все поля, в системе создаётся новая константа. За это отвечает статический класс MathConstantManager.
Когда пользователь создаёт блок ввода константы и заполняет все поля, в системе создаётся новая константа. За это отвечает статический класс MathConstantManager.

Отношение зависимости

Отношение зависимости используют, чтобы показать, что изменение одного класса требует изменение другого класса.

В нашем случае вид графика функции зависит от самой функции или, по нашей договорённости об именовании, от объекта математического выражения. Давайте покажем это на диаграмме.

Изменение объекта математического выражения влияет на вид графика.

Изменение объекта математического выражения влияет на вид графика.

Стрелка отношения зависимости направлена от зависимого класса к независимому.

Объекты класса Graph зависят от изменений в объектах класса MathExpression, поскольку, на самом деле, в объекте Graph хранится указатель на объект класса MathExpression. Поэтому мы можем считать, что график «знает» обо всех изменениях внутри математического выражения (изменение тела функции, изменение границ значений переменной, изменение значения параметров и т.д.).

Отношение между этими двумя классами как бы соединяет две диаграммы воедино. Все классы нашей первой диаграммы «работают» на объекты класса MathExpression. Людям, работающим с графической частью приложения, нужно знать лишь об этом классе, что существенно снижает сложность. В результате наша вторая диаграмма приобретает следующий вид.

Отношение наследования

Прежде чем мы начнём изучать данное отношение, проясним один момент. Как вы можете видеть, данное отношение имеет два названия: отношение обобщения и отношение наследования. В терминах ООП принцип наследования является очень важной вещью. Чтобы не вносить путаницу в дальнейшее повествование, давайте договоримся использовать только второе название – отношение наследования – применительно к диаграмме классов.

Итак, отношение наследования используется, чтобы показать, что один класс является родителем (базовым классом или суперклассом) для другого класса (потомка, производного класса).

Если вы работали с какой-нибудь библиотекой для создания графического интерфейса (OpenGL в чистом виде не в счёт!), вы могли заметить, что все классы графических элементов обычно выстраиваются в цепочку наследования.  Например, взгляните на цепочку наследования классов фреймворка Qt5, представленную на рисунке ниже.

Отношение наследования здесь изображается обычной стрелкой.

Отношение наследования здесь изображается обычной стрелкой.
Полная версия диаграммы

Полную версию диаграммы вы можете посмотреть по ссылке

Разумеется, такие цепочки наследования просто необходимы, поскольку различные виджеты (графические элементы) имеют схожие свойства и поведение. В нашем приложении классы виджетов тоже были созданы на основе нескольких базовых классов: QWidget и QDialog. Давайте покажем это на диаграмме.

Мы свернули классы ради экономия места. В дальнейшем мы также будем это делать, поскольку нас будет интересовать именно отношения между классами, а не их поля и методы. Заметьте, что в большинстве наших классов мы не можем обойтись без класса QWidget и QDialog, однако его использование приводит к беспорядку.

Давайте договоримся, что больше мы не будем изображать эти два базовых класса, чтобы избежать проблем с читабельностью диаграммы. Тем не менее, мы будем иметь в виду, от каких классов наследуются оставшиеся.

Отношение агрегации

Отношение агрегации между двумя классами показывает, что один из них включает в себя другой класс в качестве составной части. При этом класс-часть может и существовать обособленно от класса-целого (далее мы раскроем смысл этой фразы).

В переводе с английского, слово aggregation означает соединение частей. Это значение очень точно отражает суть данного отношения – показать, из каких частей состоит класс.

В целом, смысл этого отношения достаточно условен. Может показаться, что определение отношения агрегации «один класс включает в себя другой класс» означает примерно следующее:

class A
{
	class B
	{
	};
…
}; 

На самом деле, это отношение означает, что объект одного класса включает в себя в качестве составной части объект другого класса.

Объект класса PersonalComputer (упрощённо) состоит из объекта класса Monitor, объекта класса ComputerMouse и объекта класса Keyboard.

Объект класса PersonalComputer (упрощённо) состоит из объекта класса Monitor, объекта класса ComputerMouse и объекта класса Keyboard.

С отношением агрегации также можно использовать кратность, чтобы показать, сколько объектов одного класса входят в состав объекта другого класса.

На нашей диаграмме есть много мест, где нам может пригодиться отношение агрегации:

  • Объект класса MainWindow содержит в себе по одному объекту классов PaintingArea, ConstantBoxList, FunctionBoxList.

  • Неограниченное количество объектов класса Graph могут содержаться в объекте класса PaintingArea.

  • Класс-контейнер ConstantBoxList может содержать в себе неограниченное количество объектов класса ConstantBox.

  • Класс-контейнер FunctionBoxList может содержать в себе неограниченное количество объектов класса FunctionBox.

Отношение композиции

Отношение композиции является частным случаем отношения агрегации. Однако у него есть одно отличие – классы-части, которые он соединяет с классом-целым, не могут существовать обособленно.

Одним из переводов слова composition является слово смесь. Если допустить, что из смеси не получится получить исходные компоненты, то это хорошо помогает понять, что части, соединённые отношением композиции не могут существовать сами по себе.

Давайте в качестве примера рассмотрим окно интерпретатора Python.

Понятное дело, что ни полоса прокрутки (ScrollBar), ни заголовок окна (Title), ни поле ввода команд (TextInput) не могут существовать отдельно от окна программы (Window). Это можно изобразить на диаграмме классов следующим образом.

В нашей диаграмме объекты классов FunctionBox и ConstantBox не могут существовать отдельно от их контейнеров. Кроме того, объекты класса Graph тоже не могут существовать обособленно от координатной плоскости.

Вот и всё! Мы рассмотрели достаточно элементов диаграммы классов, чтобы начать делать собственные диаграммы классов.

P.S. Спасибо всем, кто дошёл до этого момента. Статья получилась очень массивной, поскольку хотелось разобрать все основные элементы на практическом примере.

Унифицированный язык моделирования ( UML ) — это язык моделирования общего назначения в области разработки программного обеспечения, предназначенный для обеспечения стандартного подхода к визуализации проектирования системы. Первоначальным мотивом создания UML было желание стандартизировать различные системы обозначений и методы проектирования программного обеспечения. В UML диаграмма классов является одним из шести типов структурных диаграмм . Диаграммы классов являются основой процесса моделирования объектов и моделируют статическую структуру системы.

Структурные диаграммы показывают статическую структуру системы и ее частей на разных уровнях абстракции и реализации и то, как они связаны друг с другом. Элементы на структурной диаграмме представляют значимые концепции системы и могут включать абстрактные концепции, концепции реального мира и реализации. Существует семь следующих типов структурных диаграмм:

  • Диаграмма классов
  • Диаграмма компонентов
  • Схема развертывания
  • Диаграмма объекта
  • Схема пакета
  • Схема составной структуры
  • Диаграмма профиля

Обзор 14 типов диаграмм UML

Что такое диаграмма классов?

Диаграмма классов на унифицированном языке моделирования (UML) — это диаграмма статической структуры, которая описывает структуру системы, показывая ее классы, их атрибуты, операции (или методы) и отношения между объектами. Диаграмма классов — это план системы или подсистемы. Диаграммы классов можно использовать для моделирования объектов, составляющих систему, для демонстрации отношений между объектами и для описания ролей этих объектов и предоставляемых ими услуг.

Цель UML — предоставить стандартную нотацию, которую можно использовать всеми объектно-ориентированными методами, а также выбрать и интегрировать лучшие элементы предшествующих нотаций. UML был разработан для широкого круга приложений. Следовательно, он предоставляет конструкции для широкого спектра систем и действий (например, распределенные системы, анализ, проектирование и развертывание систем).

UML — это нотация, возникшая в результате объединения OMT с

  1. Техника объектного моделирования OMT  [ James Rumbaugh  1991] – лучше всего подходит для анализа и информационных систем с интенсивным использованием данных.
  2. Booch [ Gradi Booch  1994] — отлично подходил для дизайна и реализации. Грэди Буч много работал с  языком Ада  и был главным игроком в разработке объектно-ориентированных методов для этого языка. Хотя метод Буча был сильным, нотация была принята хуже (в его моделях преобладало множество форм облаков — не очень аккуратно).
  3. OOSE (Object-Oriented Software Engineering [ Ivar Jacobson  1992]) — включает модель, известную как варианты использования. Сценарии использования — это мощная техника для понимания поведения всей системы (область, в которой объектно-ориентированный подход традиционно был слабым).

В 1994 году Джим Рамбо, создатель OMT, ошеломил мир программного обеспечения, когда он покинул General Electric и присоединился к Грэди Бучу в Rational Corp. Целью партнерства было объединить их идеи в единый унифицированный метод (рабочее название метод действительно был «унифицированным методом»).

История UML

Назначение диаграммы классов

Диаграммы классов полезны на многих этапах проектирования системы. На этапе анализа диаграммы классов могут помочь вам понять требования предметной области и определить ее компоненты. В проектах объектно-ориентированного программного обеспечения диаграмма классов, созданная на ранних стадиях проекта, содержит классы, которые часто преобразуются в реальные классы и объекты программного обеспечения при написании кода.

Позднее вы можете преобразовать ранний анализ и концептуальные модели в диаграммы классов, чтобы показать определенные части системы, пользовательские интерфейсы, логические реализации и т. д.

Диаграммы классов широко используются при моделировании объектно-ориентированных систем, поскольку они являются единственными диаграммами UML, которые могут быть отображены непосредственно на объектно-ориентированные языки. На этапе реализации цикла разработки программного обеспечения вы можете использовать диаграммы классов для преобразования моделей в код и кода в модели.

Пример класса

У собаки есть состояния – цвет, имя, порода, а также поведение – виляние, лай, еда. Объект является экземпляром класса.

Обозначение класса UML

Класс представляет концепцию, которая инкапсулирует состояние ( атрибуты ) и поведение ( операции ). Каждый атрибут имеет тип. Каждая  операция  имеет  подпись . Имя класса является  единственной обязательной информацией .

Имя класса:

  • Имя класса появляется в первом разделе.

Атрибуты класса:

  • Атрибуты показаны во втором разделе.
  • Тип атрибута отображается после двоеточия.
  • Атрибуты сопоставляются с переменными-членами (элементами данных) в коде.

Классовые операции (методы):

  • Операции показаны в третьем разделе. Это услуги, предоставляемые классом.
  • Тип возвращаемого значения метода отображается после двоеточия в конце подписи метода.
  • Возвращаемый тип параметров метода отображается после двоеточия после имени параметра. Операции сопоставляются с методами класса в коде

Классовые отношения

Класс может быть вовлечен в одно или несколько отношений с другими классами. Связь может быть одного из следующих типов: (См. рисунок справа для графического представления отношений).

Имена отношений

  • Имена отношений пишутся посередине ассоциативной строки.
  • Названия хороших отношений имеют смысл, если прочитать их вслух:
    • «Каждая электронная таблица  содержит  некоторое количество ячеек»,
    • «выражение  оценивается  как значение»
  • Они часто имеют  небольшую стрелку, указывающую направление,  в котором следует читать отношения, например, выражения оцениваются как значения, но значения не оцениваются как выражения.

Отношения — Роли

  • Роль – это направленная цель ассоциации.
  • Роли написаны на концах ассоциативной линии и описывают цель, которую играет этот класс в отношениях.
    • Например, ячейка связана с выражением. Характер связи таков, что выражением является  формула  клетки.

Судоходность

Стрелки указывают, возможно ли при наличии одного экземпляра, участвующего в отношении, определить связанные с ним экземпляры другого класса.

Диаграмма выше предполагает, что,

  • Имея электронную таблицу, мы можем найти все содержащиеся в ней ячейки, но это
    • мы не можем определить по ячейке, в какой электронной таблице она содержится.
  • Учитывая ячейку, мы можем получить соответствующее выражение и значение, но
    • учитывая значение (или выражение), мы не можем найти ячейку, для которой это атрибуты.

Видимость атрибутов класса и операций

В объектно-ориентированном дизайне есть нотация видимости атрибутов и операций. UML определяет четыре типа видимости:  public ,  protected ,  private и  package .

Символы +, -, # и ~ перед именем атрибута и операции в классе обозначают видимость атрибута и операции.

  • + обозначает общедоступные атрибуты или операции
  • – обозначает частные атрибуты или операции
  • # обозначает защищенные атрибуты или операции
  • ~ обозначает атрибуты пакета или операции

Пример видимости класса

В приведенном выше примере:

  • attribute1 и op1 MyClassName являются общедоступными
  • attribute3 и op3 защищены.
  • attribute2 и op2 являются частными.

Доступ для каждого из этих типов видимости показан ниже для членов разных классов.

Право доступа общественный (+) частный (-) защищенный (#) Пакет (~)
Члены одного класса да да да да
Члены производных классов да нет да да
Члены любого другого класса да нет нет в том же пакете

Множественность

Сколько объектов каждого класса принимают участие в отношениях и множественности можно выразить как:

  • Ровно один — 1
  • Ноль или единица – 0..1
  • Многие – 0..* или *
  • Один или несколько – 1..*
  • Точное число — например, 3..4 или 6
  • Или сложное отношение — например, 0..1, 3..4, 6.* будет означать любое количество объектов, кроме 2 или 5.

Пример множественности

  • Требование: Студент может посещать несколько курсов, и многие студенты могут быть зачислены на один курс.
  • В приведенном ниже примере  диаграмма классов  (слева) описывает формулировку вышеуказанного требования для статической модели, а диаграмма объектов (справа) показывает моментальный снимок (экземпляр диаграммы классов) зачисления на курс для курсы по программной инженерии и управлению базами данных соответственно)

Диаграмма объекта

Пример агрегации — компьютер и комплектующие

  • Агрегация — это частный случай ассоциации, обозначающий иерархию «состоит из».
  • Агрегат — это родительский класс, компоненты — это дочерние классы.

Пример агрегации

Пример наследования — таксономия ячеек

  • Наследование — еще один частный случай ассоциации, обозначающей «своего рода» иерархию.
  • Наследование упрощает модель анализа, вводя таксономию
  • Дочерние классы наследуют атрибуты и операции родительского класса.

Пример наследования

Диаграмма классов — пример инструмента диаграммы

Диаграмма классов может также иметь примечания, прикрепленные к классам или отношениям. Примечания отображаются серым цветом.

Пример диаграммы классов

В приведенном выше примере:

Мы можем интерпретировать значение приведенной выше диаграммы классов, прочитав пункты следующим образом.

  1. Форма — это абстрактный класс. Он показан курсивом.
  2. Форма — это суперкласс. Круг, прямоугольник и многоугольник являются производными от формы. Другими словами, Круг — это Форма. Это отношение обобщения/наследования.
  3. Существует связь между DialogBox и DataController.
  4. Форма является частью окна. Это агрегационные отношения. Shape может существовать без Window.
  5. Точка является частью Круга. Это композиционные отношения. Точка не может существовать без Окружности.
  6. Окно зависит от события. Однако Event не зависит от Window.
  7. Атрибутами Circle являются радиус и центр. Это класс сущности.
  8. Имена методов Circle: area(),circ(), setCenter() и setRadius().
  9. Радиус параметра в Circle является параметром in типа float.
  10. Метод area() класса Circle возвращает значение типа double.
  11. Атрибуты и имена методов Rectangle скрыты. У некоторых других классов на диаграмме также скрыты атрибуты и имена методов.

Пример диаграммы классов: система заказов

Пример диаграммы классов: система заказов

Пример диаграммы классов: графический интерфейс

Диаграмма классов может также иметь примечания, прикрепленные к классам или отношениям.

Пример диаграммы классов: графический интерфейс

Работа со сложной системой — диаграмма нескольких или одного класса?

Неизбежно, если вы моделируете большую систему или большую бизнес-сферу, вам придется учитывать множество сущностей. Должны ли мы использовать несколько или одну диаграмму классов для моделирования проблемы? Ответ:

  • Вместо моделирования каждой сущности и ее взаимосвязей на одной диаграмме классов лучше использовать несколько диаграмм классов.
  • Разделение системы на несколько диаграмм классов облегчает понимание системы, особенно если каждая диаграмма является графическим представлением определенной части системы.

Перспективы диаграммы классов в жизненном цикле разработки программного обеспечения

Мы можем использовать диаграммы классов на разных этапах  жизненного цикла разработки программного обеспечения  и, как правило, моделируя диаграммы классов в трех различных перспективах (уровнях детализации) постепенно по мере продвижения вперед:

Концептуальная перспектива : диаграммы интерпретируются как описание вещей в реальном мире. Таким образом, если вы принимаете концептуальную перспективу, вы рисуете диаграмму, которая представляет концепции в изучаемой области. Эти концепции будут естественным образом относиться к классам, которые их реализуют. Концептуальная перспектива  считается независимой от языка .

Перспектива спецификации : диаграммы интерпретируются как описание программных абстракций или компонентов со спецификациями и интерфейсами, но без привязки к конкретной реализации. Таким образом, если вы смотрите на спецификацию, мы  смотрим на интерфейсы программного обеспечения , а не на реализацию.

Перспектива реализации : диаграммы интерпретируются как описание программных реализаций на определенной технологии и  языке . Таким образом, если вы смотрите на реализацию, мы  смотрим на программную реализацию .

Ищете бесплатный инструмент для построения диаграмм классов?

Visual Paradigm Online (VP Online) Free Edition — это бесплатное онлайн-программное обеспечение для рисования, которое поддерживает диаграммы классов, другие диаграммы UML, инструменты ERD и инструменты организационных диаграмм. Он имеет простой, но мощный редактор, который позволяет быстро и легко создавать диаграммы классов. В этом бесплатном редакторе UML нет рекламы, нет сроков доступа и нет ограничений, например, на количество диаграмм, количество фигур и т. д. Вы являетесь владельцем диаграмм, которые создаете для личных и некоммерческих целей.

Онлайн-инструмент для построения диаграмм классов

Ищете более формальное моделирование UML на рабочем столе?

Visual Paradigm Community Edition был запущен в 2004 году для предоставления  бесплатного программного обеспечения UML  исключительно для некоммерческих целей, поддержки пользователей, которые делали свои первые шаги в моделировании UML и которым требуется бесплатное и кросс-платформенное программное обеспечение для моделирования UML для личного использования, например как применение UML в студенческих проектах.

Экран визуальной парадигмы

Бесплатный инструмент моделирования UML для всех видов некоммерческих целей. Поддержка 13 диаграмм UML 2.x

Бесплатный инструмент UML с поддержкой 13 диаграмм UML 2.x

Нас приняли более 1 миллиона установок по всему миру, и эта цифра продолжает расти. Многие люди используют платные версии Visual Paradigm для ежедневного рисования профессиональных диаграмм UML и ERD для проектирования и анализа систем и баз данных.

Причина 2

Доверие ИТ-специалистов и крупных организаций

Многие крупные организации, ИТ-компании, консультанты, университеты, неправительственные организации и правительственные учреждения по всему миру приняли Visual Paradigm (платные версии). На рисунке ниже показаны некоторые из наших платных клиентов.

Клиенты визуальной парадигмы

Причина 3

Высокое качество – награда

Нам доверяют не только самые известные предприятия мира, но и вся отрасль. Visual Paradigm — многократный обладатель международных наград.

Награды визуальной парадигмы

Причина 4

Самая широко используемая платформа для моделирования в академических кругах.

Наиболее широко используемый инструмент UML для академических кругов, принятый тысячами университетов и колледжей.

Школы, использующие визуальную парадигму

Причина 5

Сотни примеров и шаблонов диаграмм UML и ERD

Сотни примеров UML и ERD,  готовых для импорта в Visual Paradigm для мгновенного эксперимента или для начала работы с собственной моделью UML. Все бесплатно.

Причина 6

Путь обновления до коммерческих выпусков для широкого спектра приложений и возможностей

Простое обновление для огромного набора дополнительных функций (например, BPMN и поддержки совместной работы) и для коммерческого использования, начиная с  6 долларов США в месяц .

Упакованные функции в Visual Paradigm

Причина 7

Форум активных пользователей для получения помощи и обмена идеями и опытом

Поддерживайте, делитесь и обменивайтесь своими идеями с другими людьми на  форуме активных пользователей Visual Paradigm .

Форум визуальной парадигмы

Причина 8

Кроссплатформенное, удобное, быстрое и отзывчивое приложение

Visual Paradigm может работать на разных платформах, таких как Windows, Linux и Mac. Его интуитивно понятный интерфейс и мощные функции моделирования делают моделирование быстрым и легким!

Кроссплатформенное программное обеспечение UML

использованная литература

  • Что такое УМЛ?
  • Почему UML-моделирование?
  • Обзор 14 типов диаграмм UML
  • Что такое диаграмма классов?
  • Что такое диаграмма компонентов?
  • Что такое диаграмма развертывания?
  • Что такое диаграмма объекта?
  • Что такое пакетная диаграмма?
  • Что такое составная структурная диаграмма?
  • Что такое профильная диаграмма?
  • Что такое диаграмма вариантов использования?
  • Что такое Диаграмма активности?
  • Что такое диаграмма состояний?
  • Что такое диаграмма последовательности?
  • Что такое коммуникационная диаграмма?
  • Что такое обзорная диаграмма взаимодействия?
  • Что такое временная диаграмма

После того, как определены функциональные требования к системе и её границы, следует проанализировать предметную область с целью построения диаграммы классов.

Краткие теоретические сведения о диаграммах классов

Диаграмма классов определяет типы классов системы и различного рода статические связи, которые существуют между ними. На диаграммах классов изображаются также атрибуты классов, операции классов и ограничения, которые накладываются на связи между классами. Вид и интерпретация диаграммы классов существенно зависит от точки зрения (уровня абстракции): классы могут представлять сущности предметной области (в процессе анализа) или элементы программной системы (в процессах проектирования и реализации).

Основные элементы диаграммы классов

Основными элементами являются классы и связи между ними. Классы характеризуются при помощи атрибутов и операций.

Атрибуты описывают свойства объектов класса. Большинство объектов в классе получают свою индивидуальность из-за различий в их атрибутах и взаимосвязи с другими объектами. Однако, возможны объекты с идентичными значениями атрибутов и взаимосвязей. Т.е. индивидуальность объектов определяется самим фактом их существования, а не различиями в их свойствах. Имя атрибута должно быть уникально в пределах класса. За именем атрибута может следовать его тип и значение по умолчанию.

Операция есть функция или преобразование. Операция может иметь параметры и возвращать значения.

Виды связей:

  • ассоциация
  • агрегация
  • наследование.

Ассоциация (association) – представляет собой отношения между экземплярами классов.
Каждый конец ассоциации обладает кратностью (синоним – мощностью, ориг. — multiplicity), которая показывает, сколько объектов, расположенных с соответствующего конца ассоциации, может участвовать в данном отношении. В примере на рисунке каждый Товар имеет сколь угодно Записей в накладной, но каждая Запись в накладной обязательно один Товар. В общем случае кратность может быть задана любым множеством.
Ассоциации может быть присвоено имя. В качестве имени обычно выбирается глагол или глагольное словосочетание, сообщающие смысл и назначение связи.
Также на концах ассоциации под кратностью может указываться имя роли, т.е. какую роль выполняют объекты, находящиеся с данного конца ассоциации.

Агрегация (aggregation) – это ассоциация типа «целое-часть». Агрегация в UML представляется в виде прямой с ромбом на конце.
Ромб на связи указывает, какой класс является агрегирующим (т.е. «состоящим из»); класс с противоположного конца — агрегированным (т.е. те самые «части»).

Композиция (composition) – это такая агрегация, где объекты-части не могут существовать сами по себе и уничтожаются при уничтожении объекта агрегирующего класса. Композиция изображается так же, как ассоциация, только ромбик закрашен.
Важно понимать разницу между агрегацией и композицией: при агрегации объекты-части могут существовать сами по себе, а при композиции — нет. Пример агрегации: автомобиль—колесо, пример композиции: дом—комната.

Наследование (inheritance) – это отношение типа «общее-частное». Позволяет определить такое отношение между классами, когда один класс обладает поведением и структурой ряда других классов. При создании производного класса на основе базового (одного или нескольких) возникает иерархия наследования. Реализация принципов наследования является ключевой предпосылкой возможности повторного использования кода, поскольку это основной инструмент достижения полиморфизма.

Порядок построения диаграммы классов

  1. Создать новую диаграмму с именем «Сущности».
  2. Проанализировать предметную область и построить диаграмму классов. Должна получиться диаграмма, подобная примеру:

Основной сущностью в системе будет являться товар. Как известно из задания на проектирование, товар хранится на складе. Но понятия товара как некоего описания и товара, лежащего непосредственно на складе, отличаются друг от друга. Товар, лежащий на складе, кроме того, что связан со складом отношением композиции (агрегация не совсем подходит, поскольку в данной системе товар является товаром, пока он не покинет склад), ещё характеризуется количеством. Аналогично следует рассуждать и при рассмотрении отношения Товара и Заказа, Товара и Накладной. В связи с тем, что Заказ и Накладная в сущности являются документами и имеют сходные атрибуты, они были объединены с помощью общего класса-предка Документ. Примечательно, что на диаграмме представлены два класса со стереотипом Enumeration (перечисление). Стереотип можно установить из контекстного меню для класса.
3.Сохранить диаграмму.

Приложение для построения диаграмм классов

Для построения UML-диаграмм следует использовать Flexberry Designer — удобный онлайн инструмент. После простого процесса регистрации достаточно создать проект, перейти на список диаграмм и создавать нужные диаграммы.
Также рекомендуем воспользоваться полезным инструментом для быстрого построения диаграмм по текстовому описанию.

Перейти

  • Построение диаграммы видов деятельности
  • Построение диаграмм взаимодействия

В основе любой объектно-ориентированной системы лежит этап проектирования структуры классов – поэтому говорят, что диаграммы классов являются наиболее популярными из типов UML-диаграммы.

В этом простом учебном пособии по построению диаграмм классов мы рассмотрели ключевые области, которые необходимо знать, чтобы без труда нарисовать диаграммы классов. Прокрутите вниз, чтобы узнать.

  • Классовая диаграмма Определение
  • Нотации диаграммы класса с примерами
  • Как нарисовать диаграмму классов
  • Классовая диаграмма Лучшие практики
  • Примеры/шаблоны схем классов

Определение Классовой Диаграммы | Что такое Классовая Диаграмма?

Диаграмма классов – это UML-диаграмма, которая описывает систему, визуализируя различные типы объектов внутри системы и виды статических связей, которые существуют между ними. Он также иллюстрирует операции и атрибуты классов.

Обычно они используются для изучения концепций области, понимания требований к программному обеспечению и описания подробных проектов.

Нотации диаграммы класса с примерами

Существует несколько обозначений диаграмм классов, которые используются при рисовании диаграмм классов UML. Мы перечислили ниже наиболее распространенные нотации диаграммы классов.

Класс

Нотация класса - учебное пособие по диаграмме классов UML

Классы представляют собой центральные объекты в системе. Он представлен прямоугольником с 3 отсеками.

Первый показывает имя класса, а средний – атрибуты класса, которые являются характеристиками объектов. В нижнем списке перечислены операции класса, которые представляют собой поведение класса.

Простой класс

Последние два отсека являются необязательными. Нотация класса без последних двух отделений называется простым классом и содержит только имя класса.

Интерфейс

Нотация интерфейса - учебное пособие

Символ интерфейса на диаграммах классов обозначает набор операций, которые детализируют ответственность класса.

Пакет

Пакет

Символ пакета используется для группировки классов или интерфейсов, которые либо похожи по своей природе, либо связаны. Группировка этих элементов дизайна с использованием символов упаковки улучшает читабельность диаграммы

Отношения в диаграмме классов

Отношения диаграммы классов

Для получения подробной информации о типах разъемов диаграммы классов и различных отношениях между классами обратитесь к нашему удобному руководству по отношениям диаграммы классов.

Полный список нотаций/символов диаграммы классов см. в данной заметке.

Как нарисовать диаграмму классов

Классовые диаграммы идут рука об руку с объектно-ориентированным дизайном. Поэтому знание его основ – ключевая часть умения рисовать хорошие классовые диаграммы.

При необходимости описания статического вида системы или ее функциональных возможностей, потребуется нарисовать диаграмму классов. Вот шаги, которые необходимо выполнить для создания диаграммы классов.

Шаг 1: Определите имена классов

Первым шагом является идентификация первичных объектов системы.

Шаг 2: Различные отношения

Следующий шаг – определить, как каждый из классов или объектов связан друг с другом. Обратите внимание на общие черты и абстракции среди них; это поможет вам сгруппировать их при рисовании диаграммы классов.

Шаг 3: Создать структуру

Сначала добавьте имена классов и свяжите их с соответствующими коннекторами. Добавить атрибуты и функции/методы/операции можно позже.

Классовая диаграмма Лучшие практики

  • Классовые диаграммы могут иметь тенденцию к бессвязности по мере их расширения и роста. Лучше всего избегать создания больших диаграмм и разбивать их на более мелкие, которые позже можно будет связать друг с другом. Ты можешь очень легко сделать это с Крейли. Это поможет вам улучшить читабельность ваших диаграмм.
  • Используя простую нотацию класса, вы можете быстро создать высокоуровневый обзор вашей системы. Подробная диаграмма может быть создана отдельно по мере необходимости, и даже связана с первой диаграммой для удобства пользования.
  • Чем больше линий перекрываются на диаграммах классов, тем более загроможденными они становятся. Читатель только запутается, пытаясь найти путь. Убедитесь, что две линии не пересекаются.
  • Используйте цвета для группировки общих модулей. Различные цвета на разных классах помогают читателю различать различные группы.

Примеры диаграмм классов / Шаблоны

Диаграмма класса Пример 1

Пример диаграммы классов

Щелкните по шаблону, чтобы отредактировать его в режиме онлайн

Диаграмма класса Пример 2

Пример диаграммы классов

Щелкните по шаблону, чтобы отредактировать его в режиме онлайн

Диаграмма класса Пример 3

Другие ресурсы диаграммы классов

  • Руководство по работе с диаграммами классов UML – Часть 1
  • Руководство по работе с диаграммами классов UML – часть 2
  • Инструменты, шаблоны и ресурсы для построения диаграмм классов

Поделитесь своими мыслями об учебном пособии “Классная диаграмма”

В этом учебном пособии мы рассмотрели, что такое диаграмма классов, нотации диаграммы классов, как нарисовать диаграмму классов и лучшие практики, которым вы можете следовать при создании диаграмм классов. Кроме того, мы добавили несколько примеров схем классов, которые можно мгновенно редактировать в режиме онлайн.

Хотите узнать о других типах диаграмм UML?

 

UML – унифицированный язык моделирования (Unified Modeling Language) – это система обозначений, которую можно применять для объектно-ориентированного анализа и проектирования.
Его можно использовать для визуализации, спецификации, конструирования и документирования программных систем.
Словарь UML включает три вида строительных блоков:

  • Диаграммы.
  • Сущности.
  • Связи.

Сущности – это абстракции, которые являются основными элементами модели, связи соединяют их между собой, а диаграммы группируют представляющие интерес наборы сущностей.

Диаграмма – это графическое представление набора элементов, чаще всего изображенного в виде связного графа вершин (сущностей) и путей (связей). Язык UML включает 13 видов диаграмм, среди которых на первом месте в списке — диаграмма классов, о которой и пойдет речь.
Диаграммы классов показывают набор классов, интерфейсов, а также их связи. Диаграммы этого вида чаще всего используются для моделирования объектно-ориентированных систем. Они предназначены для статического представления системы.
Большинство элементов UML имеют уникальную и прямую графическую нотацию, которая дает визуальное представление наиболее важных аспектов элемента.

Сущности

Диаграммы классов оперируют тремя видами сущностей UML:

  • Структурные.
  • Поведенческие.
  • Аннотирующие.

Структурные сущности – это «имена существительные» в модели UML. В основном, статические части модели, представляющие либо концептуальные, либо физические элементы. Основным видом структурной сущности в диаграммах классов является класс.

 
Поведенческие сущности – динамические части моделей UML. Это «глаголы» моделей, представляющие поведение модели во времени и пространстве. Основной из них является взаимодействие – поведение, которое заключается в обмене сообщениями между наборами объектов или ролей в определенном контексте для достижения некоторой цели. Сообщение изображается в виде линии со стрелкой, почти всегда сопровождаемой именем операции.

 
Поведенческие сущности
Аннотирующие сущности – это поясняющие части UML-моделей, иными словами, комментарии, которые можно применить для описания, выделения и пояснения любого элемента модели. Главная из аннотирующих сущностей – примечание. Это символ, служащий для описания ограничений и комментариев, относящихся к элементу либо набору элементов. Графически представлен прямоугольником с загнутым углом; внутри помещается текстовый или графический комментарий.

 
Аннотирующие сущности

Структурные сущности — классы

Класс – это описание набора объектов с одинаковыми атрибутами, операциями, связями и семантикой.

Графически класс изображается в виде прямоугольника, разделенного на 3 блока горизонтальными линиями:

  • имя класса
  • атрибуты (свойства) класса
  • операции (методы) класса.

 
Для атрибутов и операций может быть указан один из трех типов видимости:

  • private (частный)
  • #protected (защищенный)
  • +public (общий)

Видимость для полей и методов указывается в виде левого символа в строке с именем соответствующего элемента.

Каждый класс должен обладать именем, отличающим его от других классов. Имя – это текстовая строка. Имя класса может состоять из любого числа букв, цифр и знаков препинания (за исключением двоеточия и точки) и может записываться в несколько строк.
На практике обычно используются краткие имена классов, взятые из словаря моделируемой системы. Каждое слово в имени класса традиционно пишут с заглавной буквы (верблюжья конвенция), например Sensor (Датчик) или TemperatureSensor (ДатчикТемпературы).
Обозначение класса
Для абстрактного класса имя класса записывается курсивом.

 
Атрибут (свойство) – это именованное свойство класса, описывающее диапазон значений, которые может принимать экземпляр атрибута. Класс может иметь любое число атрибутов или не иметь ни одного. В последнем случае блок атрибутов оставляют пустым.
Атрибут представляет некоторое свойство моделируемой сущности, которым обладают все объекты данного класса. Имя атрибута, как и имя класса, может представлять собой текст. На практике для именования атрибута используются одно или несколько коротких существительных, выражающих некое свойство класса, к которому относится атрибут.

Можно уточнить спецификацию атрибута, указав его тип, кратность (если атрибут представляет собой массив некоторых значений) и начальное значение по умолчанию.

Статические атрибуты класса обозначаются подчеркиванием.

Операция (метод) – это реализация метода класса. Класс может иметь любое число операций либо не иметь ни одной. Часто вызов операции объекта изменяет его атрибуты.
Графически операции представлены в нижнем блоке описания класса.
Допускается указание только имен операций. Имя операции, как и имя класса, должно представлять собой текст. На практике для именования операции используются короткие глагольные конструкции, описывающие некое поведение класса, которому принадлежит операция. Обычно каждое слово в имени операции пишется с заглавной буквы, за исключением первого, например move (переместить) или isEmpty (проверка на пустоту).
Можно специфицировать операцию, устанавливая ее сигнатуру, включающую имя, тип и значение по умолчанию всех параметров, а применительно к функциям – тип возвращаемого значения.

Абстрактные методы класса обозначаются курсивным шрифтом.
Статические методы класса обозначаются подчеркиванием.

Изображая класс, не обязательно показывать сразу все его атрибуты и операции. Для конкретного представления, как правило, существенна только часть атрибутов и операций класса. В силу этих причин допускается упрощенное представление класса, то есть для графического представления выбираются только некоторые из его атрибутов. Если помимо указанных существуют другие атрибуты и операции, вы даете это понять, завершая каждый список многоточием.
Чтобы легче воспринимать длинные списки атрибутов и операций, желательно снабдить префиксом (именем стереотипа) каждую категорию в них. В данном случае стереотип – это слово, заключенное в угловые кавычки, которое указывает то, что за ним следует.
Стереотип

Отношения между классами

Существует четыре типа связей в UML:

  • Зависимость
  • Ассоциация
  • Обобщение
  • Реализация

Эти связи представляют собой базовые строительные блоки для описания отношений в UML, используемые для разработки хорошо согласованных моделей.

Первая из них – зависимость – семантически представляет собой связь между двумя элементами модели, в которой изменение одного элемента (независимого) может привести к изменению семантики другого элемента (зависимого). Графически представлена пунктирной линией, иногда со стрелкой, направленной к той сущности, от которой зависит еще одна; может быть снабжена меткой.

 
Зависимость
Зависимость – это связь использования, указывающая, что изменение спецификаций одной сущности может повлиять на другие сущности, которые используют ее.

 
Ассоциация – это структурная связь между элементами модели, которая описывает набор связей, существующих между объектами.
Ассоциация показывает, что объекты одной сущности (класса) связаны с объектами другой сущности таким образом, что можно перемещаться от объектов одного класса к другому.
Например, класс Человек и класс Школа имеют ассоциацию, так как человек может учиться в школе. Ассоциации можно присвоить имя «учится в». В представлении однонаправленной ассоциации добавляется стрелка, указывающая на направление ассоциации.
Ассоциация

Двойные ассоциации представляются линией без стрелок на концах, соединяющей два классовых блока.
Ассоциация может быть именованной, и тогда на концах представляющей её линии будут подписаны роли, принадлежности, индикаторы, мультипликаторы, видимости или другие свойства.

Множественность ассоциации представляет собой диапазон целых чисел, указывающий возможное количество связанных объектов. Он записывается в виде выражения с минимальным и максимальным значением; для их разделения используются две точки. Устанавливая множественность дальнего конца ассоциации, вы указываете, сколько объектов может существовать на дальнем конце ассоциации для каждого объекта класса, находящегося на ближнем ее конце. Количество объектов должно находиться в пределах заданного диапазона. Множественность может быть определена как единица 1, ноль или один 0..1, любое значение 0..* или *, один или несколько 1..*. Можно также задавать диапазон целых значений, например 2..5, или устанавливать точное число, например 3.
Множественность ассоциации
Агрегация – особая разновидность ассоциации, представляющая структурную связь целого с его частями. Как тип ассоциации, агрегация может быть именованной. Одно отношение агрегации не может включать более двух классов (контейнер и содержимое).
Агрегация встречается, когда один класс является коллекцией или контейнером других. Причём, по умолчанию агрегацией называют агрегацию по ссылке, то есть когда время существования содержащихся классов не зависит от времени существования содержащего их класса. Если контейнер будет уничтожен, то его содержимое — нет.
Графически агрегация представляется пустым ромбом на блоке класса «целое», и линией, идущей от этого ромба к классу «часть».
Агрегация
Композиция — более строгий вариант агрегации. Известна также как агрегация по значению.
Композиция – это форма агрегации с четко выраженными отношениями владения и совпадением времени жизни частей и целого. Композиция имеет жёсткую зависимость времени существования экземпляров класса контейнера и экземпляров содержащихся классов. Если контейнер будет уничтожен, то всё его содержимое будет также уничтожено.
Графически представляется как и агрегация, но с закрашенным ромбиком.
Композиция

Третья связь – обобщение – выражает специализацию или наследование, в котором специализированный элемент (потомок) строится по спецификациям обобщенного элемента (родителя). Потомок разделяет структуру и поведение родителя. Графически обобщение представлено в виде сплошной линии с пустой стрелкой, указывающей на родителя.
Обобщение
Четвертая – реализация – это семантическая связь между классами, когда один из них (поставщик) определяет соглашение, которого второй (клиент) обязан придерживаться. Это связи между интерфейсами и классами, которые реализуют эти интерфейсы. Это, своего рода, отношение «целое-часть». Поставщик, как правило, представлен абстрактным классом. В графическом исполнении связь реализации – это гибрид связей обобщения и зависимости: треугольник указывает на поставщика, а второй конец пунктирной линии – на клиента.
Реализация

Пример кода и диаграммы классов для него

Программа получает данные с датчика температуры (вводятся с консоли) — по 5 измерений для каждого из двух объектов класса TemperatureMeasure и усредняет их. Также предусмотрен класс ShowMeasure для вывода измеренных значений.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78

#include <iostream>
using namespace std;
class Sensor {
  int value;
public:
  Sensor() { value = 0; }
  void setValue(int value) { this->value += value; }
  int getValue() { return value; }
};
class MeasureCount
{
  int number;
  static int total;
public:
  MeasureCount() { number = 0; }
  void increment() { number++; total++; }
  int getNumber() { return number; }
  static int getTotal() { return total; }
};
int MeasureCount::total = 0;
class ITemperatureMeasure
{
public:
  virtual void setValue() = 0;
  virtual double getValue() = 0;
};
class TemperatureMeasure : public virtual ITemperatureMeasure
{
private:
  Sensor *h;        // агрегация
  MeasureCount *measure;  // композиция
public:
  TemperatureMeasure(Sensor *h);
  int getNumber() { return measure->getNumber(); }
  double getValue() { return (double)h->getValue() / measure->getNumber(); }
  void setValue()
  {
    int value;
    measure->increment();
    cout << «t[» << measure->getNumber() << «]= «
    cin >> value;
    h->setValue(value);
  }
  static int getTotal() { return MeasureCount::getTotal(); }
};
TemperatureMeasure::TemperatureMeasure(Sensor *h)
{
  measure = new MeasureCount();
  this->h = h;
}
class ShowTemperature // зависимость
{
public:
  static void Show(TemperatureMeasure t)
  {
    cout << t.getNumber() << «: «;
    cout << t.getValue() << » oC» << endl;
  }
};

int main()
{
  Sensor *h1 = new Sensor();
  TemperatureMeasure tc1(h1);
  for(int i=0; i<5; i++)
    tc1.setValue();
  ShowTemperature::Show(tc1);
  cout << endl;
  Sensor *h2 = new Sensor();
  TemperatureMeasure tc2(h2);
  for (int i = 0; i<5; i++)
    tc2.setValue();
  ShowTemperature::Show(tc2);
  cout << endl;
  cout << «Total: « << TemperatureMeasure::getTotal() << endl;
  cin.get(); cin.get();
  return 0;
}

Результат выполнения
Тестирование отношений классов
UML-диаграмма классов для приведенного выше кода будет выглядеть следующим образом:
UML-диаграмма классов
На диаграмме классов основным классом является класс TemperatureMeasure, который и является измерителем температуры. В качестве измеренного значения формируется среднее арифметическое всех измерений — сумма всех измерений, деленная на их количество.
Для получения измерений и их суммирования используется класс Sensor (в качестве датчика температуры). В консольной задаче сами измерения передаются в этот класс для суммирования. Класс состоит в отношении агрегации с основным классом TemperatureMeasure: мы сначала создаем объект класса Sensor, а потом передаем его в качестве параметра конструктора классу TemperatureMeasure, чтобы использовать его в качестве части класса.
Количество измерений формируется классом MeasureCount, который содержит статическое свойство total для подсчета общего измерений, а также свойство count для подсчета количества измерителей конкретного объекта TemperatureMeasure. Класс MeasureCount находится в отношении композиции с классом TemperatureMeasure: объект MeasureCount создается непосредственно при создании объекта TemperatureMeasure (в его конструкторе).
Класс ITemperatureMeasure представляет собой интерфейс класса TemperatureMeasure и является своего рода поставщиком в отношении реализации.
Наконец, класс ShowTemperature находится в отношении зависимости с классом TemperatureMeasure, поскольку реализация единственного метода Show класса ShowTemperature зависит от структуры класса TemperatureMeasure.

Назад: Алгоритмизация

Понравилась статья? Поделить с друзьями:
  • Как найти медиану списка чисел
  • Как составить уравнение параболы по картинке
  • Как найти игру дикий запад
  • No mans sky как найти живой корабль
  • Как найти лучших друзей в интернете