Очистите свой JavaScript: Избавьтесь от регулярных выражений

Источник: «Clean Your JavaScript: Get Rid of the Regular Expressions — Part 2»
В этой статье я рассмотрю регулярные выражения, также известные как Regex, и попытаюсь убедить вас в том, что их наличие в вашей кодовой базе — плохая идея. Для краткости я не буду пытаться объяснить внутреннюю работу и применение Regex, но постараюсь убедить вас в необходимости их рефакторинга из вашей кодовой базы.

Что такое регулярные выражения

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

Как вы можете заметить, это может быть полезно, особенно при создании валидаций полей форм. Это одна из наиболее чувствительных к безопасности операций в Интернете, и в большинстве случаев мы проверяем вводимые данные, потому что хотим ограничить доступ или решить какую-то другую связанную с этим проблему. Мы увидим, как регулярные выражения используются для проверки кредитных карт, электронной почты, паролей, фильтров поиска и т.д.

В чем проблема с регулярными выражениями

Возможно, в этот момент вы спросите себя: А в чем тогда проблема с их использованием, они же вроде бы полезные. И вы будете не так уж далеки от истины. Регулярные выражения часто не имеют смысла, поскольку из-за сложности синтаксиса регулярных выражений очень трудно с первого взгляда понять, что именно достигается с помощью того или иного шаблона.

Я профессионально пишу код уже около 8 лет, и никогда не работал с инженером, который мог бы с первого взгляда пересказать, чего пытается добиться Regex. Это делает ревью кода крайне болезненными, поскольку мне нужно проверить, полностью ли и правильно ли шаблон Regex проверяет все требования. Это делает код очень хрупким и подверженным опечаткам, которые могут привести к катастрофическим потерям в бизнесе.

Плохо написанные регулярные выражения в некоторых случаях могут быть уязвимы в плане обеспечения безопасности. Например, некоторые шаблоны могут быть подвержены атакам ReDoS (Regular Expression Denial of Service), когда злоумышленник предоставляет специально подготовленные входные данные, заставляющие систему потреблять чрезмерное количество ресурсов процессора или памяти.

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

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

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

Например, по этой ссылке можно найти полноценный Regex в соответствии с RFC 822 для проверки электронной почты. Затем вы заметите, что быстро потеряете интерес к попыткам понять, как это работает. Либо будете искать другое решение или просто поверите, что оно работает, и скопируете его в свою кодовую базу, что приведёт к огромному количеству проблем, если вдруг кто-то изменит какой-либо символ в шаблоне.

Вообще говоря, реализация Regex также зависит от языка программирования и, как известно, очень медленна с ростом сложности и не может решать такие сложные задачи, как разбор вложенных структур, например XML, и обработка HTML текста.

В одном интересном исследовании говорится следующее:

10% исследованных ими веб-сервисов на базе Node.js уязвимы к ReDoS. При таком и без того жёстком сценарии авторы обнаружили, что только 38% опрошенных ими разработчиков знают о существовании ReDoS-атак.

Чем заменить регулярные выражения

На самом деле, ответ на этот вопрос достаточно прост и очевиден. Это одна из тех вещей, которым каждый программист обучается на ранних стадиях, ещё до того, как узнает о существовании Regex, строковых методов. В зависимости от того, чего вы хотите добиться, вы можете использовать комбинацию этих методов с методами Array.

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

Даже в тех случаях, когда вам кажется, что решение с использованием Regex является быстрым "однострочником", избегайте его использования любой ценой. Особенно для начинающих разработчиков соблазнительно броситься на быстрое решение или считать менее элегантный код элегантным, но на самом деле это далеко не так. Элегантный код — это хорошо написанный, поддерживаемый и масштабируемый код.

Заключение

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

Поэтому, когда вы в следующий раз обратитесь к Regex, подумайте, не могут ли более простые методы достичь того же результата с большей ясностью. Такой подход не только сделает ваш код более доступным для пользователей, но и защитит его от мелких ошибок и проблем с производительностью, что в конечном итоге приведёт к созданию более надёжной и устойчивой кодовой базы.

Остальные статьи серии "Очистите свой JavaScript"

Дополнительные материалы

Предыдущая Статья

Очистите свой JavaScript: Трансформация условных операторов

Следующая Статья

Новое в Symfony 6.4: Улучшения DX (часть 1)