Назад к вопросам
Senior
120
questionbank

Что такое CQRS и как эта модель может быть применена в разработке?

Sobes Copilot

Получайте ответы в реальном времени

Ответ от нейросети

sobes.tech AI

CQRS (Command Query Responsibility Segregation) — это шаблон архитектуры, разделяющий операции чтения (Queries) и записи (Commands) данных. Эта модель может быть применена для:

  1. Разделения ответственности: Отдельные модели или сервисы обрабатывают запросы на чтение (не изменяют состояние) и команды на изменение состояния (транзакционные операции).
  2. Масштабирования: Оптимизация хранилищ и обработчиков отдельно для чтения (часто read-heavy) и записи (write-heavy). Например, разные базы данных с разными схемами.
  3. Оптимизации производительности: Запросы на чтение могут использовать простые SQL-запросы или NoSQL для быстрых ответов, в то время как команды требуют более сложных транзакций и логики.
  4. Использования Event Sourcing: Часто используется в связке с Event Sourcing, где команды генерируют события, которые затем используются для обновления read-модели.
  5. Повышения гибкости: Позволяет использовать различные технологии для чтения и записи данных.

Пример применения:

  • Command (Запись): Обработчик команды CreateOrderCommand принимает данные, выполняет валидацию, обновляет состояние домена (например, создает заказ и резервирует товары), и генерирует доменные события (OrderCreated).
  • Query (Чтение): Сервис OrderQueryService использует оптимизированное для чтения хранилище (например, денормализованное представление данных) для быстрого получения списка заказов или деталей конкретного заказа.

Структурные элементы:

  • Commands: Объекты, представляющие намерения пользователя или системы изменить состояние. Например, CreateProductCommand, PlaceOrderCommand.
  • Command Handlers: Принимают команды и выполняют бизнес-логику, изменяя состояние системы.
  • Queries: Объекты, представляющие запросы на получение данных. Например, GetProductQuery, GetCustomerOrdersQuery.
  • Query Handlers: Выполняют запросы на чтение, возвращая данные без изменения состояния.
  • Read Model: Оптимизированное для чтения представление данных, часто денормализованное или использующее другую СУБД.
  • Write Model: Модель, используемая для обработки команд и изменения состояния (часто доменная модель).
<?php

// Пример команды
final class CreateProductCommand
{
    public function __construct(
        public string $name,
        public float $price
    ) {}
}

// Пример обработчика команды
final class CreateProductCommandHandler
{
    public function __construct(
        private ProductRepository $productRepository // Репозиторий для записи
    ) {}

    public function __invoke(CreateProductCommand $command): void
    {
        // Бизнес-логика, валидация и создание продукта
        $product = new Product($command->name, $command->price);
        $this->productRepository->save($product);
        // Возможно, генерация события ProductCreated
    }
}

// Пример запроса
final class GetProductQuery
{
    public function __construct(
        public string $productId
    ) {}
}

// Пример обработчика запроса
final class GetProductQueryHandler
{
    public function __construct(
        private ProductReadRepository $productReadRepository // Репозиторий для чтения
    ) {}

    public function __invoke(GetProductQuery $query): ?ReadProductDto // DTO для чтения
    {
        // Запрос к оптимизированному для чтения хранилищу
        return $this->productReadRepository->findById($query->productId);
    }
}

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