Модуль 04: Моделирование в UML — Практическое задание
Общая информация
Кейс: Проектирование ИТ-системы для каршеринга (поиск, бронирование и аренда автомобиля).
Цель задания: Применить три ключевые UML-диаграммы (Use Case, Sequence, Class) к одному сквозному кейсу, чтобы смоделировать систему каршеринга с разных точек зрения: функциональной (Use Case), процессной (Sequence) и структурной (Class).
Формат сдачи: Один документ (Markdown или PDF), содержащий:
- Задание 1: Use Case диаграмма (PlantUML-код или скриншот)
- Задание 2: PlantUML-код для Sequence диаграммы + описание
- Задание 3: Class диаграмма (PlantUML-код обязателен)
- Задание 4: Письменные ответы на вопросы рефлексии
Баллы: 10 баллов (распределение указано в каждом задании).
Кейс: Система каршеринга «Carsharing Now»
Контекст
Стартап «Carsharing Now» запускает сервис краткосрочной аренды автомобилей в крупном городе. Пользователи через мобильное приложение могут найти свободный автомобиль рядом, забронировать его, открыть через смартфон, доехать до цели и завершить аренду — оплата списывается автоматически за фактическое время использования.
Описание бизнес-процессов
Регистрация и верификация:
- Новый пользователь скачивает приложение и регистрируется (email/телефон + подтверждение)
- Пользователь загружает фото паспорта и водительского удостоверения
- Менеджер автопарка проверяет документы (вручную или через интеграцию с ГИБДД)
- После верификации пользователь может начать аренду
Аренда автомобиля:
- Пользователь открывает карту, видит свободные автомобили рядом
- Пользователь выбирает автомобиль, видит его характеристики (модель, цена, уровень топлива, пробег)
- Пользователь бронирует автомобиль (система резервирует его на 15 минут)
- Пользователь идёт к автомобилю, нажимает «Открыть» в приложении
- Бэкенд отправляет команду на телематический модуль автомобиля — двери открываются
- Пользователь садится, проверяет автомобиль (фотографирует повреждения, если есть)
- Пользователь нажимает «Начать поездку» — аренда запущена
- Система фиксирует время начала поездки и списывает деньги с карты (авторизация)
- Во время поездки телематический модуль передаёт телеметрию (координаты, скорость, уровень топлива)
- Пользователь паркуется в разрешённом месте и нажимает «Завершить поездку»
- Система фиксирует время окончания, рассчитывает стоимость (помингутно), списывает финальную сумму
- Пользователь может оставить отзыв о поездке
Управление автопарком (Менеджер):
- Менеджер может добавить новый автомобиль в систему (VIN, модель, госномер, телематический модуль)
- Менеджер может просматривать текущие и завершённые поездки
- Менеджер может установить тарифы (цена за минуту, за час, за сутки)
- Менеджер обрабатывает спорные ситуации (тикеты от пользователей — вернуть деньги, если машина была грязной)
- Менеджер видит дашборд: загруженность автопарка, доход, инциденты
Задание 1. Use Case Diagram (3 балла)
Постройте Use Case диаграмму для системы каршеринга «Carsharing Now».
Роли (актёры)
Обязательные актёры:
- Клиент (Client) — основной пользователь системы, арендует автомобили
- Менеджер автопарка (Fleet Manager) — сотрудник компании, управляет автопарком
- Дополнительные актёры, если необходимо (платёжная система, телематический модуль и т.д.)
Требования к диаграмме
- Определите System Boundary («Carsharing Now»)
- Выявите всех актёров:
- Клиент (Client) — все функции для аренды
- Менеджер автопарка (Fleet Manager) — администрирование
- Платёжная система (Payment Gateway) — внешняя система
- Телематический модуль (Telematics Unit) — оборудование в автомобиле (выступает как актёр)
- Администратор (если уместно)
- Выявите варианты использования (минимум 10, максимум 18)
- Укажите минимум:
- 2 отношения <> (обязательные шаги, например авторизация)
- 2 отношения <> (опциональные расширения, например страховка, отзыв)
- 1 обобщение актёров (если уместно)
- 1 обобщение прецедентов (если уместно)
- Точки расширения (Extension Points) хотя бы для одного из прецедентов с <>
- Названия Use Case — глагол + существительное, на русском языке (допустимо с английскими терминами в скобках)
Рекомендуемые Use Case
Для Клиента:
- Зарегистрироваться в системе
- Верифицировать документы
- Найти автомобиль на карте
- Просмотреть детали автомобиля
- Забронировать автомобиль
- Открыть автомобиль
- Начать поездку
- Завершить поездку
- Оплатить поездку (может быть <>)
- Оставить отзыв
- Создать тикет в поддержку
- Просмотреть историю поездок
Для Менеджера автопарка:
- Добавить автомобиль в систему
- Просмотреть отчёт по поездкам
- Установить тарифы
- Обработать тикет пользователя
- Заблокировать пользователя
Пример отношений (ориентир, не ограничивайтесь этим списком):
| Отношение | Тип | Пояснение |
|---|---|---|
| «Забронировать автомобиль» → «Авторизоваться» | <> | Авторизация обязательна для бронирования |
| «Начать поездку» → «Проверить завершённость предыдущей поездки» | <> | Система должна убедиться, что нет активных поездок |
| «Завершить поездку» → «Рассчитать стоимость» | <> | Расчёт стоимости — обязательный шаг завершения |
| «Начать поездку» ← «Застраховать поездку» | <> | Страховка — опциональное расширение (только для некоторых тарифов) |
| «Завершить поездку» ← «Загрузить фото повреждений» | <> | Опционально — если пользователь заметил повреждения |
| «Просмотреть отчёт по поездкам» ← «Экспортировать отчёт в Excel» | <> | Экспорт — опциональная функция |
Баллы
| Критерий | Баллы |
|---|---|
| Актёры выявлены корректно (включая внешние системы) | 0,5 |
| Use Case (10–18, логически верные названия) | 0,5 |
| <> (2+ отношения, корректное направление) | 0,5 |
| <> (2+ отношения, указаны условия и Extension Points) | 0,5 |
| Обобщение актёров и/или прецедентов | 0,5 |
| Читаемость: границы системы, актёры расставлены, связи не пересекаются | 0,5 |
| Итого за задание 1 | 3,0 |
Задание 2. Sequence Diagram (4 балла)
Напишите PlantUML-код для Sequence диаграммы процесса «Начало аренды автомобиля».
Сценарий
Пользователь уже забронировал автомобиль через приложение. Теперь он подошёл к машине и хочет начать аренду.
Описание шагов:
- Пользователь открывает приложение → видит активное бронирование
- Пользователь нажимает кнопку «Открыть автомобиль»
- Мобильное приложение отправляет POST-запрос на бэкенд:
/api/v1/rentals/{id}/open - Бэкенд проверяет:
- Активно ли бронирование (не истекли 15 минут)?
- Верифицирован ли пользователь?
- Нет ли задолженности за предыдущие поездки?
- Если проверка не пройдена — бэкенд возвращает ошибку (410 — бронирование истекло, 403 — не верифицирован, 402 — есть задолженность)
- Если проверка пройдена — бэкенд отправляет команду на Телематический модуль автомобиля:
POST /telematics/{carId}/unlock - Телематический модуль выполняет команду: разблокирует двери и включает питание бортового компьютера
- Телематический модуль возвращает статус:
{status: "unlocked", timestamp} - Бэкенд логирует событие в БД: INSERT в таблицу events (тип "car_unlocked")
- Бэкенд возвращает мобильному приложению:
200 OK {status: "unlocked", rentalId, carInfo} - Приложение показывает пользователю: «Автомобиль открыт, проверьте его состояние»
- Пользователь садится в автомобиль, проверяет салон
- Пользователь нажимает «Начать поездку»
- Приложение отправляет POST-запрос:
/api/v1/rentals/{id}/start - Бэкенд проверяет, что двери были открыты (есть событие «car_unlocked» в логе)
- Бэкенд обновляет статус бронирования → "IN_PROGRESS"
- Бэкенд отправляет команду телематическому модулю:
POST /telematics/{carId}/start-trip - Телематический модуль начинает сбор телеметрии (GPS, скорость, топливо)
- Телематический модуль возвращает:
{status: "trip_started", tripId} - Бэкенд создаёт запись о поездке в БД
- Бэкенд отправляет асинхронное событие
rental.startedв очереди сообщений (Kafka/RabbitMQ) - Параллельно: произвольный Service (Notification) получает событие и отправляет push-уведомление пользователю «Поездка начата! Счастливого пути!»
- Параллельно: Billing Service получает событие и авторизует сумму на карте пользователя (холд)
- Бэкенд возвращает приложению:
200 OK {rentalId, status: "in_progress", startTime} - Приложение показывает экран активной поездки (таймер, маршрут)
Участники
| Участник | Тип PlantUML | Описание |
|---|---|---|
| Пользователь | actor |
Клиент каршеринга |
| Мобильное приложение | participant |
Клиентское приложение (iOS/Android) |
| Бэкенд (Backend) | participant |
Серверная логика (API Gateway + Core) |
| База данных (PostgreSQL) | database |
Хранилище данных |
| Телематический модуль | participant |
Бортовое оборудование автомобиля |
| Очередь сообщений | collections |
Kafka / RabbitMQ |
| Notification Service | participant |
Сервис отправки уведомлений |
| Billing Service | participant |
Сервис платежей |
Требования к диаграмме
-
Фрагменты:
- Минимум 2 фрагмента
alt:alt[проверка пройдена] / [проверка не пройдена] (разблокировка)alt[двери открыты] / [двери не открыты] (начало поездки)
- Минимум 1 фрагмент
opt— для необязательного шага (например, проверка наличия события) - Минимум 1 фрагмент
par— параллельные уведомления после старта поездки (push + billing) - Минимум 1
break— прерывание сценария при ошибке (если бронирование истекло) - Минимум 1
ref— ссылка на подпроцесс (например, «Проверить статус бронирования»)
- Минимум 2 фрагмента
-
Типы сообщений:
- Синхронные HTTP-вызовы:
->(мобильное приложение → бэкенд, бэкенд → телематический модуль) - Асинхронное сообщение:
->>(бэкенд → очередь сообщений) - Self-вызов:
бэкенд -> бэкенд: проверить()(внутренняя логика) - Возвраты:
-->с указанием HTTP-статусов (200, 403, 410, 402)
- Синхронные HTTP-вызовы:
-
Activation Bar:
activate/deactivateдля каждого участника при получении/завершении запроса- Activation Bars должны быть закрыты (нет «висящих»)
-
Детали:
- Явно указать URL эндпоинтов:
/api/v1/rentals/{id}/open,/api/v1/rentals/{id}/start - Явно указать HTTP-статусы на возвратах:
200 OK,403 Forbidden,410 Gone,402 Payment Required - Использовать
noteдля пояснений ключевой логики (как минимум 2 заметки) - Использовать
===для разделения логических блоков («Блокировка» / «Старт поездки»)
- Явно указать URL эндпоинтов:
Баллы
| Критерий | Баллы |
|---|---|
| Все участники объявлены с корректными типами (actor, participant, database, collections) | 0,5 |
| Activation / Deactivation для каждого вызова (нет «висящих») | 0,5 |
alt фрагменты (2+) с корректными условиями и полным покрытием |
0,5 |
opt, par, break, ref фрагменты присутствуют |
0,5 |
| Асинхронное сообщение в очередь (->>) | 0,5 |
| HTTP-статусы и URL эндпоинтов указаны | 0,5 |
Параллельный par блок с двумя разными сервисами (Notification и Billing) |
0,5 |
| Код компилируется в PlantUML без ошибок | 0,5 |
| Итого за задание 2 | 4,0 |
Шаблон для старта
@startuml
skinparam backgroundColor #FEFEFE
title Процесс "Начало аренды автомобиля"
' ===== Участники =====
actor "Пользователь" as user
participant "Мобильное\nприложение" as app
participant "Бэкенд\n(Backend)" as backend
database "PostgreSQL" as db
participant "Телематический\nмодуль" as telematics
collections "Очередь\nсообщений" as queue
participant "Notification\nService" as notif
participant "Billing\nService" as billing
' ===== Ваш код здесь =====
@enduml
Задание 3. Class Diagram (3 балла)
Спроектируйте Class Diagram для системы каршеринга «Carsharing Now». Ограничьтесь четырьмя ключевыми сущностями: Пользователь (User), Автомобиль (Car), Поездка (Rental), Транзакция (Transaction).
Классы
1. User (Пользователь)
Обязательные атрибуты:
+ id: UUID
- email: String {unique}
- phone: String {unique}
- firstName: String
- lastName: String
- passwordHash: String
- status: UserStatus
- driverLicense: String? {optional}
- passportData: JSON? {optional}
- isVerified: Boolean
- rating: Decimal {range 0..5}
- createdAt: DateTime
- updatedAt: DateTime
2. Car (Автомобиль)
Обязательные атрибуты:
+ id: UUID
- vin: String {unique}
- brand: String
- model: String
- year: Int
- color: String
- licensePlate: String {unique}
- fuelType: FuelType
- fuelLevel: Decimal {range 0..100}
- transmission: TransmissionType
- dailyRate: Decimal
- hourlyRate: Decimal
- minuteRate: Decimal
- status: CarStatus
- latitude: Decimal? {optional}
- longitude: Decimal? {optional}
- lastMaintenanceAt: DateTime?
- createdAt: DateTime
3. Rental (Поездка / Бронирование)
Обязательные атрибуты:
+ id: UUID
- status: RentalStatus
- startTime: DateTime?
- endTime: DateTime?
- startLatitude: Decimal?
- startLongitude: Decimal?
- endLatitude: Decimal?
- endLongitude: Decimal?
- totalMinutes: Int?
- totalAmount: Decimal?
- discount: Decimal
- finalAmount: Decimal?
- createdAt: DateTime
- updatedAt: DateTime
4. Transaction (Транзакция)
Обязательные атрибуты:
+ id: UUID
- type: TransactionType
- amount: Decimal
- currency: String {default: "RUB"}
- status: TransactionStatus
- paymentMethod: PaymentMethod
- gatewayTransactionId: String? {optional}
- gatewayResponse: JSON? {optional}
- description: String?
- createdAt: DateTime
Перечисления (Enum)
Создайте следующие перечисления и привяжите их к соответствующим атрибутам:
enum UserStatus {
PENDING_VERIFICATION
ACTIVE
BLOCKED
DELETED
}
enum CarStatus {
AVAILABLE
BOOKED
IN_USE
MAINTENANCE
OUT_OF_SERVICE
}
enum FuelType {
GASOLINE
DIESEL
ELECTRIC
HYBRID
}
enum TransmissionType {
MANUAL
AUTOMATIC
ROBOTIC
}
enum RentalStatus {
RESERVED
IN_PROGRESS
COMPLETED
CANCELLED
DISPUTED
}
enum TransactionType {
AUTHORIZATION_HOLD
CHARGE
REFUND
PENALTY
BONUS
}
enum TransactionStatus {
PENDING
SUCCEEDED
FAILED
REFUNDED
CANCELLED
}
enum PaymentMethod {
CREDIT_CARD
DEBIT_CARD
APPLE_PAY
GOOGLE_PAY
SBP
}
Связи между классами
Определите и обоснуйте связи между четырьмя классами:
| Класс A | Класс B | Тип связи | Кратность | Пояснение |
|---|---|---|---|---|
| User | Rental | ? | ? — ? | Пользователь совершает поездки |
| Car | Rental | ? | ? — ? | Автомобиль участвует в поездках |
| Rental | Transaction | ? | ? — ? | Поездка имеет транзакции |
| User | Transaction | ? | ? — ? | Пользователь совершает платежи |
Ваша задача: определить для каждой связи:
- Тип (Association / Aggregation / Composition)
- Кратность на обоих концах
- Роль (название связи) — опционально
- Обоснование — почему вы выбрали именно этот тип и эту кратность
Дополнительно (опционально, +бонус)
Добавьте наследование: User △ AdminUser (администратор с правом блокировки пользователей и управления тарифами).
Баллы
| Критерий | Баллы |
|---|---|
| Класс User — все атрибуты с корректными типами и модификаторами | 0,25 |
| Класс Car — все атрибуты с корректными типами и модификаторами | 0,25 |
| Класс Rental — все атрибуты с корректными типами и модификаторами | 0,25 |
| Класс Transaction — все атрибуты с корректными типами и модификаторами | 0,25 |
| Перечисления (enum) — все 7 перечислений корректно определены | 0,5 |
| Связь User — Rental: корректный тип и кратность + обоснование | 0,25 |
| Связь Car — Rental: корректный тип и кратность + обоснование | 0,25 |
| Связь Rental — Transaction: корректный тип и кратность + обоснование | 0,25 |
| Связь User — Transaction: корректный тип и кратность + обоснование | 0,25 |
| PlantUML-код компилируется, все связи отражены | 0,5 |
| Итого за задание 3 | 3,0 |
Задание 4. Рефлексия и анализ (0 баллов, но обязательно для получения оценки)
Ответьте письменно на вопросы (2–4 предложения на каждый):
-
Наследование в Use Case (Задание 1): На одной из ваших связей актёров или прецедентов есть обобщение (Generalization). Объясните, почему вы его применили. В чём разница между родительским и дочерним прецедентом / актёром?
-
Extension Points (Задание 1): У одного из ваших Use Case указана точка расширения. При каких условиях срабатывает <>? Что произойдёт, если условие не выполнено?
-
Composition vs Aggregation (Задание 3): Какая из четырёх связей (User → Rental, Car → Rental, Rental → Transaction, User → Transaction), по вашему мнению, наиболее близка к Composition? А какая — к простой Association? Обоснуйте.
-
Sequence vs Activity (Задание 2): Почему для сценария «Начало аренды» мы выбрали Sequence Diagram, а не Activity Diagram? В каких случаях вы бы использовали Activity для этого же кейса?
-
Связь диаграмм: Как диаграммы из Заданий 1, 2 и 3 связаны между собой? Приведите пример: какой элемент из Use Case превращается в Sequence, а какой результат Sequence ложится в Class?
Критерии оценки (суммарно 10 баллов)
| Задание | Тема | Макс. балл |
|---|---|---|
| 1 | Use Case Diagram | 3,0 |
| 2 | Sequence Diagram (PlantUML) | 4,0 |
| 3 | Class Diagram (PlantUML) | 3,0 |
| 4 | Рефлексия (письменно) | обязательно |
| Итого | 10,0 |
Шкала оценивания
| Баллы | Оценка |
|---|---|
| 9,0–10,0 | Отлично. Все диаграммы логически корректны, PlantUML-код компилируется, связи верны, обоснования убедительны. |
| 7,0–8,9 | Хорошо. Есть незначительные ошибки (пропущен один актёр, не хватает одного фрагмента, кратность не на обоих концах). |
| 5,0–6,9 | Удовлетворительно. Существенные ошибки (не хватает 2+ ключевых элементов, PlantUML не компилируется, связи перепутаны). |
| 0–4,9 | Требуется доработка. Диаграммы не соответствуют заданию, отсутствуют ключевые элементы, код не рабочий. |
Дополнительные критерии (могут повысить/понизить балл)
| Критерий | Влияние |
|---|---|
| PlantUML-код компилируется без ошибок | +0,5 (к любому заданию, если код рабочий) |
| Использованы продвинутые элементы (Extension Points, обобщение прецедентов, вложенные alt, несколько par) | +0,5 |
| Диаграммы нарисованы от руки сфотканы (нечитаемо) | −1,0 |
| Скопировано из интернета без адаптации под кейс | задание не засчитывается |
| Письменные обоснования по Заданию 4 отсутствуют | −1,0 от общей суммы |
Требования к оформлению
- Формат: Markdown (
.md) или PDF. - Именование файла:
Модуль04_ФамилияИО.mdилиМодуль04_ФамилияИО.pdf - Для Заданий 2 и 3: PlantUML-код обязателен. Код должен быть расположен в блоках
plantuml .... - Для Задания 1: Допустимо нарисовать в Draw.io / Lucidchart / на бумаге и приложить скриншот, но PlantUML-код приветствуется.
- Критично: Все диаграммы должны быть авторскими. Копирование готовых решений из интернета без адаптации под кейс карается незачётом задания.
Советы для успешного выполнения
Задание 1 (Use Case)
- Не путайте <> и <>. Помните: <> — «обязательно», <> — «иногда, по условию».
- Extension Point — это место внутри прецедента, где может быть вставлено расширение. Запишите его в виде
[Условие: Клиент выбрал расширенную страховку]внутри овала прецедента. - Актёр «Телематический модуль» — это внешняя система (автомобиль). Не забудьте его.
- Обобщение актёров: возможно, у вас есть «Администратор» (общий) и «Менеджер автопарка» (частный случай). Или «Пользователь» (общий) и «Клиент» (частный случай).
Задание 2 (Sequence)
- Используйте вложенные
altдля разных проверок. Например, первыйalt— «проверка пройдена?», внутри второгоalt— «двери открыты?». - Не забудьте про
breakпри фатальной ошибке (бронирование истекло, пользователь заблокирован). - Для
par— два разных сервиса: Notification и Billing. Убедитесь, что они получают сообщение из очереди, а не синхронно от бэкенда. - Проверьте, что каждый
activateимеет соответствующийdeactivate. Лишние или пропущенные активации — типичная ошибка.
Задание 3 (Class)
- Внимательно выберите тип связи для
Rental → Transaction. Это Composition? Агрегация? Или просто Association? Обоснуйте. - Не забудьте кратность на обоих концах связи.
User 1 — 0..* Rental— это верно (один пользователь → много поездок). А с другой стороны:Rental 0..1 — 1 User? ИлиRental * — 1 User? - Для
Car → Rental: автомобиль может быть в поездках. Одна поездка — один автомобиль. Один автомобиль — много поездок (но не одновременно). Какую кратность поставить у Car? - Enum'ы в PlantUML пишутся как
enum Name { VALUE1; VALUE2 }. Подключите их к атрибутам классов через указание типа, например- status: UserStatus.
Пример структуры ответа
Модуль 04 — Практическое задание
ФИО: Иванов Иван Иванович
=== Задание 1. Use Case Diagram ===
[PlantUML-код или скриншот]
=== Задание 2. Sequence Diagram ===
[PlantUML-код]
=== Задание 3. Class Diagram ===
[PlantUML-код]
=== Задание 4. Рефлексия ===
1. [Ответ на вопрос о наследовании в Use Case]
2. [Ответ на вопрос об Extension Points]
3. [Ответ на вопрос о Composition vs Aggregation]
4. [Ответ на вопрос о Sequence vs Activity]
5. [Ответ на вопрос о связи диаграмм]
Удачи! Помните: UML — это язык коммуникации. Ваша задача — сделать диаграммы, которые будут понятны команде (разработчикам, архитекторам, QA) и заказчику.