Перейти к содержимому

82. Best practices

JavaScript: Best Practices – Пишем чистый, поддерживаемый код

Заголовок раздела «JavaScript: Best Practices – Пишем чистый, поддерживаемый код»

Иллюстрация к уроку

Привет! Как опытный разработчик, ты знаешь, что написать рабочий код – это полдела. Настоящая магия начинается, когда твой код чист, легок для понимания и прост в поддержке другими (или тобой самим через полгода!). В этом уроке мы погрузимся в мир “Best Practices” – лучших практик, которые сделают твой JavaScript-код по-настоящему профессиональным.

Это не просто прихоть. Это набор принципов и рекомендаций, которые помогают:

  • Улучшить читаемость и понимание кода.
  • Снизить количество багов.
  • Ускорить разработку и облегчить отладку.
  • Сделать код более масштабируемым и поддерживаемым.

Поехали!

Используй осмысленные имена для переменных, функций и классов. Избегай сокращений, если они не общеприняты. const для неизменяемых переменных.

// Плохо 👎
let usr = "Alice";
function calc() { /* ... */ }
// Хорошо 👍
const userName = "Alice"; // Используем `const`
function calculateTotalPrice(items) { /* ... */ }
const API_URL = "https://api.example.com/data"; // Константы в верхнем регистре

2. Функции с одной ответственностью (Single Responsibility Principle)

Заголовок раздела «2. Функции с одной ответственностью (Single Responsibility Principle)»

Каждая функция должна делать ОДНУ вещь и делать её хорошо. Это улучшает переиспользуемость.

// Хорошо 👍: разделение ответственности
function validateUser(user) {
if (!user || !user.name) {
throw new Error("Invalid user data");
}
}
function formatUserName(name) {
return name.trim().toUpperCase();
}
async function saveUserToDatabase(user) {
// Имитация сохранения в БД
return Promise.resolve({ id: Math.random().toFixed(0), ...user });
}
async function handleUserRegistration(user) {
validateUser(user);
const formattedName = formatUserName(user.name);
const savedUser = await saveUserToDatabase({ ...user, name: formattedName });
console.log(`User ${savedUser.name} with ID ${savedUser.id} registered.`);
}
handleUserRegistration({ name: "john doe", email: "[email protected]" });

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

const userProfile = { name: "Bob", email: "[email protected]", settings: { theme: "dark" } };
// Хорошо 👍: создание новой копии с изменениями с помощью spread-оператора
const updatedProfile = {
...userProfile, // Копируем все свойства
email: "[email protected]", // Обновляем email
settings: {
...userProfile.settings, // Копируем настройки
theme: "light" // Обновляем тему
}
};
console.log(userProfile.settings.theme); // "dark" (исходный не изменился)
console.log(updatedProfile.settings.theme); // "light"

4. Деструктуризация и Spread-оператор для чистоты кода

Заголовок раздела «4. Деструктуризация и Spread-оператор для чистоты кода»

Используй их для более лаконичного и читаемого кода.

// Получение свойств из объекта
const product = { id: 1, name: "Laptop", price: 1200 };
const { name, price } = product;
console.log(`Product: ${name}, Price: $${price}`);
// Передача параметров функции
function createUser({ username, password, email }) { // Деструктуризация параметров
console.log(`Creating user: ${username}, Email: ${email}`);
}
createUser({ username: "john_doe", password: "pwd", email: "[email protected]" });
// Объединение массивов
const arr1 = [1, 2];
const arr2 = [3, 4];
const combinedArr = [...arr1, ...arr2, 5]; // [1, 2, 3, 4, 5]

Пиши асинхронный код так, чтобы он выглядел синхронным. Избегай “Callback Hell” и громоздких цепочек .then().

async function fetchUserPosts(userId) {
try {
const userResponse = await fetch(`https://jsonplaceholder.typicode.com/users/${userId}`);
const userData = await userResponse.json();
const postsResponse = await fetch(`https://jsonplaceholder.typicode.com/users/${userId}/posts`);
const userPosts = await postsResponse.json();
return { user: userData, posts: userPosts };
} catch (error) {
console.error("Ошибка при получении данных:", error);
throw error; // Передаем ошибку дальше
}
}
fetchUserPosts(1).then(data => console.log(data.user.name, data.posts.length));

Всегда предусматривай обработку ошибок, особенно в асинхронных операциях.

async function fetchDataWithErrorHandling(url) {
try {
const response = await fetch(url);
if (!response.ok) { // Проверяем статус HTTP
throw new Error(`HTTP error! Status: ${response.status}`);
}
const data = await response.json();
return data;
} catch (error) {
console.error("Не удалось получить данные:", error.message);
// Можно отправить ошибку в систему логирования: Sentry.captureException(error);
return null; // Или выбросить ошибку снова `throw error;`
}
}
fetchDataWithErrorHandling('https://jsonplaceholder.typicode.com/non-existent-endpoint')
.then(data => console.log('Данные:', data))
.catch(err => console.error('Обработанная ошибка в промисе:', err));
  • Линтеры и Форматтеры: Используй ESLint для проверки кода на соответствие стандартам и Prettier для автоматического форматирования. Это обеспечит консистентность в команде.

  • Раннее возвращение (Early Return): Выходи из функции как можно раньше, чтобы избежать глубокой вложенности if/else.

    function processOrderClean(order) {
    if (!order || !order.items || order.items.length === 0) {
    console.error("Invalid order");
    return; // Ранний выход
    }
    // Вся логика обработки здесь, без вложенности
    console.log("Order processed successfully.");
    }
  1. Непреднамеренная мутация состояния: Изменение объектов/массивов напрямую, вместо создания новых копий, ведет к трудноотслеживаемым ошибкам.
  2. Пропущенная обработка ошибок: Особенно в асинхронном коде, что может привести к “тихим” сбоям приложения.
  3. Нечитаемый код: Запутанные имена, глубокая вложенность, огромные функции – все это замедляет разработку.
  • Начни с малого: Внедряй практики постепенно.
  • Используй инструменты: ESLint, Prettier – твои лучшие друзья.
  • Ревью кода: Активно участвуй в ревью, как проверяющий, так и проверяемый.
  • Читай чужой код: Изучай открытые проекты, ищи примеры хорошего кода.
  • Практикуйся: Чем больше пишешь, тем лучше чувствуешь “правильный” код.

Внедряя эти Best Practices, ты не только улучшишь качество своего кода, но и значительно повысишь свой профессиональный уровень как разработчика. Удачи!