Как контролировать количество параметров функции при добавлении новых, чтобы не усложнять интерфейс?
Что проверяют
Понимаете ли вы, что длинный список параметров это симптом, а не проблема синтаксиса. Интервьюер ждёт, что вы отличите приёмы, которые прячут сложность, от тех, что её убирают. Следом часто спрашивают, как то же самое выглядит для пропсов React-компонента.
Как отвечать
Сначала правило: главное и обязательное остаётся позиционным, всё необязательное уходит в объект опций. Дальше приёмы:
- объект опций с деструктуризацией:
function fetchUsers(query, { limit = 20, signal } = {}). Новый параметр добавляется без поломки вызовов, порядок аргументов перестаёт иметь значение, а= {}защищает от вызова без второго аргумента; - тип для опций: в TypeScript выносите
interface FetchOptionsи помечайте необязательное через?. Тип документирует интерфейс и ловит опечатки в именах ключей; - отказ от булевых флагов:
render(item, true, false)нечитаем. Два режима работы обычно означают две функции или один параметр-перечисление вродеmode: 'compact' | 'full'; - разделение ответственности: если функции нужны семь параметров, она часто делает три дела. Разбейте её или вынесите подготовку данных наружу;
- частичное применение: фабрика
createClient(config)запоминает редко меняющиеся настройки, и возвращённые функции принимают только своё; - для компонентов: вместо двадцати пропсов композиция через
children, составные компоненты (Tabs.List,Tabs.Panel) или контекст для сквозных данных.
Для контроля в команде есть правило ESLint max-params, по умолчанию оно ругается на четвёртый параметр. Rest-параметры ...args уместны только для однородных значений, как в sum(...numbers).
Где спотыкаются
Заворачивают в объект всё подряд, включая единственный обязательный аргумент. Вызов становится многословным, а при слишком мягком типе TypeScript уже не подскажет, что главное забыли передать.
Предлагают Builder как основной ответ. В JavaScript объект опций решает ту же задачу без класса, а Builder оправдан, когда объект собирают поэтапно с проверкой на каждом шаге.
Мутируют переданный объект опций внутри функции. Вызывающий код получает побочный эффект, особенно заметный, когда один объект настроек переиспользуют.