Architectural Styles

Как устроены системы: от монолита до событий

Что такое архитектурный стиль?

Шаблон организации компонентов и их взаимодействия

Как выбрать?

  • Размер команды
  • Масштабируемость
  • Отказоустойчивость
  • Скорость изменений

Мы рассмотрим:

MessagingEvent-Driven, Pub/Sub
DistributedClient-Server, P2P
StructuralMonolithic, Layered, Component-Based

1. Event-Driven Architecture

Система реагирует на события

🔹 Принцип

Произошло событие → система реагирует

Примеры: пользователь зарегистрировался, модель обучилась

✅ Пример: ML Pipeline

# Событие: данные обновились
event_bus.publish("data_updated", dataset_id)

# Обработчик 1: запускает переобучение
@on_event("data_updated")
def retrain_model(event):
    train_new_version(event.dataset_id)

# Обработчик 2: уведомляет команду
@on_event("data_updated")
def notify_team(event):
    send_slack("Новые данные — модель будет переобучена")

💡 Плюсы

  • Высокая масштабируемость
  • Гибкость: можно добавить новый обработчик
  • Отказоустойчивость: если один упал — другие работают

⚠️ Минусы

  • Сложнее отлаживать (цепочки событий)
  • Труднее тестировать
  • Нужна инфраструктура: Kafka, RabbitMQ

🎯 Когда использовать?

— Микросервисы
— Реактивные системы
— ETL, ML Pipelines

2. Publish-Subscribe

Один издатель → много подписчиков

🔹 Отличие от Event-Driven

Pub/Sub — это способ доставки событий

Publisher → Message Broker → [Subscriber A, Subscriber B]

✅ Пример: FastAPI + Redis

# Издатель
redis.publish("logs", "User logged in")

# Подписчик 1
pubsub = redis.pubsub()
pubsub.subscribe("logs")
for message in pubsub.listen():
    print("LOG:", message['data'])

# Подписчик 2 — другой сервис
pubsub.subscribe("logs")
for msg in pubsub.listen():
    analytics.track(msg)

💡 Плюсы

  • Полная децентрализация
  • Лёгко масштабировать обработку
  • Изоляция компонентов

⚠️ Минусы

  • Нет гарантии доставки (если не настроить)
  • Сложно отследить порядок сообщений
  • Брокер становится SPOF

🎯 Когда использовать?

— Логгирование
— Аналитика
— Push-уведомления

3. Client-Server

Один сервер обслуживает множество клиентов

🔹 Классика веба

Клиент → GET /api/predict
Сервер → { "result": 0.92 }

✅ Пример: ML API

@app.post("/predict")
def predict(input: Features):
    result = model.predict(input.values)
    return {"prediction": result}

Клиенты: фронтенд, мобильное приложение, скрипт

💡 Плюсы

  • Простота понимания
  • Легко масштабировать (load balancer)
  • Стандарты: HTTP, REST, JSON

⚠️ Минусы

  • Сервер — узкое место
  • Состояние обычно на сервере
  • Зависимость от сети

🎯 Когда использовать?

— Веб-API
— Инференс-сервисы
— Централизованные системы

4. Peer-to-Peer (P2P)

Все узлы равны — нет центрального сервера

🔹 Принцип

[Node A] ↔ [Node B] ↔ [Node C]
     ↖_____________↙

Каждый может быть клиентом и сервером

✅ Примеры

  • BitTorrent
  • Blockchain (например, Ethereum)
  • Distributed ML: federated learning
# Узел обучает локально
local_model = train_on_local_data()

# Отправляет обновление соседям
send_update_to_peers(local_model.delta)

💡 Плюсы

  • Нет единой точки отказа
  • Хорошо масштабируется
  • Работает без центрального сервера

⚠️ Минусы

  • Сложность координации
  • Разные версии данных
  • Безопасность: доверие к узлам

🎯 Когда использовать?

— Распределённые вычисления
— Файлообмен
— Конфиденциальное обучение (federated learning)

5. Monolithic Architecture

Всё в одном приложении

🔹 Структура

my-app/
  ├── main.py
  ├── models/
  ├── api/
  ├── workers/
  └── database.py

Один процесс, одна база, одно развертывание

✅ Пример: FastAPI + SQLAlchemy

# Один файл — всё вместе
@app.post("/train")
def train_endpoint():
    data = load_data()
    model = train(data)
    save_model(model)
    send_email()

💡 Плюсы

  • Простота старта
  • Легко отлаживать
  • Единая кодовая база

⚠️ Минусы

  • Растёт как "спагетти"
  • Трудно масштабировать
  • Один баг — падает всё

🎯 Когда использовать?

— Небольшие проекты
— MVP
— Команда из 1–3 человек

6. Layered Architecture

Слои: сверху вниз — UI, Use Cases, Domain, Infrastructure

🔹 Чёткие границы

┌─────────────────┐
│   Presentation  │ ← API, CLI
├─────────────────┤
│   Application   │ ← Use Cases
├─────────────────┤
│     Domain      │ ← User, Model, TrainingJob
├─────────────────┤
│ Infrastructure  │ ← DB, Email, HTTP
└─────────────────┘
       ↓
 Зависимости только вниз!

✅ Пример структуры

app/
  ├── presentation/
  │   └── api.py
  ├── application/
  │   └── usecases.py
  ├── domain/
  │   └── models.py
  └── infrastructure/
      ├── database.py
      └── email_client.py

💡 Плюсы

  • Чёткая организация
  • Легко находить код
  • Поддерживает DIP и защиту домена

⚠️ Минусы

  • Жёсткая структура
  • Может превратиться в "многослойный монолит"

🎯 Когда использовать?

— Большие приложения
— Команды > 3 человек
— Нужна долгосрочная поддерживаемость

7. Component-Based

Система как набор независимых компонентов

🔹 Отличие от слоёв

Компоненты группируются по домену, а не по типу

user/
  ├── models.py
  ├── service.py
  └── api.py

order/
  ├── models.py
  ├── service.py
  └── discount_calculator.py

💡 Плюсы

  • Легко выделить микросервис
  • Ясные границы
  • Команда владеет компонентом

⚠️ Минусы

  • Нужно следить за дублированием
  • Общие библиотеки — потенциальный хаос

🎯 Когда использовать?

— Подготовка к микросервисам
— Большие системы
— Domain-Driven Design

📊 Сравнение архитектурных стилей

Стиль Масштабируемость Сложность Где используется
Monolithic Низкая Низкая MVP, малые команды
Layered Средняя Средняя Большие приложения
Component-Based Высокая Высокая DDD, микросервисы
Event-Driven Очень высокая Очень высокая Реактивные системы
Client-Server Высокая Низкая Веб, API

🎯 Как выбирать?

Не "лучше/хуже", а "подходит/не подходит"

  • Команда 1 человек? → Monolith
  • Нужна реактивность? → Event-Driven
  • Готовы к сложности? → Component-Based

🎯 Что дальше?

Теперь вы понимаете, как устроены системы.


Следующие темы:

  • Architectural Patterns: MVC, Microservices, CQRS
  • Enterprise Patterns: Repository, DTO, Usecase
  • ORM & Prisma: как работать с БД без боли

"Архитектура — это не про технологии.
Это про принятие решений."