Совершенный код: избавляйтесь от строк

Веб-программирование насквозь состоит из манипулирования строковыми данными. Данные в базе, данные в JSON (который тоже строка), данные в коде (SQL-запросы, списки). Часть этих строк на код не влияет, это просто данные, которые гоняются из базы пользователю и обратно. Другие данные задействованы в логике приложения и серьезно влияют на устойчивость к ошибкам и скорость их обнаружения.
Подписывайтесь на канал Кирилла Мокевнина в Telegram — чтобы узнать больше о программировании и профессиональном пути разработчика
Ниже я расскажу, как правильно организовать логику, завязанную на строки, и повысить качество кода. Начнем с типичного примера. Представьте, что где-то в коде приложения есть такая проверка:
Подобных проверок очень много в любом веб-проекте. Мы постоянно анализируем статусы, роли, доступные возможности, соответствия значениям из каких-нибудь списков и так далее. Большинство этих данных представлено в виде строк, поэтому и проверки выглядят как сравнение со строками.
Сам по себе подобный код неизбежен, любая бизнес-логика должна быть реализована. В этом, по большому счету, и состоит основная задача кодирования. Однако способ написания подобных условий важен. Сравнение со строкой – худший из возможных подходов. Почему?
Автоматизированные инструменты не гарантируют корректность такого сравнения и не помогают, если оно построено неверно. Представьте себе две ситуации:
- программист мог допустить ошибку в слове 'delivering';
- программа изменилась, и статуса 'delivering' больше нет.
Что произойдет с проверкой в любой из этих ситуаций? Правильный ответ: ничего. Мы не узнаем об ошибочной проверке, пока не увидим ее косвенное влияние на поведение программы. Например, пока что-то не вывелось или не посчиталось неверно. Иногда это может произойти быстро, а иногда приходится ждать долго. В такой ситуации вы можете узнать об ошибке от пользователей, которые столкнулись с проблемами. Частично эту проблему могут решить тесты, но они помогают далеко не всегда. Если от этого условия зависит вывод блока на экране, то тесты почти наверняка его не обнаружат. Кроме того, такой код порождает дублирование. При любых изменениях придется искать все места и править их.
Продолжайте учиться
На Хекслете есть блок «Треки», где собраны курсы как для опытных программистов, так и для начинающих, которые хотят углубить свои знания про разработку.
Посмотрим на другой пример. В веб-приложениях часто нужно строить ссылки:
Возникает ровно такая же ситуация. Адрес строится как строка. Что, если он поменяется? Программист снова не узнает о проблеме в момент ее появления. Более того, на практике подобные ошибки могут не проявлять себя месяцами, пока какой-то пользователь не пожалуется, что получает 404.
И последний пример:
И если ошибок в SQL база данных не прощает, то перепутать значение легко, и никто в такой ситуации не поругается. Даже если значение правильное, нет никакой гарантии, что оно не изменится в будущем. А значит, код, который работает сегодня, завтра может работать неверно. И снова непонятно, в какой момент проблема станет известной.
Содержание
Замена строк
Описанные подходы немного разнятся для статических и динамических языков.
Основной способ решения данной проблемы – замена строк на вызовы функций. Их можно писать самим, а можно пользоваться готовыми инструментами. И это лучший вариант. Например, в хороших фреймворках есть механизм, позволяющий строить ссылки на базе существующего роутинга. При таком подходе любые несоответствия начнут порождать исключения. Кроме того, подобный механизм позволяет менять готовую ссылку без необходимости переписывать весь код везде, где она используется.
Даже если приходится работать с адресами вне роутинга (например, если пользователь вводит адрес сам), всегда можно выкрутиться. Обработку таких адресов лучше выполнять через специальные функции, которые сами проверяют их корректность. Во многих языках подобная функциональность доступна прямо в стандартной библиотеке:
То же самое касается работы с путями в файловой системе. Вместо ручной сборки есть готовые функции, которые могут защитить от опечаток:
В случае проверок на соответствие поможет создание перечисления (enum). В одних языках это встроенный механизм, в других библиотека, а иногда и просто самописный код. Идея этого подхода — замена строк на обращение к значениям из специального описания, где есть все возможные значения. Это описание должно использоваться всеми частями программы, которые на него завязаны. В таком случае изменение этой структуры приведет к ошибкам там, где есть неверные обращения с точки зрения нового кода. Ошибка будет выглядеть примерно так: «Такого значения не существует».
В самых простых случаях достаточно создать функции или методы, выполняющие нужные проверки:
То же самое касается и всех остальных атрибутов. А вот со статусами ситуация отличается. Статусы всегда описывают какие-то процессы. И правильная работа с ними подразумевает использование конечных автоматов. Библиотеки, которые их реализуют, в том числе обеспечивают нужные нам гарантии. Эта тема выходит за рамки статьи, начать знакомство с ней можно отсюда.
Дополнительные материалы:
Kirill Mokevnin
6 лет назад