← Назад к вопросам

Как понять что код плохой?

2.3 Middle🔥 191 комментариев
#Архитектура и паттерны

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI2 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Как понять что код плохой

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

Признаки плохого кода

1. Дублирование кода (DRY нарушение)

// ❌ Плохо — повторение одной логики
function getUserName(id) {
  const user = database.users.find(u => u.id === id);
  const name = user ? user.name : 'Anonymous';
  return name;
}

function getProductName(id) {
  const product = database.products.find(p => p.id === id);
  const name = product ? product.name : 'Unknown';
  return name;
}

function getAuthorName(id) {
  const author = database.authors.find(a => a.id === id);
  const name = author ? author.name : 'Unknown';
  return name;
}

// ✅ Хорошо — общая функция
function getName(collection, id, fallback = 'Unknown') {
  const item = collection.find(i => i.id === id);
  return item ? item.name : fallback;
}

const userName = getName(database.users, userId, 'Anonymous');
const productName = getName(database.products, productId);
const authorName = getName(database.authors, authorId);

2. Функции делают слишком много (SRP нарушение)

// ❌ Плохо — функция делает всё
function processUser(userData) {
  // Валидация
  if (!userData.email || !userData.name) {
    throw new Error('Invalid data');
  }
  
  // Форматирование
  const formattedData = {
    ...userData,
    email: userData.email.toLowerCase(),
    name: userData.name.trim()
  };
  
  // API запрос
  fetch('/api/users', {
    method: 'POST',
    body: JSON.stringify(formattedData)
  });
  
  // Логирование
  console.log('User created:', formattedData);
  
  // Уведомление
  sendEmail(userData.email, 'Welcome!');
}

// ✅ Хорошо — разделение ответственности
function validateUser(userData) {
  if (!userData.email || !userData.name) {
    throw new Error('Invalid data');
  }
}

function formatUser(userData) {
  return {
    ...userData,
    email: userData.email.toLowerCase(),
    name: userData.name.trim()
  };
}

async function saveUser(userData) {
  const response = await fetch('/api/users', {
    method: 'POST',
    body: JSON.stringify(userData)
  });
  return response.json();
}

async function processUser(userData) {
  validateUser(userData);
  const formatted = formatUser(userData);
  const saved = await saveUser(formatted);
  console.log('User created:', saved);
  await sendEmail(saved.email, 'Welcome!');
  return saved;
}

3. Сложные условия (Циклическая сложность)

// ❌ Плохо — вложенные условия
function getDiscount(user, product, season) {
  if (user.isPremium) {
    if (product.category === 'electronics') {
      if (season === 'sale') {
        return 0.5;
      } else if (season === 'regular') {
        return 0.3;
      }
    } else if (product.category === 'clothing') {
      if (season === 'sale') {
        return 0.4;
      } else {
        return 0.2;
      }
    }
  } else {
    if (product.category === 'electronics') {
      return 0.1;
    } else if (product.category === 'clothing') {
      return 0.05;
    }
  }
  return 0;
}

// ✅ Хорошо — lookup table
const discountRules = {
  premium: {
    electronics: { sale: 0.5, regular: 0.3 },
    clothing: { sale: 0.4, regular: 0.2 },
  },
  regular: {
    electronics: { sale: 0.1, regular: 0 },
    clothing: { sale: 0.05, regular: 0 },
  },
};

function getDiscount(user, product, season) {
  const type = user.isPremium ? 'premium' : 'regular';
  return discountRules[type]?.[product.category]?.[season] ?? 0;
}

4. Магические числа и строки

// ❌ Плохо — непонятные значения
function validatePassword(password) {
  if (password.length < 8) return false;  // Откуда 8?
  if (password.length > 128) return false; // Откуда 128?
  return true;
}

function calculatePrice(quantity, price) {
  return quantity * price * 0.85; // Откуда 0.85? (это налог?)
}

// ✅ Хорошо — именованные константы
const PASSWORD_MIN_LENGTH = 8;
const PASSWORD_MAX_LENGTH = 128;
const TAX_RATE = 0.85;

function validatePassword(password) {
  return password.length >= PASSWORD_MIN_LENGTH && 
         password.length <= PASSWORD_MAX_LENGTH;
}

function calculatePrice(quantity, price) {
  return quantity * price * TAX_RATE;
}

5. Длинные функции

// ❌ Плохо — функция на 100+ строк
function handleUserRegistration(email, password, name, phone) {
  // 30 строк валидации
  // 20 строк форматирования
  // 15 строк API запроса
  // 20 строк обработки ошибок
  // 10 строк логирования
  // ...
}

// ✅ Хорошо — маленькие, понятные функции
function handleUserRegistration(email, password, name, phone) {
  const userData = { email, password, name, phone };
  validateUserData(userData);
  const formatted = formatUserData(userData);
  return registerUser(formatted);
}

6. Плохие имена переменных

// ❌ Плохо — неинформативные имена
function calc(a, b, c) {
  const x = a * b;
  const y = x + c;
  const z = y * 0.1;
  return z;
}

const data = [1, 2, 3];
const d = data.map(v => v * 2);
const temp = d.filter(i => i > 3);

// ✅ Хорошо — понятные имена
function calculateDiscountedPrice(basePrice, quantity, discount) {
  const subtotal = basePrice * quantity;
  const total = subtotal + discount;
  const finalPrice = total * TAX_RATE;
  return finalPrice;
}

const prices = [10, 20, 30];
const doubledPrices = prices.map(price => price * 2);
const expensiveItems = doubledPrices.filter(price => price > 30);

7. Обработка ошибок

// ❌ Плохо — игнорируем ошибки
function fetchData(url) {
  try {
    const response = fetch(url);
    return response.json();
  } catch (e) {
    console.log('error'); // Плохое логирование
  }
}

// ✅ Хорошо — правильная обработка
async function fetchData(url) {
  try {
    const response = await fetch(url);
    if (!response.ok) {
      throw new Error(`HTTP ${response.status}: ${response.statusText}`);
    }
    return await response.json();
  } catch (error) {
    console.error(`Failed to fetch data from ${url}:`, error);
    throw error; // Пробрасываем для обработки выше
  }
}

8. Асинхронность

// ❌ Плохо — callback hell
function getUser(id, callback) {
  fetch(`/api/users/${id}`)
    .then(res => res.json())
    .then(user => {
      fetch(`/api/posts/${user.id}`)
        .then(res => res.json())
        .then(posts => {
          fetch(`/api/comments/${posts[0].id}`)
            .then(res => res.json())
            .then(comments => {
              callback(user, posts, comments);
            });
        });
    });
}

// ✅ Хорошо — async/await
async function getUserData(id) {
  const user = await fetch(`/api/users/${id}`).then(r => r.json());
  const posts = await fetch(`/api/posts/${user.id}`).then(r => r.json());
  const comments = await fetch(`/api/comments/${posts[0].id}`).then(r => r.json());
  return { user, posts, comments };
}

9. Performance проблемы

// ❌ Плохо — неэффективно
function findUser(users, id) {
  // O(n) сложность
  return users.find(u => u.id === id);
}

// В цикле
for (let i = 0; i < 1000; i++) {
  const user = findUser(allUsers, userIds[i]); // O(n*m)
}

// ✅ Хорошо — оптимизировано
const usersMap = new Map(users.map(u => [u.id, u]));

for (let i = 0; i < 1000; i++) {
  const user = usersMap.get(userIds[i]); // O(1)
}

10. Type safety

// ❌ Плохо — нет типизации
function getUserAge(user) {
  return user.age; // Может быть undefined, null, string...
}

// ✅ Хорошо — TypeScript
interface User {
  id: string;
  name: string;
  age: number;
}

function getUserAge(user: User): number {
  return user.age; // Гарантировано число
}

Чеклист для проверки кода

[ ] Нет дублирования (DRY)
[ ] Каждая функция делает одно (SRP)
[ ] Функции небольшие (<50 строк)
[ ] Имена переменных понятные
[ ] Нет магических чисел
[ ] Обработка ошибок правильная
[ ] Асинхронный код с async/await
[ ] Хорошая производительность (O(n) вместо O(n^2))
[ ] Типизация (TypeScript)
[ ] Тесты есть (>90% coverage)
[ ] Код прошёл linter
[ ] Код понятен коллегам

Инструменты для анализа

# ESLint — проверка качества кода
npm run lint

# TypeScript — типизация
tsc --noEmit

# Code metrics
npm install --save-dev complexity-report

# Тесты
npm test

Вывод

Плохой код:

  • Дублируется (нарушает DRY)
  • Делает слишком много (нарушает SRP)
  • Сложен для понимания (плохие имена, магические числа)
  • Неэффективен (O(n^2) вместо O(n))
  • Без тестов (нет гарантий)
  • Без типизации (ошибки в runtime)

Хороший код:

  • Легко читается за несколько секунд
  • Легко тестируется (одна ответственность)
  • Легко поддерживается (понятные имена)
  • Легко расширяется (слабая связанность)
  • Быстро работает (оптимальная сложность)
Как понять что код плохой? | PrepBro