JavaScript Разделение команд и запросов

Command-query Separation принцип программирования. Команда связана с выполнением побочных эффектов, а чистые функции возможны только для запросов.

2 мин
Автор PINTA IT
JavaScript Разделение команд и запросов

JavaScript Разделение команд и запросов

Command-query Separation (CQS) - принцип программирования, изобретённый Бертраном Мейером, создателем языка Eiffel. Согласно этому принципу, каждая функция является либо командой, которая выполняет действие (action), либо запросом (query), который извлекает данные, но не тем и другим одновременно. Команда всегда связана с выполнением побочных эффектов, а чистые функции возможны только для запросов.

Команда JavaScript

// Возвращает true или false как результат своего выполнения
save(user);

Согласно принципу CQS, функция save является командой. Единственное, что она может - возвращать (опять же согласно принципу) успешность своего выполнения, то есть true или false (либо undefined, как в случае с console.log). Возврат этой функцией любых осмысленных данных, рассматривается как нарушение CQS. Однако, стоит сказать, что существуют ситуации, в которых невозможно соблюсти этот принцип. Например, открытие файла на запись возвращает файловый дескриптор - необходимый идентификатор, через который происходят манипуляции с файлом.

const file = fopen('/etc/hosts', 'r');

Отделение команд от запросов тесно связано с идеями, описанными в уроке про чистые функции. Команды по определению выполняют недетерминированный код с побочными эффектами. Недетерминированный, потому что повторный вызов команды приводит либо к ошибке, либо к повторному выполнению действия (хотя их и можно сделать детерминированными, но, как правило, такой код скрывает логические ошибки). Следовательно, выделение запроса (возврата данных) из команды в отдельную функцию, помогает разделить более чистый код от не чистого. Запросы, как мы увидим позже, можно выполнять множество раз не боясь чего-либо сломать.

Запрос JavaScript

// Возвращает true или false
isAdmin(user);

Функция isAdmin - предикат, типичный запрос (query) или, можно даже сказать, вопрос, который звучит так "Пользователь администратор?" Такая функция, с точки зрения CQS, не может изменять состояние системы: например, поменять дату проверки на администратора внутри пользователя или даже сделать пользователя администратором. Это противоречит не только CQS, но и здравому смыслу. В отличие от предыдущего примера, true и false в случае предикатов это не успешность выполнения функции, а ответ на заданный вопрос. CQS имеет альтернативную формулировку, которая отлично характеризует код выше: "Задавая вопрос, не изменяй ответ". К запросам относятся и любые вычисления.

// Функция Math.max() возвращает максимальное число из переданных
const maxNumber = Math.max(1, 30, 4); // 30

Этот код не создаёт никаких побочных эффектов и детерминирован. Его можно вызывать сколько угодно раз без риска получить ошибку или неверный результат.

Отсутствие изменения в запросах - очень важный принцип, который нужно соблюдать всегда. Даже на интуитивном уровне ни один человек не ожидает, что проверка isAdmin или вычисление максимального числа в массиве, может выполнить какое-то деструктивное действие. С другой стороны, на практике такой код иногда попадается, и теперь вы знаете, как правильно его исправить.

JavaScript 

Лучшие бесплатные онлайн курсы по JavaScript - Научись писать код на JavaScript и создавать потрясающие веб приложения. Большая коллекция курсов JavaScript.

УЧИТЬ БОЛЬШЕ

Похожие публикации