Спринт 12/18: Архитектура системы → Тема 4/6: Моделирование архитектуры → Урок 1/2
Диаграмма компонентов (UML Component Diagram)
В предыдущих уроках этого спринта вы познакомились с самыми распространёнными архитектурными стилями ПО. В этом уроке вы познакомитесь с диаграммой компонентов — одним из способов изображения архитектуры ПО.
Айгуль
Ксения скинула нам на почту документацию Otium. Видел?
Даня
Да! И уже заметил там своё любимое слово 🤪
Айгуль
«Диаграмма»?
Даня
Да! Кажется, нужно твоё объяснение.
Айгуль
Легко! Начнём с диаграммы компонентов.
Диаграмма компонентов
Диаграмма компонентов — это способ представления архитектуры ПО. Она используется для визуализации того, как организованы компоненты системы и их отношения.
В контексте этого урока компонент — это часть программного кода (исходного, двоичного, исполняемого) или его эквивалентов (скриптов, командных файлов, библиотек, таблиц). Набор компонентов позволяет программному обеспечению выполнять свои функции.
Диаграммы компонентов часто входят в состав проектной документации. Как правило, системный аналитик не составляет диаграммы компонентов сам, но он должен понимать, что на них изображено. Они позволяют архитектору, системному аналитику и разработчику убедиться, что все функции ПО могут выполняться его компонентами. Ценность диаграммы компонентов для архитектора и разработчиков так же важна, как карта для туриста, составляющего маршрут по городу: диаграмма компонентов позволяет сориентироваться в архитектуре ПО и принимать решения о том, как его менять.
Для составления диаграммы компонентов используется уже известная вам по предыдущим спринтам нотация UML.
Элементы диаграммы
Стандартная диаграмма компонентов состоит из следующих элементов:
Компоненты (Components).
Пакеты (Packages).
Интерфейсы (Interfaces).
Отношения (Relationships).
Рассмотрим каждый элемент диаграммы на примере одной из функций приложения по доставке цветов и подарков.
Компоненты
В нотации UML компоненты представляют собой достаточно независимые части системы. Каждый из них выполняет свою функцию, а вместе они выполняют функции ПО.
Компонент, как элемент модели, может иметь разные формы: это может быть сервис, файл, таблица или библиотека. В предыдущих уроках вы познакомились с такими частями ПО, как промежуточное ПО для обмена сообщениями (Messaging middleware) и слой интерфейса программирования приложения (Application Programming Interface — API Layer). Эти части ПО на диаграмме также представляют в виде компонентов.
Формат компонента можно описать с помощью текстовых стереотипов. Стереотип может указывать на тип компонента. Например:
Исполняемый файл (executable) — это разновидность компонента, который представлен в виде файла с исполняемым кодом.
Источник (source) — это разновидность компонента, который представлен в виде файла с исходным кодом.
Библиотека (library)
База данных (dataBase)
Хранилище данных (storage)
Также стереотип может описывать назначение компонента: вызов (сall), создание (create), отправка (send). Если тип компонента не указывается при составлении диаграммы, такой компонент будет иметь стереотип component.
Для изображения компонента используется прямоугольник с символом компонента (его обозначают в правом верхнем углу в виде маленького прямоугольника с двумя скобами слева). У каждого компонента должно быть название. Стереотип размещают в двойных угловых скобках (<<>>) над названием компонента.
Например, приложение по доставке цветов должно дать возможность пользователю найти нужный товар, заказать его и оплатить. Предположим, что оно включает четыре компонента, где компонент «Товары» ещё и база данных.
Один компонент может содержать несколько других компонентов. Например, компонент «Товары» может состоять из компонента с исполняемым программным кодом «Добавление товаров» и базы данных «Товары»:
Пакеты
Разные элементы диаграммы компонентов группируют в пакеты. Например, несколько сервисов можно объединить в один пакет. С помощью пакетов можно показать слои ПО или его компоненты, а также улучшить читаемость диаграммы.
Элемент «Пакет» изображается на диаграмме в виде прямоугольника со вкладкой в левом верхнем углу. Название каждого пакета описывает его содержимое. Оно должно быть уникальным, то есть не дублировать название других элементов диаграммы.
Допустим, для работы приложения используются различные библиотеки: для форматирования данных, для логирования, для улучшения проведения запросов между компонентами и прочее. Их можно выделить в отдельный пакет.
Чтобы отобразить слой хранилища данных на диаграмме, базы данных и хранилище изображений для баннеров группируют в пакет.
Интерфейс
Чтобы выполнять свои функции, компоненты могут взаимодействовать друг с другом. Они делают это с помощью интерфейса. В диаграмме компонентов выделяют два вида интерфейсов:
Предоставляемый интерфейс. Как следует из названия, компонент предоставляет свой интерфейс для того, чтобы другие компоненты могли получить необходимые данные. Графически предоставляемый интерфейс изображается в виде круга, соединённого с компонентом прямой линией.
Требуемый интерфейс. Компонент запрашивает интерфейс у других компонентов для взаимодействия с ними. Графически представляется в виде полусферы (или «лапки»), соединённой прямой линией с компонентом. Описание интерфейса располагается под линией.
Например, компонент «Заказы» для выполнения своих функций должен иметь информацию о каждом товаре в заказе. Поэтому он требует от других компонентов предоставить ему интерфейс для доступа к этим данным. При этом сам компонент содержит разные детали заказов и может предоставить эту информацию другим компонентам.
Обратите внимание, что один и тот же компонент может одновременно иметь несколько требуемых и предоставляемых интерфейсов.
Отношения
Отношения — это элемент диаграммы компонентов, который определяет, какие компоненты взаимодействуют друг с другом для осуществления своих функций и как они это делают. Есть несколько типов отношений между компонентами:
Отношения абстракции Это связь между элементами модели, которые представляют одно и то же понятие на разных уровнях абстракции или с разных точек зрения. Например, один компонент модели может быть связан отношением абстракции с другим компонентом модели, который менее детализирован. Отношения абстракции изображаются в виде стрелки с пунктирной линией и открытым наконечником.
Отношения ассоциации Связь между двумя компонентами может быть конкретной. То есть можно одним глаголом описать, что происходит между компонентами. Например, глаголом «импортировать», «объединить» или «делегировать». На диаграмме такая связь обозначается стрелкой со сплошной линией, над которой подписывают действие.
Отношения с реализованным интерфейсом
Этот тип обозначает связь между одним компонентом и интерфейсом, который предоставляет другой компонент. Такая связь обозначается пунктирной линией с полым наконечником в виде стрелки.
Отношения реализации
Такой тип связи возникает между элементами модели, если поведение одного элемента зависит от поведения другого элемента. Отношения реализации на диаграмме обозначаются так же, как и отношения с реализованным интерфейсом. Однако при типе «Отношения реализации» взаимодействие происходит без участия интерфейса.
Отношения использования
Если для функционирования компонента требуется другой компонент, то между такими элементами модели устанавливается связь использования. То есть работа одного компонента полностью зависит от работы другого компонента. Это самая тесная связь между компонентами. Чтобы обозначить её графически, используется стрелка с пунктирной линией и открытым наконечником, сверху над ней помещается надпись <<use>>.
Рассмотрим примеры разных типов отношений. Отношения между компонентом «Поиск» и пакетом библиотек будут абстрактными, так как уровень детализации компонентов разный.
Рассмотрим другой тип связи. Компонент «Поиск» осуществляет функцию поиска товаров по разным параметрам, а компоненту «Заказы» нужно получить детальную информацию о товарах, которые входят в заказ. В итоге обоим компонентам требуется интерфейс, который предоставит им данные о товаре. Этот интерфейс предоставляет компонент «Товары».
Компоненты «Поиск» и «Заказы» будут использовать интерфейс компонента «Товары», а значит, компоненты «Поиск» и «Заказы» устанавливают отношения через реализованный интерфейс с компонентом «Товары».
Внутренняя структура компонента
Уровень детализации модели можно увеличить с помощью дополнительных элементов диаграммы компонентов. Таким образом можно, например, показать внутреннюю структуру компонента.
В примере выше один компонент включает в себя несколько компонентов (речь про компонент «Товары», который состоит из компонента с исполняемым кодом «Добавление товаров» и базы данных «Товары»). Для детализации можно показать не только состав компонента, но и то, как его внутренние элементы взаимодействуют между собой.
Такой многосоставный компонент всегда взаимодействует с внешней средой с помощью портов — квадратов, которые расположены по периметру компонента.
Порт показывает, как предоставляемый или требуемый интерфейс соотносятся с внутренними компонентами. Таким образом, порт отделяет внутреннее устройство компонента от внешней среды.
Допустим, что компонент «Товары» выполняет две функции: предоставляет информацию о товарах и формирует подборку рекомендуемых товаров пользователям.
Для предоставления информации о товаре через порт нужно обратиться к компоненту «Карточка товара». Между портом и компонентом устанавливается отношение ассоциации — <<delegate>> (делегировать). Работа компонента «Карточка товара» напрямую зависит от трёх баз данных: «Цветы», «Шарики» и «Песни». Компонент «Карточка товара» связан с каждой из этих баз данных отношениями использования.
В карточке товара могут присутствовать рекомендации — товары, которые могут быть интересны пользователю. Для этого компонент «Карточка товара» с помощью интерфейса «Рекомендации» должен получить данные от компонента «Рекомендуемые товары». Но компонент «Рекомендуемые товары» также зависит от других компонентов ПО, которые находятся за пределами общего компонента «Товары». Поэтому отношение ассоциации <<delegate>> (делегировать) создаётся с требуемым интерфейсом «Профиль рекомендаций» через порт.
Стили архитектуры на диаграмме компонентов
Даня
Наверное, у каждого стиля диаграммы по-разному выглядят?
Айгуль
Ага! Давай посмотрим на диаграммы компонентов тех стилей, что мы разбирали 😇
Расположение компонентов на диаграмме позволяет определить, в каком архитектурном стиле разработано ПО. Рассмотрим, как на диаграмме компонентов выглядят уже известные вам монолитные и распределённые стили архитектуры.
Многослойный стиль
В многослойной архитектуре ПО, как правило, разделено на четыре элемента, которые называются слоями. Слои выполняют определённые функции ПО, взаимодействуя с другими слоями, но не с компонентами этих слоёв.
Для изображения слоя на диаграмме компонентов используется элемент «Пакет». Поэтому для обозначения взаимодействия слоёв между пакетами устанавливаются отношения. Пакет может включать в себя несколько вложенных пакетов (да-да, пакет с пакетами) и компонентов.
Допустим, приложение по доставке цветов и подарков спроектировано в многослойном архитектурном стиле. На диаграмме изображены четыре пакета, каждый из которых соответствует определённому слою. Слои взаимодействуют только друг с другом. Внутри бизнес-слоя существуют компоненты, которые отвечают за определённые функции ПО, но компонент «Товары», например, не может напрямую обратиться к базе данных «Товары». Взаимодействие осуществляется через слой доступа к данным.
Сервис-ориентированный стиль
Сервис, как вы помните, — основной элемент сервис-ориентированной архитектуры. Принадлежащие к одному виду сервисы объединяются в группы. На диаграмме сервисы изображаются в виде компонентов со стереотипом <<service>>. Сервисы могут группироваться по типу, например: инфраструктурные сервисы могут быть сгруппированы в один компонент.
Ещё одна важная отличительная особенность сервис-ориентированной архитектуры — наличие промежуточного ПО для обмена сообщениями. На диаграммах оно обозначается в виде компонента с аббревиатурой ESB (Enterprise service bus).
Если приложение по доставке цветов и подарков спроектировано в сервис-ориентированном архитектурном стиле, диаграмма компонентов будет выглядеть так:
На диаграмме присутствует компонент, который является промежуточным ПО, — ESB. Через это промежуточное ПО происходит взаимодействие с сервисами предприятия ПО.
Каждый сервис предприятия имеет запрашиваемый и требуемый интерфейс, который позволяет им обмениваться сообщениями с промежуточным ПО.
На диаграмме может присутствовать общее хранилище данных, при этом каждый сервис может иметь и своё собственное хранилище.
Микросервисный стиль
На диаграмме компонентов ПО, которое спроектировано в микросервисном стиле, есть две отличительные особенности:
Наличие слоя API, который осуществляет взаимодействие между клиентом и сервисами. Этот промежуточный слой представлен в виде компонента.
Взаимодействие сервисов между собой. В этом архитектурном стиле сервисы взаимодействуют друг с другом, поэтому на диаграмме компонентов будут присутствовать как отношения с реализованным интерфейсом, так и отношения реализации. На диаграмме компонентов также может изображаться внутреннее устройство микросервиса, поэтому для такой диаграммы характерно наличие портов у компонентов.
Допустим, приложение по доставке цветов и подарков спроектировано в микросервисном архитектурном стиле. На диаграмме присутствует слой API, микросервисы с большим количеством требуемых и предоставляемых интерфейсов. Обратите внимание, что у микросервиса «Товары» своя база данных «Товары». Поэтому, чтобы получить информацию, сервис «Поиск» должен обратиться к микросервису «Товары», прямого доступа к этой базе данных у него нет.
Подведём итоги
Диаграмма компонентов — это способ представления архитектуры ПО. Она используется для визуализации того, как организованы компоненты ПО и их отношения. Для составления диаграммы используется нотация UML.
Элементы нотации UML, которые используются для построения диаграммы компонентов:
Компонент — часть программного кода (исходного, двоичного, исполняемого) или его эквивалентов (скриптов, командных файлов, библиотек, таблиц). Набор компонентов позволяет программному обеспечению выполнять свои функции.
Пакет — сгруппированные элементы диаграммы компонентов. В один пакет, например, можно объединить несколько сервисов. Используется для обозначения слоёв или элементов развёртывания ПО.
Интерфейс — способ взаимодействия компонентов между собой. Делятся на два вида: предоставляемый интерфейс и требуемый интерфейс.
Порт — показывает, как предоставляемый или требуемый интерфейс компонента соотносится с внутренними элементами компонента.
Отношения — элемент диаграммы компонентов, который определяет, какие элементы взаимодействуют друг с другом для осуществления своих функций.
Системный аналитик не составляет диаграмму компонентов самостоятельно, но должен уметь читать и анализировать её, чтобы участвовать в обсуждении архитектуры.
Чтобы вам было проще запомнить основные элементы диаграммы компонентов, воспользуйтесь этой памяткой.