Композиция валидаторов

Композиция валидаторов представляет собой способ построения сложной логики проверки данных из набора небольших, изолированных и переиспользуемых функций. Вместо создания монолитных проверок используется принцип функциональной сборки, при котором простые предикаты объединяются в более выразительные и управляемые конструкции.

В основе подхода лежит идея, что каждый валидатор выполняет одну конкретную задачу: проверяет тип, диапазон, формат или соответствие правилам. Композиция позволяет объединять такие проверки в цепочки, деревья и альтернативные ветвления без дублирования кода.

Функциональная основа композиции

Валидатор обычно представляет собой функцию, принимающую значение и возвращающую результат проверки:

  • true/false
  • объект ошибки
  • или структурированный результат валидации

Композиция строится вокруг преобразования набора таких функций в новые функции с более сложной логикой. Важное свойство — отсутствие побочных эффектов и детерминированность.

Функциональный подход позволяет рассматривать валидаторы как строительные блоки, которые можно:

  • комбинировать
  • вкладывать друг в друга
  • переиспользовать в разных схемах проверки

Логическая композиция AND

Самая базовая форма композиции — логическое «И». Несколько валидаторов применяются последовательно, и результат считается успешным только если все проверки прошли.

Типовая структура:

  • входное значение проходит первую проверку
  • затем вторую
  • затем третью
  • при первом сбое цепочка может прерываться или собирать все ошибки

Такой подход используется для строгих правил, где все условия обязательны: длина строки, формат, допустимые символы, диапазон чисел.

Пример логики:

  • проверка на пустоту
  • проверка минимальной длины
  • проверка регулярным выражением

Композиция AND часто реализуется через функцию-обёртку, принимающую массив валидаторов и возвращающую новый валидатор.

Логическая композиция OR

Композиция «ИЛИ» используется для альтернативных правил. Значение считается валидным, если хотя бы один валидатор из набора проходит проверку.

Особенности:

  • используется для гибких форматов данных
  • позволяет поддерживать несколько допустимых стандартов
  • снижает жесткость схемы

Типичный пример — поле может быть либо email, либо телефонным номером. В этом случае валидаторы проверяются по очереди, и успех любого из них завершает цепочку.

Последовательная композиция (pipeline)

Пайплайн представляет собой линейную трансформацию и проверку значения. Каждый валидатор получает результат предыдущего.

В отличие от чистой проверки, pipeline может:

  • преобразовывать данные (trim, normalize)
  • валидировать промежуточный результат
  • передавать изменённое значение дальше

Такая композиция полезна при обработке пользовательского ввода, где важно не только проверить, но и нормализовать данные перед проверкой.

Комбинирование предикатов

Предикатная композиция основана на объединении простых логических функций:

  • isString
  • isNumber
  • isEmail
  • isInRange

Из них строятся более сложные конструкции:

  • «строка и email»
  • «число в диапазоне и целое»
  • «строка, соответствующая шаблону и не пустая»

Комбинирование может быть реализовано через:

  • логические операторы
  • функции высшего порядка
  • фабрики валидаторов

Ключевая идея — разделение ответственности между мелкими проверками.

Фабрики валидаторов

Фабрика валидаторов — это функция, возвращающая новый валидатор на основе параметров.

Примеры параметров:

  • минимальная длина
  • максимальное значение
  • регулярное выражение
  • список допустимых значений

Фабрики позволяют создавать параметризованные проверки без дублирования логики.

Преимущества:

  • единая реализация логики
  • гибкость настройки
  • удобство композиции

Фабрики часто являются основой для построения DSL-подобных схем валидации.

Кастомные валидаторы и расширяемость

Расширяемость достигается за счёт возможности внедрения пользовательских функций в композицию.

Кастомный валидатор:

  • принимает значение
  • применяет бизнес-логику
  • возвращает результат проверки

Он может быть встроен в любую композиционную структуру:

  • цепочку AND
  • альтернативу OR
  • pipeline обработки

Это позволяет интегрировать доменные правила без изменения базовой системы валидации.

Асинхронная композиция

Некоторые проверки требуют асинхронных операций:

  • запрос к серверу
  • проверка уникальности в базе
  • внешние API

Асинхронная композиция усложняет структуру, так как:

  • результат возвращается через Promise
  • порядок выполнения может быть важен
  • необходимо управление параллельностью

Подходы к композиции:

  • последовательное ожидание (await chain)
  • параллельная проверка с Promise.all
  • ранний выход при ошибке

Асинхронные валидаторы особенно важны в формах регистрации и сложных бизнес-логиках.

Агрегация ошибок

При композиции нескольких валидаторов возникает задача объединения ошибок в единый результат.

Варианты агрегации:

  • первое найденное нарушение
  • список всех ошибок
  • группировка по полям
  • структурированные деревья ошибок

Агрегация важна для UX, так как позволяет отображать пользователю полную картину проблем, а не только первую ошибку.

При композиции AND часто используется стратегия накопления ошибок, тогда как OR может возвращать ошибки всех альтернатив.

Переиспользование и модульность

Композиция валидаторов напрямую связана с модульностью кода. Каждый валидатор становится независимым модулем, который можно:

  • импортировать
  • комбинировать
  • тестировать отдельно
  • переиспользовать в разных схемах

Это снижает связность системы и упрощает сопровождение.

Типичная архитектура:

  • базовые валидаторы (primitive)
  • составные валидаторы (composed)
  • доменные валидаторы (business logic)

Обёртки и декораторы валидаторов

Декораторы позволяют расширять поведение валидаторов без изменения их внутренней логики.

Примеры обёрток:

  • логирование результата
  • кэширование результата проверки
  • таймаут выполнения
  • преобразование входных данных

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

Условная композиция

Условная композиция позволяет изменять набор валидаторов в зависимости от контекста.

Примеры условий:

  • значение другого поля
  • роль пользователя
  • режим формы (создание/редактирование)
  • флаг конфигурации

В этом случае композиция становится динамической:

  • набор валидаторов формируется во время выполнения
  • структура проверки адаптируется под ситуацию

Это особенно важно в сложных формах и конфигурационных системах.

Практические паттерны композиции

В реальных приложениях композиция валидаторов принимает устойчивые формы:

1. Слои проверок

  • синтаксическая проверка
  • семантическая проверка
  • бизнес-правила

Каждый слой строится из композиции валидаторов.

2. Группировка по полям

  • валидаторы для отдельных полей
  • композиция на уровне формы
  • агрегатор ошибок

3. Переиспользуемые блоки

  • email-валидатор как композиция базовых проверок
  • пароль как набор правил сложности
  • дата как комбинация формата и диапазона

4. Комбинация синхронных и асинхронных проверок

  • быстрые локальные проверки выполняются первыми
  • дорогие асинхронные — только при успехе базовых

Такой подход оптимизирует производительность и снижает нагрузку на внешние системы.