Найти тему
Tominoff

Читаемость кода, пара трюков для начинающих

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

1. Названия

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

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

Лично для себя я выработал несколько простых правил нейминга, которых придерживаюсь в своих проектах (разумеется, если у проекта есть готовый styleguide, то конечно лучше следовать ему)

  • Только английские слова - никаких транскрипций и уж тем более сочетаний из английского и транскрипции
zaprositPlatezh - requestPayment
initializeNewZakaz - initializeNewOrder
  • Общие/глобальные константы должны быть максимально ёмкими и отражающими свою суть
CARD - PAYMENT_TYPE_CARD - становится понятен контекст
DAY_PERIOD - DAY_IN_SECONDS - сразу понятно в каком измерении
  • Использование префиксов для разных типов функций
Часто использую подобные обозначения:

is* - проверка, всегда возвращает boolean (isPrepayable, isReady, isValid)
make* - порождение чего-либо (makeProductElasticIndexName, makeUploadHandler)
get* - получение чего-либо (getFullname, getPhone)
to* - трансформация объекта во что-то другое (toString, toJSON)

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

2. Избегаем магии и шифрования

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

Пожалуй, самый распространённый способ что-то где-то сократить – использовать тернарные условия.

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

Бывает, случается соблазн написать что-то эдакое вычурное, использовать некую "магию" языка программирования чтобы всех удивить.

Ну да, эта функция каррирования работает.. но вот быстро ли вы разберётесь в этом коде?
Ну да, эта функция каррирования работает.. но вот быстро ли вы разберётесь в этом коде?

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

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

Чем код проще — тем лучше.

Пример monkey patch для библиотеки yandex-checkout
Пример monkey patch для библиотеки yandex-checkout

3. Меньше ветвлений

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

Для примера, посмотрим на простенькую функцию деления:

Типичный код с ветвлениями
Типичный код с ветвлениями

Да, пример очень простой, но даже тут заметно что код загромождён.

А вот как эту же функцию можно записать в более понятном виде:

Сначала проверяем пограничные случаи и делаем ранний возврат
Сначала проверяем пограничные случаи и делаем ранний возврат

Фишка в том, что мы избавляемся от вложенности операторов ветвления и избавляемся от else. Все пограничные инварианты мы обрабатываем в самом начале, а сама логика работы функции описана простой формулой.

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

4. Разделяй и властвуй

Классический совет - всегда максимально разбивайте большую задачу на множество маленьких.

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

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

Есть несколько преимуществ у такого подхода:

  1. Чистые функции крайне легко тестировать, поскольку их результат зависит только от входных параметров и вам не нужны нагромождения из mock-объектов и прочих имитаций
  2. Их легко переиспользовать в разных местах
  3. Их легко читать и понимать

5. Хардкод

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

Самый банальный пример где очень часто приходится видеть проблемы с этим - работа со временем:

Простой код для установки времени истечения действия токена ОФД
Простой код для установки времени истечения действия токена ОФД

В данном случае совершенно непонятно - какое же на самом деле время жизни этого самого токена?

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

Исправить это крайне легко, используя именованные константы и отдельный метод класса:

Таким образом можно легко переиспользовать этот код и в то же время он остаётся в контексте объекта
Таким образом можно легко переиспользовать этот код и в то же время он остаётся в контексте объекта