В 2019 году была написана потрясающая статья Parse, don’t validate. Я крайне рекомендую изучить её всем программистам (а также недавнее дополнение к ней Names are not type safety). Её основная идея заключается в том, что существует два способа проверки валидности входящих данных функции:
- Валидатор проверяет входящие данные на правильность и в случае их неправильности выдаёт ошибку. Он ничего не возвращает. Например, он может проверять, не пуст ли список.
- Парсер делает то же самое, что и валидатор, но возвращает более конкретное представление входящих данных, обеспечивающее соответствие требуемого свойства. Например, он проверяет, не пуст ли список, и возвращает тип NonEmptyList.
Главное утверждение, сделанное в этой статье — что парсеры предпочтительнее, чем валидаторы. Её основной посыл — нужно сделать недопустимые состояния непредставимыми (unrepresentable). В статье это реализовано с помощью использования системы типов. Я полностью согласен с такой философией, но хотел бы выделить и более подробно обсудить один из ироничных аспектов аргументации:
Инструмент контроля типов является хрестоматийным примером валидатора!
Ведь в конечном итоге инструмент контроля типов получает на входе уже подвергнутое парсингу представление программы и «бракует» его, если не удаётся выполнить контроль типов. Он не возвращает более конкретного представления программы. (Не стоит путать это с выводом типа, который возвращает больше информации, но только касательно типов).
Какой же может быть альтернатива инструменту контроля типов в виде парсера для языка программирования?
Читать полностью »