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

Что такое хороший код?

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

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

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

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

Что такое хороший код

Хороший код — это не просто код, который работает. Это код, который легко понять, поддерживать, тестировать и расширять. За 10+ лет разработки я выделил ключевые характеристики качественного кода.

1. Читаемость

Хороший код пишется для людей, не для компьютера. Компьютер просто выполняет инструкции.

# Плохо: непонятное имя переменной
def calc(x, y, z):
    r = x * y + z / 2
    return r if r > 0 else 0

# Хорошо: явное имя и назначение
def calculate_profit_margin(revenue, costs, discount):
    profit = revenue - costs + discount / 2
    return max(profit, 0)

Правила читаемости:

  • Значимые имена переменных, функций, классов
  • Функция делает одно, но делает хорошо
  • Избегаешь вложенности более чем на 3 уровня
  • Максимум 20-30 строк в функции (исключения редки)

2. Простота (KISS - Keep It Simple, Stupid)

Просто — не значит глупо. Это означает: не усложняй без необходимости.

# Плохо: оверинжиниринг
from abc import ABC, abstractmethod

class OperationFactory:
    _operations = {}
    
    @classmethod
    def register(cls, name, operation):
        cls._operations[name] = operation
    
    @classmethod
    def execute(cls, name, *args):
        return cls._operations[name](*args)

class Add(ABC):
    @abstractmethod
    def execute(self, a, b):
        pass

class AddImpl(Add):
    def execute(self, a, b):
        return a + b

OperationFactory.register('add', AddImpl().execute)
result = OperationFactory.execute('add', 2, 3)

# Хорошо: просто и понятно
def add(a, b):
    return a + b

result = add(2, 3)

Когда нужна сложность? Только когда задача действительно требует её.

3. Тестируемость

Хороший код легко тестировать. Если код сложно тестировать — значит его архитектура плохая.

# Плохо: зависимость от внешних сервисов, сложно тестировать
def process_payment(amount):
    api = PaymentAPI()  # Захардкодено
    api.charge(amount)
    db = Database()      # Захардкодено
    db.save_transaction(amount)

# Хорошо: зависимости инъектируются
def process_payment(amount, payment_api, database):
    payment_api.charge(amount)
    database.save_transaction(amount)

# Тестирование с mock объектами
from unittest.mock import Mock

mock_api = Mock()
mock_db = Mock()
process_payment(100, mock_api, mock_db)

mock_api.charge.assert_called_once_with(100)
mock_db.save_transaction.assert_called_once_with(100)

4. DRY (Don't Repeat Yourself)

Если ты пишешь один и тот же код дважды — это плохо.

# Плохо: дублирование
def validate_email(email):
    if '@' not in email or '.' not in email:
        raise ValueError("Invalid email")

def validate_phone(phone):
    if '+' not in phone or not phone[1:].isdigit():
        raise ValueError("Invalid phone")

# Хорошо: общая функция
import re

def validate_format(value, pattern, error_msg):
    if not re.match(pattern, value):
        raise ValueError(error_msg)

validate_format(email, r'^[\w.-]+@[\w.-]+\.\w+$', "Invalid email")
validate_format(phone, r'^\+\d{10,}$', "Invalid phone")

5. SOLID Принципы

Single Responsibility (Единая ответственность):

# Плохо: класс делает всё
class User:
    def create_user(self, data):
        self.validate(data)
        self.save_to_db(data)
        self.send_email(data['email'])
        self.log_event("User created")

# Хорошо: разделение ответственности
class User:
    def __init__(self, validator, repository, notifier, logger):
        self.validator = validator
        self.repository = repository
        self.notifier = notifier
        self.logger = logger
    
    def create(self, data):
        self.validator.validate(data)
        user = self.repository.save(data)
        self.notifier.send_welcome_email(user)
        self.logger.info(f"User {user.id} created")
        return user

Open/Closed (Открыто для расширения, закрыто для модификации):

# Плохо: нужно изменять функцию при добавлении нового типа
def calculate_discount(price, user_type):
    if user_type == 'premium':
        return price * 0.9
    elif user_type == 'vip':
        return price * 0.8
    elif user_type == 'regular':
        return price

# Хорошо: расширяемо без изменений
class DiscountStrategy:
    def apply(self, price):
        raise NotImplementedError

class PremiumDiscount(DiscountStrategy):
    def apply(self, price):
        return price * 0.9

class VIPDiscount(DiscountStrategy):
    def apply(self, price):
        return price * 0.8

def calculate_discount(price, strategy: DiscountStrategy):
    return strategy.apply(price)

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

Хороший код предусматривает ошибки и обрабатывает их правильно.

# Плохо: бледная обработка ошибок
try:
    result = 1 / 0
except:
    pass  # Игнорируем всё

# Хорошо: обработка конкретных ошибок
try:
    result = 1 / divisor
except ZeroDivisionError:
    logger.error("Division by zero", extra={"divisor": divisor})
    return None
except TypeError:
    logger.error("Invalid type for division", extra={"type": type(divisor)})
    raise

7. Производительность

Хороший код оптимален, но не оптимизирован раньше времени.

# Плохо: преждевременная микро-оптимизация
def search(items, target):
    # Очень быстро на малых списках, но сложно читать
    return next((i for i, x in enumerate(items) if x == target), -1) if items else -1

# Хорошо: понятно и достаточно быстро
def search(items, target):
    try:
        return items.index(target)
    except ValueError:
        return -1

# Оптимизируй, когда профилирование покажет проблему
import cProfile
cProfile.run('search(large_list, target)')  # Профилируй перед оптимизацией

8. Документация

Хороший код самодокументируется, но иногда нужны комментарии.

# Плохо: ненужные комментарии
x = 5  # устанавливаем x в 5
for i in range(x):  # цикл от 0 до x
    print(i)  # выводим i

# Хорошо: нет комментариев, но код понятен
max_retries = 5
for attempt in range(max_retries):
    print(attempt)

# Хорошо: комментарии объясняют ПОЧЕМУ, не ЧТО
def calculate_hash(data):
    # MurmurHash3 используем для лучшей распределении ключей в hash table
    # по сравнению со встроенным hash() который может быть медленнее
    return murmurhash3(data)

9. Версионирование и история

Хороший код имеет историю изменений с понятными commit сообщениями.

# Плохо
git commit -m "fixed stuff"
git commit -m "updates"

# Хорошо
git commit -m "fix: handle null pointers in payment processing

When payment API returns null, system crashed.
Now we validate response and return meaningful error.

Fixes #123"

10. Type Hints (в Python)

Хороший Python код использует type hints для безопасности.

# Плохо: неясно какие типы
def process(data):
    return len(data) > 0

# Хорошо: явные типы
def process(data: list[str]) -> bool:
    return len(data) > 0

# С mypy проверкой типов
from typing import Optional

def find_user(user_id: int) -> Optional[User]:
    # ...
    pass

11. Следование стилю проекта

Хороший код согласуется с существующим codebase.

# Если проект использует black для форматирования
python -m black myfile.py

# Если проект использует ruff для linting
python -m ruff check myfile.py

# Если проект имеет type hints
mypy myfile.py

12. Модульность

Хороший код разбивается на маленькие, переиспользуемые модули.

# Плохо: монолитный скрипт
api.py (5000 строк, всё в одном файле)

# Хорошо: модульная структура
api/
  __init__.py
  models/
    user.py
    post.py
  routes/
    auth.py
    posts.py
  services/
    user_service.py
    post_service.py
  middleware/
    auth.py
    logging.py

Практические метрики хорошего кода

  1. Cyclometric Complexity (сложность циклов) < 10 — хорошо
  2. Test Coverage > 80% — минимум для production
  3. Lines of Code в функции < 30 — идеал
  4. Code Duplication < 5% — хорошо
  5. Comment Ratio 10-20% — достаточно

Инструменты для контроля качества

# Python: статический анализ
mypy myfile.py          # Type checking
pylint myfile.py        # Лinting
ruff check myfile.py    # Fast linting
black myfile.py         # Форматирование

# Тестирование
pytest tests/ --cov     # Tests + coverage

# Профилирование
python -m cProfile myapp.py

Заключение

Хороший код — это баланс между:

  • Читаемостью (люди) и производительностью (компьютеры)
  • Простотой (сейчас) и расширяемостью (будущее)
  • Быстротой разработки (сроки) и качеством (поддержка)

Лучший способ писать хороший код — постоянно читать чужой код хороших проектов и учиться от опытных разработчиков.

Что такое хороший код? | PrepBro