Почему «чистый код» — это не про эстетику, а про деньги и время
Представьте, что вы открываете чужой проект на JavaScript. Переменные называются a, b, x1. Функция длиной в 300 строк. Вложенность условий — как матрёшка. Знакомо? Если вы хоть раз проклинали такого «автора», значит, вы уже понимаете, зачем нужен чистый код.
Чистый код на JavaScript — это не дань моде и не прихоть перфекциониста. Это инструмент, который экономит часы дебага, упрощает онбординг новичков и снижает стоимость поддержки проекта. В этой статье мы разберём конкретные правила и приёмы, которые помогут вам писать код, понятный не только машине, но и человеку.
Правило №1: Имена переменных и функций должны говорить сами за себя
Самая распространённая ошибка новичков — использовать короткие и ничего не значащие имена. Плохой пример:
let d = new Date();
let n = d.getDay();
let r = n === 0 || n === 6 ? 'Выходной' : 'Будний день';
console.log(r);
Хороший пример:
const currentDate = new Date();
const dayOfWeek = currentDate.getDay();
const isWeekend = dayOfWeek === 0 || dayOfWeek === 6;
const dayType = isWeekend ? 'Выходной' : 'Будний день';
console.log(dayType);
Разница очевидна. Во втором варианте мы сразу понимаем, что делает код, без дополнительных комментариев. Совет: используйте существительные для переменных и глаголы для функций. Например: getUserData(), calculateTotal(), isValidEmail().
Как избежать «магических чисел»?
Магические числа — это цифры, смысл которых непонятен без контекста. Вместо них используйте константы:
// Плохо
if (user.role === 1) { ... }
// Хорошо
const ROLE_ADMIN = 1;
if (user.role === ROLE_ADMIN) { ... }
Правило №2: Функции должны быть маленькими и делать только одно
Принцип единственной ответственности (Single Responsibility) применим не только к классам, но и к функциям. Если функция делает три дела — она должна быть разбита на три функции. Плохой пример:
function processOrder(order) {
// Валидация
if (!order.items || order.items.length === 0) {
throw new Error('Корзина пуста');
}
// Расчёт скидки
let discount = 0;
if (order.total > 1000) {
discount = 0.1;
}
// Отправка email
sendEmail(order.email, 'Ваш заказ принят');
return order.total - order.total * discount;
}
Хороший пример (рефакторинг):
function validateOrder(order) {
if (!order.items || order.items.length === 0) {
throw new Error('Корзина пуста');
}
}
function calculateDiscount(total) {
return total > 1000 ? 0.1 : 0;
}
function notifyCustomer(email) {
sendEmail(email, 'Ваш заказ принят');
}
function processOrder(order) {
validateOrder(order);
const discount = calculateDiscount(order.total);
notifyCustomer(order.email);
return order.total - order.total * discount;
}
Такая структура позволяет легко тестировать каждую часть отдельно и менять логику, не затрагивая остальной код.
Правило №3: Избегайте глубокой вложенности
Чем больше уровней вложенности (if внутри if внутри for), тем сложнее читать код. Используйте ранний возврат (early return) и guard clauses.
// Плохо
function getUserDisplayName(user) {
if (user) {
if (user.name) {
if (user.name.length > 0) {
return user.name;
}
}
}
return 'Аноним';
}
// Хорошо
function getUserDisplayName(user) {
if (!user || !user.name || user.name.length === 0) {
return 'Аноним';
}
return user.name;
}
Правило №4: DRY — Don't Repeat Yourself
Дублирование кода — главный враг чистоты. Если вы видите, что один и тот же кусок кода встречается дважды, выносите его в функцию или переменную. Пример:
// Дублирование
const price1 = basePrice * 1.2;
const price2 = basePrice * 1.5;
// Чистый код
const addVAT = (price, rate) => price * rate;
const price1 = addVAT(basePrice, 1.2);
const price2 = addVAT(basePrice, 1.5);
Но не переусердствуйте. Иногда дублирование оправдано (например, для читаемости), но в 90% случаев его лучше избегать.
Правило №5: Комментарии — это запах кода
Хороший код не требует комментариев. Если вам хочется написать «// Здесь мы проверяем, является ли пользователь админом», значит, ваша функция или переменная названы неправильно. Переименуйте их. Комментарии нужны только для объяснения почему вы сделали именно так, а не иначе (например, из-за бага в браузере).
// Плохо
// Суммируем цены
let s = 0;
for (let i = 0; i < items.length; i++) {
s += items[i].price;
}
// Хорошо
const totalPrice = items.reduce((sum, item) => sum + item.price, 0);
Правило №6: Используйте современный синтаксис (ES6+)
Старый JavaScript (ES5) был многословным. Новый синтаксис делает код короче и понятнее. Вот несколько приёмов, которые стоит использовать:
- Стрелочные функции вместо
functionдля коротких колбэков. - Деструктуризация для извлечения данных из объектов и массивов.
- Spread-оператор (
...) для копирования и объединения. - Шаблонные строки вместо конкатенации.
// Старый стиль
var name = user.name;
var age = user.age;
var message = 'Привет, ' + name + '! Тебе ' + age + ' лет.';
// Современный стиль
const { name, age } = user;
const message = `Привет, ${name}! Тебе ${age} лет.`;
Правило №7: Принцип KISS (Keep It Simple, Stupid)
Не усложняйте там, где можно сделать просто. Одна из главных проблем разработчиков — желание написать «умный» код в одну строку, который потом никто не может понять. Пример переусложнения:
const result = arr.filter(x => x > 0).map(x => x * 2).reduce((a, b) => a + b, 0);
Этот код рабочий, но его сложно дебажить. Лучше разбить на шаги: