Код пишется один раз, а читается — десятки. Через полгода вы сами не вспомните, зачем написали тот хитрый однострочник. А если проект командный — нечитаемый код превращается в мину замедленного действия: баги множатся, онбординг новичков растягивается на месяцы, а рефакторинг становится рискованной операцией. Вот 10 принципов, которые делают код поддерживаемым.
1. Имена должны объяснять намерение
Хорошее имя переменной, функции или класса делает комментарий ненужным. Сравните:
| Плохо | Хорошо | Почему |
|---|---|---|
d |
elapsedDays |
Что такое d? Дата? Дистанция? Без контекста непонятно |
process() |
calculateMonthlyRevenue() |
«Обработать» — это всё что угодно. Конкретное имя описывает действие |
data |
userProfiles |
data — самое бессмысленное имя после temp |
flag |
isEmailVerified |
Булевы переменные начинаются с is/has/can/should |
Правило: если для понимания переменной нужно заглянуть в определение — имя плохое. Длинное имя лучше короткого, но непонятного.
2. Функции делают одно дело
Функция должна выполнять одну задачу и делать это хорошо. Признак нарушения — союз «и» в описании: «валидирует данные И сохраняет в базу И отправляет email». Это три функции, а не одна.
Оптимальный размер функции — 5–20 строк. Если функция не помещается на один экран — скорее всего, она делает слишком много. Выделите подзадачи в отдельные функции с понятными именами.
3. Избегайте магических чисел и строк
Число 86400 в коде — что это? Секунды в сутках, максимальный размер файла, ID пользователя? Замените на именованную константу SECONDS_IN_DAY = 86400. Это касается любых литералов, смысл которых неочевиден: статус-коды, лимиты, URL-адреса, конфигурационные значения.
4. Комментируйте «почему», а не «что»
Комментарий «увеличиваем счётчик на 1» к строке counter += 1 — бесполезен. Код уже говорит «что» происходит. Ценный комментарий объясняет «почему»: бизнес-правило, ограничение внешней системы, неочевидный выбор алгоритма.
Примеры хороших комментариев:
// Stripe API возвращает сумму в центах, конвертируем в доллары// Таймаут 30с — требование SLA от платёжного провайдера// Используем бинарный поиск вместо хеш-таблицы, потому что данные уже отсортированы
5. Ранний возврат вместо глубокой вложенности
Код с пятью уровнями вложенности if-else нечитаем. Используйте guard clauses — ранний возврат при невалидных условиях:
Вместо вложенных проверок «если пользователь существует, то если он активен, то если у него есть разрешение…» — инвертируйте условия: «если пользователь не существует — return ошибку, если неактивен — return ошибку, если нет разрешения — return ошибку». Основная логика остаётся на первом уровне вложенности.
6. DRY, но без фанатизма
Don’t Repeat Yourself — один из самых известных принципов, и один из самых переиспользованных. Дублирование — зло, когда два фрагмента кода меняются по одной и той же причине. Но если два похожих фрагмента обслуживают разные бизнес-домены — объединять их в одну абстракцию опасно.
Правило трёх: дублируйте спокойно, когда код встречается дважды. На третий раз — задумайтесь об абстракции. Преждевременная абстракция хуже дублирования.
7. Обрабатывайте ошибки явно
Пустые catch-блоки — техдолг, который рано или поздно выстрелит. Каждая потенциальная ошибка должна быть либо обработана (retry, fallback, сообщение пользователю), либо проброшена наверх с контекстом. Логируйте ошибку с достаточным контекстом для отладки: что произошло, с какими данными, в какой точке.
8. Пишите тесты как документацию
Хороший тест описывает поведение системы на человеческом языке. Используйте формат «given-when-then» в именах: test_expired_subscription_denies_access() сообщает больше, чем test_subscription_1().
Покрытие 100% — не цель. Покрывайте в первую очередь: бизнес-логику, граничные случаи, интеграции с внешними системами. Тесты на геттеры и сеттеры — пустая трата времени.
9. Структурируйте проект по фичам, а не по типам
Организация по типам файлов (/controllers, /models, /services) плохо масштабируется — при 50 файлах в каждой папке навигация превращается в кошмар. Организация по фичам (/users, /payments, /notifications) группирует связанный код вместе и упрощает работу с конкретной функциональностью.
10. Рефакторите постоянно и маленькими шагами
Большой рефакторинг — это риск. Маленький рефакторинг при каждом изменении — это гигиена. Правило бойскаута: оставляй код чище, чем нашёл. Переименовал неудачную переменную, выделил метод, убрал мёртвый код — и через месяц кодовая база станет заметно лучше.
Не нужно переписывать проект, чтобы код стал чистым. Достаточно принять эти принципы как ежедневную привычку — и качество будет расти инкрементально с каждым коммитом.