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

Делал ли рефакторинг кода

1.0 Junior🔥 211 комментариев
#Soft Skills#Архитектура и паттерны

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

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

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

Опыт рефакторинга кода

Да, я регулярно выполняю рефакторинг и вижу это как неотъемлемую часть профессиональной разработки. Рефакторинг не стоит путать с переписыванием — это улучшение кода без изменения его функциональности.

Что такое рефакторинг

Рефакторинг — это процесс улучшения внутренней структуры кода без изменения его внешнего поведения. Цели:

  • Улучшить читаемость
  • Снизить сложность (cyclomatic complexity)
  • Убрать дублирование (DRY)
  • Улучшить тестируемость
  • Облегчить поддержку

Категории рефакторинга

1. Извлечение функций (Extract Function)

До рефакторинга:

def process_user_order(user_id, items):
    # Получаем пользователя
    user = db.query(User).filter(User.id == user_id).first()
    if not user:
        raise ValueError('User not found')
    
    # Вычисляем сумму
    total = 0
    for item in items:
        product = db.query(Product).filter(Product.id == item['id']).first()
        price = product.price * item['quantity']
        if user.discount > 0:
            price *= (1 - user.discount / 100)
        total += price
    
    # Создаём заказ
    order = Order(user_id=user_id, total=total)
    db.add(order)
    db.commit()
    
    return order

После рефакторинга:

def process_user_order(user_id, items):
    user = get_user(user_id)
    total = calculate_order_total(user, items)
    order = create_order(user_id, total)
    return order


def get_user(user_id):
    user = db.query(User).filter(User.id == user_id).first()
    if not user:
        raise ValueError('User not found')
    return user


def calculate_order_total(user, items):
    total = 0
    for item in items:
        price = get_item_price(item)
        price = apply_discount(price, user.discount)
        total += price
    return total


def get_item_price(item):
    product = db.query(Product).filter(Product.id == item['id']).first()
    return product.price * item['quantity']


def apply_discount(price, discount):
    if discount > 0:
        return price * (1 - discount / 100)
    return price


def create_order(user_id, total):
    order = Order(user_id=user_id, total=total)
    db.add(order)
    db.commit()
    return order

Плюсы: Код читается как проза, легко тестировать, легко переиспользовать.

2. Замена условного оператора на полиморфизм

До рефакторинга:

def calculate_price(user_type, base_price):
    if user_type == 'premium':
        return base_price * 0.8
    elif user_type == 'regular':
        return base_price * 0.9
    elif user_type == 'guest':
        return base_price
    else:
        raise ValueError('Unknown user type')

После рефакторинга:

from abc import ABC, abstractmethod

class UserType(ABC):
    @abstractmethod
    def calculate_price(self, base_price):
        pass


class PremiumUser(UserType):
    def calculate_price(self, base_price):
        return base_price * 0.8


class RegularUser(UserType):
    def calculate_price(self, base_price):
        return base_price * 0.9


class GuestUser(UserType):
    def calculate_price(self, base_price):
        return base_price


def calculate_price(user: UserType, base_price):
    return user.calculate_price(base_price)

Плюсы: Легко добавлять новые типы пользователей без изменения основного кода (Open/Closed Principle).

3. Удаление дублирования (DRY)

До рефакторинга:

def validate_email(email):
    if not email:
        raise ValueError('Email is required')
    if '@' not in email:
        raise ValueError('Invalid email format')
    if len(email) > 255:
        raise ValueError('Email is too long')
    return email


def validate_password(password):
    if not password:
        raise ValueError('Password is required')
    if '@' not in password:  # Глупо, но дублирование
        raise ValueError('Invalid password format')
    if len(password) > 255:
        raise ValueError('Password is too long')
    return password

После рефакторинга:

def validate_field(value, field_name, validators=None):
    validators = validators or []
    
    if not value:
        raise ValueError(f'{field_name} is required')
    
    for validator in validators:
        if not validator(value):
            raise ValueError(f'Invalid {field_name} format')
    
    if len(str(value)) > 255:
        raise ValueError(f'{field_name} is too long')
    
    return value


def validate_email(email):
    return validate_field(email, 'Email', [lambda x: '@' in x])


def validate_password(password):
    return validate_field(password, 'Password', [
        lambda x: len(x) >= 8,
        lambda x: any(c.isupper() for c in x)
    ])

4. Упрощение сложного условия

До рефакторинга:

if user.is_active and user.has_subscription and user.subscription.is_valid and not user.is_banned and user.balance > 0:
    process_payment(user)

После рефакторинга:

if is_eligible_for_payment(user):
    process_payment(user)


def is_eligible_for_payment(user):
    return (
        user.is_active
        and user.has_subscription
        and user.subscription.is_valid
        and not user.is_banned
        and user.balance > 0
    )

5. Переименование переменных

До рефакторинга:

users = get_users()
for u in users:
    if u.age > 18 and u.status == 'active':
        u.send_promo_email()  # Непонятно что происходит

После рефакторинга:

active_adult_users = get_active_adult_users()
for user in active_adult_users:
    user.send_promotional_email()

Типичные метрики улучшения

После рефакторинга обычно улучшаются:

МетрикаУлучшение
Cyclomatic ComplexityСнижение на 30-50%
Дублирование кодаСнижение на 20-40%
Test CoverageУвеличение на 10-30%
Time to fix bugsСнижение на 40-60%
Onboarding timeСнижение для новичков

Когда делать рефакторинг

Делать:

  • Когда функция больше 30 строк
  • Когда cyclomatic complexity > 5
  • Перед добавлением нового функционала
  • Когда нужно исправить баг и код непонятный
  • Когда вспоминаешь код дольше, чем его переписываешь

Не делать:

  • Во время критичного падежа (fix fast first)
  • Без покрытия тестами
  • Одновременно с добавлением функционала
  • Если это наносит вред performance

Boy Scout Rule

Это мой подход:

  • Каждый раз когда трогаю код — немного его улучшу
  • Не нужно идеальное решение за один раз
  • Мелкие улучшения накапливаются
  • Главное — оставить код лучше, чем был

Инструменты для рефакторинга

# Анализ кода
# pylint, flake8, black — форматирование и анализ
# Refactoring IDE — PyCharm умеет много автоматизировать

# Тестирование перед рефакторингом
def test_order_calculation():
    user = create_test_user(discount=20)
    items = [{'id': 1, 'quantity': 2}]
    total = calculate_order_total(user, items)
    assert total > 0
    # Тесты гарантируют, что поведение не изменилось

Вывод

Рефакторинг — это не факультативный процесс, а обязательная часть профессиональной разработки. Я регулярно его делаю, следуя SOLID, DRY и KISS принципам. Главное правило: без хороших тестов не делай рефакторинг, они гарантируют, что ты ничего не сломал.