← Назад к вопросам
Зачем нужно разделять запросы и команды?
1.8 Middle🔥 121 комментариев
#Браузер и сетевые технологии
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI2 апр. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
CQRS — Command Query Responsibility Segregation
CQRS — это архитектурный паттерн, который разделяет операции на две группы: команды (Commands) и запросы (Queries). Это разделение критично для построения масштабируемых и поддерживаемых приложений.
Разница между командами и запросами
Команды — операции, которые изменяют состояние:
- Создание, обновление, удаление данных
- Побочные эффекты
- Возвращают минимум информации (успех/ошибку)
Запросы — операции, которые только читают данные:
- Получение информации
- Без побочных эффектов
- Возвращают данные
Почему разделять?
1. Оптимизация производительности
// Запросы можно кэшировать
const users = cache.get("users") || fetchUsers();
// Команды всегда свежие
await updateUser(userId, data); // Нет кэша
2. Разные требования к масштабированию
- Запросы: частые, много читателей → масштабируем читов
- Команды: редкие, сложная бизнес-логика → ACID, транзакции
3. Независимая оптимизация
// Запросы: денормализованная БД для скорости
const getUsers = () => db.query(`SELECT id, name FROM users_view`);
// Команды: нормализованная БД для консистентности
const updateUser = async (id, data) => {
await db.transaction(async (trx) => {
await trx("users").where({id}).update(data);
await trx("user_history").insert({user_id: id, ...});
});
};
4. Определённые побочные эффекты
- Запросы: без эффектов (идемпотентные)
- Команды: явные эффекты (логирование, кэш-инвалидация)
5. Разное обращение с ошибками
// Запрос — не критично если старые данные
const data = await getUsers().catch(() => cache.fallback);
// Команда — обязательно успеть или откатить
await updateUser(id, data); // Без fallback
Пример в контексте фронтенда
// API структура
// Запросы (GET)
GET /api/v1/users // Список пользователей
GET /api/v1/users/:id // Один пользователь
GET /api/v1/questions/search // Поиск вопросов
// Команды (POST/PUT/DELETE)
POST /api/v1/users // Создать пользователя
PUT /api/v1/users/:id // Обновить
DELETE /api/v1/users/:id // Удалить
// В клиентском коде
const [users, setUsers] = useState([]);
// Запрос — можно кэшировать
const fetchUsers = useCallback(async () => {
const cached = localStorage.getItem("users");
if (cached) return JSON.parse(cached);
const data = await fetch("/api/v1/users").then(r => r.json());
localStorage.setItem("users", JSON.stringify(data));
return data;
}, []);
// Команда — инвалидирует кэш
const createUser = useCallback(async (userData) => {
const response = await fetch("/api/v1/users", {
method: "POST",
body: JSON.stringify(userData)
});
// Очищаем кэш после команды
localStorage.removeItem("users");
setUsers([]);
return response.json();
}, []);
Практическое значение
Паттерн CQRS помогает предсказывать поведение, избежать багов с побочными эффектами и оптимизировать производительность. На собеседовании это показывает, что вы думаете о масштабируемости и архитектуре.