Скрытая цена грязного кода
Плохой код не объявляет о себе. Он проникает медленно — быстрый фикс здесь, обходное решение там, «отрефакторим позже», которого никогда не бывает. Потом однажды добавление простой функции занимает три недели, потому что никто не понимает систему.
Эти пять принципов — правила, которые наша команда соблюдает в каждом проекте.
1. Названия — это первая документация
Единственный самый высокоэффективный инструмент: правильно называть вещи.
Плохо: const d = users.filter(u => u.a && !u.b)
Хорошо: const activeUnverifiedUsers = users.filter(u => u.isActive && !u.isEmailVerified)
Правило: если нужен комментарий, чтобы объяснить что делает переменная или функция — название неправильное. Исправьте название.
2. Функции делают одно дело
Функция по имени handleUser, которая валидирует данные, обновляет БД, отправляет email и логирует событие — это не функция, это модуль.
У каждой функции должна быть одна задача. Одна причина существовать. Одна причина меняться.
Разбивайте большие функции на меньшие именованные шаги. Ваше будущее «я» скажет спасибо.
3. Удаляйте мёртвый код
Закомментированные блоки, неиспользуемые функции, необъявленные переменные — это мёртвый код. Он создаёт путаницу. Когда кто-то читает // Old approach - kept for reference, они не знают — это валидная альтернатива, поучительный пример или просто лень?
Git существует по причине. Если нужно вернуться к старому подходу — git log найдёт его. Удалите мёртвый код.
4. Обрабатывайте ошибки там, где они происходят
Худший паттерн: перехватывать исключения на верхнем уровне и логировать «что-то пошло не так». К тому времени как ошибка достигает этого блока, весь контекст потерян.
Обрабатывайте ошибки близко к месту их возникновения:
// Плохо
try {
await sendEmail(user.email, template);
} catch (err) {
logger.error('Email failed');
}
// Хорошо
try {
await sendEmail(user.email, template);
} catch (err) {
logger.error('Failed to send welcome email', {
userId: user.id,
email: user.email,
error: err.message
});
throw new EmailDeliveryError(`Welcome email failed for user ${user.id}`);
}
Второй вариант говорит вам всё необходимое для отладки без погружения в логи.
5. Пишите тесты на поведение, а не реализацию
Тесты должны проверять что делает ваш код, а не как он это делает.
Когда тесты тесно связаны с деталями реализации — они ломаются при каждом рефакторинге. В итоге получается тест-сюит, который больше препятствие, чем страховочная сеть.
Пишите тесты, описывающие поведение снаружи:
- «Когда пользователь вводит неверный email, появляется ошибка»
- «Когда платёж прошёл, статус заказа становится confirmed»
- «Когда БД недоступна, API возвращает 503 с retry-заголовком»
Такие тесты переживают рефакторинг. Они документируют намерение.
Эффект накопления
Ни один из этих принципов не является драматичным сам по себе. Эффект приходит от применения всех их, последовательно, в каждом файле проекта.
Кодовая база, следующая этим правилам: новые инженеры продуктивны через дни. Фичи добавляются без страха. Баги находятся за часы. Система растёт без пропорционального роста команды.
Если хотите, чтобы следующий проект строился по этим стандартам с первого дня, давайте поговорим.