Написать пост

Стоит ли писать «красивый» код — отвечают эксперты

Аватар Никита Прияцелюк

У подхода к оформлению кода согласно разным Style Guide есть сторонники и противники. Спрашиваем у экспертов, стоит ли вообще думать о виде вашего кода.

Стоит ли тратить время на «красивое» оформление кода согласно разным Style Guide, если того не требует заказчик? Или же это всё дурные мысли, появляющиеся от безделья, и главное, чтобы код работал? Узнаем у экспертов.

Корректное именование переменных и Code Style — это не прихоть. Это то, из чего складывается такая полезная вещь, как семантика кода, она же в переводе с высшего эльфийского — читаемость и понятность. В своём проекте можно творить любую дичь, хоть запутывание кода на уровне написания — но любой коммерческий проект подразумевает поддержку. А значит, упорядоченный, читаемый код — «не роскошь, а средство передвижения». Просто спросите себя — а я сам эту «мудрость предков» пойму через месяц? Или буду обкладывать матом человека, который это написал?

Мой любимый пример — это работа с сервисом очередей на одном проекте. Код был написан на основе внутренней магии сервиса и содержал четыре переменные — a, b, c и d. Чтобы выяснить, что это за переменные и какая именно магия используется внутри, ушло десять часов. Вместо десяти минут. Как сказал человек, которому пришлось это разбирать… Хотя нет, я не могу этого рассказать — это непедагогично.

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

  • Банальное именование переменных. Например, абстрактные data, result и value — там же данные, результат и значение, что может быть непонятного? Только в проекте этих данных, результатов и значений — как у дурака фантиков. К тому же, каждый раз придётся вспоминать, что там лежит, если не оставить себе на будущее комментарии. Перед каждой строкой, где эти переменные используются.
  • «Вроде-как-синонимы». Индекс элемента массива, обозначенный как order1, даже выглядит логично — элементы идут по порядку, начиная с первого. Только «порядок сортировки» и «порядковый номер элемента» это даже не синонимы, хотя в голове автора это, видимо, так. Здесь можно было бы вспомнить про «Ложных друзей переводчика», если бы мы говорили о трудностях перевода.
  • «Я художник — я так вижу». Вот функция с названием getListCount, которая возвращает true, false или null. Что хотел сказать этим автор? — что длина списка строго больше единицы. А что значит null? — что не придумали другого обозначения для пустого списка. Но читая название функции, я хочу сразу понимать, что она делает, а не гадать, почему на вопрос «Ты будешь чай или кофе?» мне отвечают «В четверг».
  • Разное название для одних и тех же терминов. direct, isDirect, oneWay и emptyTransfers — нормальные названия для прямых рейсов в рамках ста строк кода (если не смог договориться с голосами в голове).

Смотря на все эти примеры, основную мысль можно выразить так: правильное именование сущностей позволяет поддерживать код без головной боли, пустой траты времени и битвы экстрасенсов. Это даёт ожидаемое поведение чего бы то ни было.

Так что не стоит пренебрегать корректным именованием переменных и форматированием кода — последнее в профессиональных редакторах вообще делается парой клавиш. И себе нервы сэкономите, и человеку, который за вами это будет доделывать. И помните: статья «Как писать неподдерживаемый код» — это вредные советы, а не руководство к действию.

Таким вопросом программисты задаются достаточно часто, и главный аргумент противников «красивого» кода — «время будет потрачено впустую». И если разговор зашёл про время, давайте посмотрим на проблему с другой стороны. Допустим, кому-то придётся модифицировать код, написанный другим программистом (возможно, это будет даже его собственный код, но с момента его написания прошло значительное время, и всё порядком подзабылось). Как быстро удастся с ним разобраться, когда в нём нет комментариев, на каждой строчке расположено по несколько действий, а все переменные именуются «А», «ВВ», «ССС»?  Сразу отвечу: иногда бывает проще написать новый код, чем распутывать это «спагетти».

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

Ответ на поставленный запрос напрямую зависит от того, как и с кем работает программист.

Если перед программистом стоит задача написать приложение или библиотеку для себя, или если в будущем не планируется привлечения других людей для работы над проектом, то можно действительно «творить» со своим кодом всё, что душа пожелает. Золотое правило для программистов-одиночек звучит следующим образом: «Пока я понимаю свой код, ничего дополнительного мне делать не нужно».

Если программист работает в команде (или в ближайшее время такая работа планируется), то возникает необходимость в документировании и тестировании исходного кода, а также в корректном именовании переменных, соблюдении стилевого гида. Это необходимо для того, чтобы прямо через исходный код сообщать о своих намерениях коллегам. В противном случае, над проектом всегда будет висеть угроза большого количества ошибок, возникших в результате влияния одних кусков кода на другие — регрессий. Командная работа также подразумевает использование нетривиальных техник программирования — design patterns. С их помощью код разбивается на необходимые структурные элементы, которые документируются и тестируется независимо друг от друга. Если все программисты, работающие над одним проектом, говорят на одном «языке» архитектуры приложения, то каждый сможет написать такие независимые модули, а вероятность их «поломки» будет стремиться к нулю. Design patterns, unit tests, документирование кода — это своеобразное письменное соглашение программистов о том, как ведётся работа над конкретным проектом. Она помогает коллегам лучше помогать друг друга через код.

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

Писать «красивый» код стоит. Почему?

Открывая меню любого ресторана/бара/кафе, что вы делаете в первую очередь? Видите картинки. Для себя определяете: нравится ли блюдо, понятен ли его состав, большая ли порция, будет ли её достаточно. Согласитесь: если вам принесут некую непонятную субстанцию, пусть даже и гипотетически вкусную, первая реакция — недоверие.

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

В длинном и неаккуратном коде вы можете возиться очень долго — потеряете время, нервы, силы, и нет гарантии, что всё получится.

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

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

«Красивый», но неработающий код бесполезен, а работающий код без красоты нечитаем и сложен. Сделать его и работающим, и «красивым» помогает целый ряд ПО. Мы, например, используем:

  • Smoke test на Vanessa-add (разработанная на основе Vanessa-behavior) — для проверки работоспособности;
  • SonarQube — для анализа качества и «красоты» кода.

Вот некоторые моменты, на которые мы обращаем внимание при написании кода в своих разработках:

  • когнитивная сложность функции/процедуры: помогает ограничить количество условий и циклов в одной функции/процедуре. Такое ограничение нужно для повышения сопровождаемой функции/процедуры. Многие разработчики этим общим стандартом пренебрегают, а в дальнейшем сталкиваются с достаточно типовыми проблемами — например, в тестировании или в доработке таких функций/процедур;
  • «магические» числа/даты — сущность, появляющаяся в коде из ниоткуда и используемая напрямую в выражениях; за ней надо следить, потому что это тоже достаточно частый грешок программистов, после чего сам же программист сталкивается с непониманием того, что он сделал;
  • именование виртуальных таблиц в запросах. Ещё одна очень часто встречающаяся проблема, когда программист строит многоуровневый запрос с большим количеством виртуальных таблиц или вложенных запросов и именует их по типу VT1, VT2, VT3 и т. д. В дальнейшем такой подход усложняет процесс сопровождения и читаемости запроса.

Это, разумеется, далеко не все важные моменты. Но всё, что ещё можно было бы здесь перечислить, так или иначе влияет на сопровождаемость, читаемость и тестирование кода. Отсюда можно сделать вывод: «красивый» и работающий код, написанный по общепризнанным стандартам, упрощает и сокращает затраты на его сопровождение.

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

А дальше этот код будут читать. Много, долго и совершенно непричастные люди. Гораздо дольше, чем планирует автор, и люди, максимально далёкие от заложенных в коде идей. Или даже сам автор, но в ситуации, которая исключает плавное и вдумчивое погружение во вчерашние озарения. Поэтому то, что называется «красивостью», является обычным инструментом, который призван удешевить главный параметр кода — его сопровождаемость.

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

Заказчик в крайне редких случаях предъявляет какие-то требования к коду. Разве что его основной бизнес — программирование. Покупают у программистов фичи, а не код, инструменты и их работающую функциональность. А ещё дешёвое внесение модификаций в уже работающую систему или расширение функциональности, не требующее экспоненциально растущих затрат.

Можно ли сэкономить на красоте? Можно, конечно. Если код планируется «write-only» — запустить один раз и забыть.

Я не вижу дихотомии. Код должен работать и быть красивым, то есть простым (не примитивным!), читаемым, понятным, легко модифицируемым и расширяемым.

Корректное оформление кода позволяет сохранять код понятным и поддерживаемым. На крупных проектах, над которыми работают несколько команд программистов, особенно важно правильно понимать то, что сделано другими. Во frontend разработке, в частности, принято комментирование кода согласно JsDoc и корректное именование переменных. Для оформления отступов и форматирования можно применять Prettier, настраивать pre-commit и pre-push hooks для Git, а в качестве дополнительного средства для улучшения качества кода использовать статические анализаторы.

Code Style важен для проекта, особенно если над ним работает не один человек, а целая команда. Для того, чтобы с кодом в дальнейшем можно было работать и поддерживать его, дополняя и внося изменения, обязательно должна быть логика именования переменных, описания функций и т. п. Вопросы стилизации кода, коррекции его отступов, расстановку запятых можно автоматизировать и не тратить на них времени, если в проекте уже есть настройки для плагинов, форматирующих код в IDE или для самой IDE, если язык это позволяет делать. На эту часть работы тратится от силы час в начале работы над проектом и дальше автоматика всё делает за разработчика, хотя с какого-то момента уже и сам начинаешь писать код в соответствии со стилем (потому что это очень удобно, когда сразу всё в одном стиле).

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

Моё мнение, что проекты, в которых есть Style Guide и следование стандартам написания кода и именования переменных, на голову жизнеспособнее в долгосрочной перспективе по сравнению с проектами, где Style Guide отсутствует.

Итак, нужно ли писать «красивый» код?

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

Если же вы работаете над каким-то проектом с командой, то тут, безусловно, нужно придерживаться определённых правил. И дело не в том, что у компаний слишком много денег, что они готовы тратить драгоценное время программистов на написание кода в каком-то определённом стиле. Проекты, как правило, предполагают поддержку. А код, написанный абы как, поддерживать дорого, потому что даже его создатель через месяц может не вспомнить, почему он использовал этот шаблон проектирования или что это за переменная data.

Итого: пишете что-то для себя — чистый код может подождать, работаете в команде — следуйте принятым правилам оформления кода и пишите с перспективой на будущее.

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

Следите за новыми постами
Следите за новыми постами по любимым темам
8К открытий8К показов