← Назад к вопросам

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

1.0 Junior🔥 121 комментариев
#Диаграммы и моделирование#Опыт работы и проекты

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI26 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

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

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

Почему связи важны

Без связей разработчики гадают:

  • "Таблица User связана с таблицей Order. Это one-to-many или many-to-many?"
  • "Если удалить User, что с его Orders? Удалить или оставить?"
  • "Какое поле в таблице Order ссылается на User? user_id или owner_id?"

Это приводит к ошибкам в БД и коде.

С связями всё ясно.

Пример: E-commerce система

Диаграмма классов с связями

┌──────────────────────────┐
│       USER               │
├──────────────────────────┤
│ - id: UUID (PK)          │
│ - email: String          │
│ - name: String           │
│ - created_at: DateTime   │
├──────────────────────────┤
│ + register()             │
│ + updateProfile()        │
└──────────┬───────────────┘
           │
           │ 1 пользователь
           │ * много заказов
           │ (one-to-many)
           │ Cascade delete: YES
           │ (если удалить User → удалить его Orders)
           │
           v
┌──────────────────────────┐
│      ORDER               │
├──────────────────────────┤
│ - id: UUID (PK)          │
│ - user_id: UUID (FK)     │ ← ссылка на User
│ - total_price: Decimal   │
│ - status: Enum           │
│ - created_at: DateTime   │
├──────────────────────────┤
│ + cancel()               │
│ + trackOrder()           │
└──────────┬───────────────┘
           │
           │ 1 заказ
           │ * много товаров в заказе
           │ (one-to-many)
           │ Cascade delete: YES
           │
           v
┌──────────────────────────┐
│     ORDER_ITEM           │
├──────────────────────────┤
│ - id: UUID (PK)          │
│ - order_id: UUID (FK)    │ ← ссылка на Order
│ - product_id: UUID (FK)  │ ← ссылка на Product
│ - quantity: Int          │
│ - unit_price: Decimal    │
├──────────────────────────┤
│ + getTotal()             │
└──────────┬───────────────┘
           │
           │ Many товаров
           │ Many заказов
           │ (many-to-many через таблицу ORDER_ITEM)
           │ Cascade delete: RESTRICT
           │ (если удалить Product, оставить ORDER_ITEM с price)
           │
           v
┌──────────────────────────┐
│      PRODUCT             │
├──────────────────────────┤
│ - id: UUID (PK)          │
│ - name: String           │
│ - price: Decimal         │
│ - stock: Int             │
│ - category_id: UUID (FK) │ ← ссылка на Category
├──────────────────────────┤
│ + updateStock()          │
│ + updatePrice()          │
└──────────┬───────────────┘
           │
           │ Many products
           │ 1 category
           │ (many-to-one)
           │ Cascade delete: RESTRICT
           │
           v
┌──────────────────────────┐
│     CATEGORY             │
├──────────────────────────┤
│ - id: UUID (PK)          │
│ - name: String           │
│ - description: String    │
├──────────────────────────┤
│ + updateName()           │
└──────────────────────────┘

Типы связей

1. One-to-Many (1:*)

  • User → Orders: один пользователь может иметь много заказов
  • Обозначение: user_id в таблице Orders
  • На диаграмме: стрелка из User в Order

2. Many-to-One (*:1)

  • Products → Category: много товаров в одной категории
  • Обозначение: category_id в таблице Products
  • На диаграмме: стрелка из Product в Category

3. Many-to-Many (:)

  • Products ↔ Orders: много товаров в много заказов
  • Обозначение: промежуточная таблица OrderItem
  • На диаграмме: две стрелки (Product → OrderItem, Order → OrderItem)

4. One-to-One (1:1)

  • Когда User имеет ровно один Profile
  • Обозначение: user_id UNIQUE в таблице Profile
  • На диаграмме: одна стрелка с пометкой "1..1"

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

Cascade Delete (DELETE)

Если удалить User → удалить все его Orders

Когда использовать:
- User удалён → его заказы теряют смысл
- Comment удален → его replies не имеют смысла

Когда НЕ использовать:
- User удален → сохранить его Orders (для истории)
- Product удалён → сохранить OrderItems (для финансов)

Restrict (RESTRICT)

Если Product имеет OrderItems → его нельзя удалить

Когда использовать:
- Product в истории заказов → важно сохранить для аудита
- Удаляй только через soft delete (флаг is_deleted)

Ошибка: если забыть RESTRICT, удалишь Product → потеряешь информацию о том, что был заказан

Set Null (SET NULL)

Если удалить Manager → в таблице Employee поле manager_id = NULL

Когда использовать:
- Employee может не иметь Manager
- Manager уходит → Employee остаются, но без Manager

Как я документирую связи

В диаграмме + в описании

ОРДЕР → ТОВАР

Тип связи: Many-to-Many
Промежуточная таблица: order_items

Поля:
- order_items.order_id (FK → orders.id)
- order_items.product_id (FK → products.id)

Ограничения:
- order_items.quantity >= 1
- order_items.unit_price >= 0

Каскадное удаление:
- Если удалить order → delete all order_items (CASCADDE DELETE)
- Если удалить product → сохранить order_items (SET NULL на product_id или RESTRICT)

Оптимизация:
- Индекс на order_id (для поиска товаров в заказе)
- Индекс на product_id (для поиска в каких заказах этот товар)

Реальный пример из моей практики

Проект: CRM система

Я забыл указать в диаграмме:

  • Может ли Contact иметь много Organizations?
  • Может ли Organization иметь много Contacts?
  • Это many-to-many?

Разработчики гадали неделю, потом спросили меня.

Оказалось:

  • Один Contact → работает в одной Organization (1:1 или много:1)
  • Но Contact может иметь много Emails, много Phones (1:many)

Я переделал диаграмму, добавил:

Contact ← Organization (many-to-one)
Contact → Email (one-to-many, cascade delete)
Contact → Phone (one-to-many, cascade delete)

Результат: разработчики написали БД правильно с первой попытки.

Инструменты для диаграмм

draw.io (рекомендую)

Быстро рисуешь классы и связи
Прямые стрелки, пометки 1:*, cascade
Экспортируешь в PNG/SVG

Lucidchart

Формальнее, с правильной UML нотацией
Но сложнее и платнее

PlantUML (для текстовых документов)

@startuml
class User {
  - id: UUID
  - email: String
}

class Order {
  - id: UUID
  - user_id: UUID
}

User "1" -- "*" Order : has
@enduml

Частые ошибки при рисовании связей

Ошибка 1: Не указать направление

❌ User ←→ Order (непонятно, кто referenced кого)
✅ User ← Order (Order.user_id ссылается на User.id)

Ошибка 2: Забыть промежуточную таблицу

❌ User ↔ Product (many-to-many без таблицы)
✅ User → Order_Product ← Product (через промежуточную таблицу)

Ошибка 3: Не указать cascade delete

❌ User ← Order (непонятно, что случится при удалении User)
✅ User ← Order [CASCADE DELETE]

Ошибка 4: Забыть foreign key

❌ Order таблица, но нет user_id поля
✅ Order таблица с user_id (FK) полем

Вывод

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

✅ Все таблицы (классы) и поля ✅ Первичные ключи (PK) ✅ Внешние ключи (FK) с названием поля ✅ Тип связи (1:*, :, 1:1) ✅ Cascade delete правила ✅ Текстовое описание для неясных связей

Это экономит часы переделок, потому что разработчик сразу понимает, что нужно реализовать.

Прописывал ли связи в диаграмме классов? | PrepBro