Как избежать булевых значений в сигнатуре функции JavaScript 👩💻
-
Почему булевы значения в сигнатуре функции — это плохо?
- Снижение читаемости
Когда вы видите вызов функции, например:
processOrder(order, true);
Сразу ли понятно, что делает этот
true
? Нет. Это может быть флаг для “экспресс-доставки”, “скидки” или ещё чего-то. Код становится менее понятным.-
Ограниченная масштабируемость
Если завтра нужно добавить третий режим, вам придётся заменять булево значение на что-то более сложное. Например,null
, дополнительные флаги или даже переписывать логику. -
Увеличение когнитивной нагрузки
При чтении кода разработчик должен помнить, что означает каждый булевый флаг. Это особенно сложно в больших проектах.
Альтернативные подходы
Вот несколько способов, как можно избежать булевых значений в сигнатуре функции:
- Использование объектов для конфигурации
Передавайте параметры в виде объекта, где каждое свойство имеет осмысленное название. Это делает код более читаемым и масштабируемым.
// Плохо function processOrder(order, isExpress) { if (isExpress) { console.log("Обработка экспресс-заказа"); } else { console.log("Обработка стандартного заказа"); } } processOrder(order, true); // Что значит true? // Хорошо function processOrder(order, options) { if (options.isExpress) { console.log("Обработка экспресс-заказа"); } else { console.log("Обработка стандартного заказа"); } } processOrder(order, { isExpress: true }); // Ясно, что это экспресс-заказ
- Использование перечислений (Enums)
Если у вас есть несколько фиксированных вариантов поведения, используйте перечисления. Это делает код более строгим и предсказуемым.
// Плохо function setVisibility(element, isVisible) { if (isVisible) { element.style.display = "block"; } else { element.style.display = "none"; } } setVisibility(myElement, false); // Что значит false? // Хорошо const Visibility = { VISIBLE: "visible", HIDDEN: "hidden", }; function setVisibility(element, visibility) { if (visibility === Visibility.VISIBLE) { element.style.display = "block"; } else if (visibility === Visibility.HIDDEN) { element.style.display = "none"; } } setVisibility(myElement, Visibility.HIDDEN); // Ясно, что скрываем элемент
- Разделение функций
Если поведение функции сильно зависит от флага, возможно, стоит разделить её на две отдельные функции.
// Плохо function calculatePrice(price, isDiscounted) { return isDiscounted ? price * 0.9 : price; } console.log(calculatePrice(100, true)); // Неочевидно // Хорошо function calculateFullPrice(price) { return price; } function calculateDiscountedPrice(price) { return price * 0.9; } console.log(calculateDiscountedPrice(100)); // Ясно, что считаем скидку
- Использование классов или замыканий
Для более сложных случаев можно использовать классы или замыкания, чтобы инкапсулировать поведение.
// Плохо function createLogger(isVerbose) { if (isVerbose) { console.log("Логирование включено"); } else { console.log("Логирование отключено"); } } createLogger(true); // Что значит true? // Хорошо class Logger { constructor(verbose) { this.verbose = verbose; } log(message) { if (this.verbose) { console.log(`[DEBUG] ${message}`); } else { console.log(message); } } } const verboseLogger = new Logger(true); verboseLogger.log("Это сообщение будет с префиксом"); // Ясно, что логгер включен
Вот таблица, которая наглядно демонстрирует преимущества и недостатки различных подходов для избежания булевых значений в сигнатуре функции:
Подход Преимущества Недостатки Булевы значения - Простота реализации
- Быстрое написание кода- Низкая читаемость
- Ограниченность в масштабировании
- Увеличение когнитивной нагрузкиОбъекты для конфигурации - Высокая читаемость
- Легко добавлять новые параметры
- Гибкость- Может быть избыточным для простых задач
- Требует дополнительного времени на написаниеПеречисления (Enums) - Строгость типов
- Предсказуемость
- Четкая документация поведения- Требует дополнительного кода
- Не всегда подходит для динамических случаевРазделение функций - Ясность намерений
- Простота использования
- Легко тестировать- Увеличивает количество функций
- Может привести к дублированию кодаКлассы/замыкания - Инкапсуляция логики
- Гибкость
- Возможность повторного использования- Может быть сложнее для новичков
- Увеличивает объем кодаИспользование булевых значений в сигнатуре функции — это быстрое решение, которое часто приводит к проблемам в будущем. Вместо этого лучше использовать более явные подходы, такие как объекты для конфигурации, перечисления или разделение функций. Это сделает ваш код чище, понятнее и проще в поддержке.
- Снижение читаемости