Увійти Реєстрація
Блог Серії
Кар'єра
Вакансії Компанії
Навчання
Документація Співбесіди Тестування Відео
Екосистема
Пакети Ресурси Проєкти Інструменти Події
Інше
Про нас Реклама

Що таке CQRS і коли розділення команд і запитів виправдане?

CQRS (Command Query Responsibility Segregation) - розділення моделі на дві: одна для змін (команди), інша для читання (запити).

Чому одна модель часто незручна для обох задач:

  • запис потребує агрегатів з поведінкою й інваріантами, нормалізованих даних, транзакцій;
  • читання потребує денормалізованих, плоских даних під конкретний екран: «список замовлень з ім'ям клієнта, кількістю позицій, статусом доставки й останнім коментарем».

Одна модель на обидві задачі або обростає зв'язками й N+1 для читання, або втрачає виразність для запису.

Рівні CQRS - від легкого до радикального:

1. Розділення в коді - найпоширеніше й найкорисніше:

// команди: змінюють стан через агрегати
final class PlaceOrder { public function handle(PlaceOrderData $data): OrderId { /* ... */ } }

// запити: окремі класи, що читають напряму, без моделей домену
final class OrderListQuery
{
    public function get(int $customerId): Collection
    {
        return DB::table('orders')
            ->join('customers', ...)
            ->select(['orders.id', 'customers.name', 'orders.status', ...])
            ->where('orders.customer_id', $customerId)
            ->get();
    }
}

Читання не обмежене формою агрегатів - оптимізований SQL під екран.

2. Окремі моделі читання (read models) - денормалізовані таблиці чи проєкції, що оновлюються подіями: таблиця order_summaries з усім потрібним для списку.

3. Окремі сховища - запис у реляційну базу, читання з Elasticsearch/Meilisearch чи окремої репліки.

Коли CQRS виправданий:

  • складний домен з багатою логікою запису й різноманітними поданнями для читання;
  • велика різниця навантажень: читань у сотні разів більше, і їх треба масштабувати окремо;
  • різні вимоги до даних: пошук, звіти, аналітика;
  • разом з event sourcing - там CQRS практично обов'язковий (стан будується з подій).

Коли шкодить: у простих CRUD-застосунках - подвоєння коду без вигоди. Фаулер прямо попереджає: для більшості систем CQRS додає ризику й складності.

Ціна окремих моделей читання:

  • кінцева узгодженість: користувач зберіг зміну, а список ще показує старе. Інтерфейс має це враховувати;
  • синхронізація: проєкції, що не оновилися через помилку, треба вміти перебудувати;
  • більше рухомих частин.

Практична порада: почати з рівня 1 (окремі класи-запити) - він дає більшість користі майже без ціни.

Докладніше в документації: Martin Fowler: CQRS

Перевір себе

20 випадкових питань за спробу, після завершення - розбір кожної помилки

Схожі питання