← Назад к вопросам
Как ты занимаешься рефакторингом?
1.2 Junior🔥 201 комментариев
#Архитектура и паттерны
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Процесс рефакторинга кода
Рефакторинг — это процесс улучшения внутреннего качества кода без изменения его внешнего поведения. Это не добавляет новые фичи, это делает код лучше.
Этапы рефакторинга
1. Анализ и идентификация проблем
# Плохой код — что нужно улучшить?
def process_user_data(user_list):
result = []
for u in user_list:
if u['age'] > 18 and u['status'] == 'active':
result.append({
'name': u['name'],
'age': u['age'],
'email': u['email']
})
return result
Проблемы:
- Имена переменных неинформативны (u, result)
- Без типизации
- Логика смешана с трансформацией
- Нет документации
2. Написание тестов ДО рефакторинга
import pytest
def test_process_active_adults():
users = [
{"name": "Alice", "age": 25, "status": "active", "email": "alice@ex.com"},
{"name": "Bob", "age": 17, "status": "active", "email": "bob@ex.com"},
{"name": "Charlie", "age": 30, "status": "inactive", "email": "ch@ex.com"},
]
result = process_user_data(users)
assert len(result) == 1
assert result[0]["name"] == "Alice"
def test_empty_input():
assert process_user_data([]) == []
3. Рефакторинг — шаг 1: типизация
from typing import TypedDict, List
class User(TypedDict):
name: str
age: int
status: str
email: str
class ProcessedUser(TypedDict):
name: str
age: int
email: str
def process_user_data(users: List[User]) -> List[ProcessedUser]:
return [
{"name": u["name"], "age": u["age"], "email": u["email"]}
for u in users
if u["age"] > 18 and u["status"] == "active"
]
4. Рефакторинг — шаг 2: выделение функций
def is_adult_and_active(user: User) -> bool:
"""Проверяет, является ли пользователь активным взрослым"""
return user["age"] > 18 and user["status"] == "active"
def extract_public_fields(user: User) -> ProcessedUser:
"""Извлекает только публичные данные пользователя"""
return {
"name": user["name"],
"age": user["age"],
"email": user["email"]
}
def process_user_data(users: List[User]) -> List[ProcessedUser]:
"""Получает данные активных взрослых пользователей"""
return [
extract_public_fields(u)
for u in users
if is_adult_and_active(u)
]
5. Рефакторинг — шаг 3: использование классов
from dataclasses import dataclass
@dataclass
class User:
name: str
age: int
status: str
email: str
def is_adult_and_active(self) -> bool:
return self.age > 18 and self.status == "active"
def public_data(self) -> dict:
return {
"name": self.name,
"age": self.age,
"email": self.email
}
class UserFilter:
@staticmethod
def get_active_adults(users: list[User]) -> list[dict]:
return [
user.public_data()
for user in users
if user.is_adult_and_active()
]
6. Запуск тестов — убеждаемся, что поведение не изменилось
pytest test_user.py -v
# Все тесты должны быть зелёные
Техники рефакторинга
Extract Method
# До
def calculate_total():
subtotal = sum(item.price for item in items)
tax = subtotal * 0.1
total = subtotal + tax
return total
# После
def calculate_total():
subtotal = _calculate_subtotal()
tax = _calculate_tax(subtotal)
return subtotal + tax
def _calculate_subtotal():
return sum(item.price for item in items)
def _calculate_tax(subtotal):
return subtotal * 0.1
Remove Duplication
# До
def validate_email(email):
if not email or "@" not in email:
raise ValueError("Invalid email")
def validate_username(username):
if not username or "@" in username:
raise ValueError("Invalid username")
# После
def validate_not_empty(value: str, field_name: str):
if not value:
raise ValueError(f"{field_name} cannot be empty")
def validate_email(email):
validate_not_empty(email, "Email")
if "@" not in email:
raise ValueError("Invalid email format")
Rename for clarity
# До
data = {"u": users, "a": active_only, "s": sorted_by_date}
# После
filtered_data = {
"users": all_users,
"active_only": filter_active(users),
"sorted_by_date": sort_by_date(users)
}
Инструменты рефакторинга в Python
# Форматирование кода
black myfile.py
# Статический анализ
flake8 myfile.py
ruff check myfile.py
# Type checking
mypy myfile.py
# Анализ сложности
radon cc myfile.py
# Удаление неиспользуемого кода
vulture myfile.py
SOLID принципы в рефакторинге
# S — Single Responsibility
class UserValidator: # Только валидация
def validate(self, user):
pass
class UserRepository: # Только доступ к данным
def save(self, user):
pass
# O — Open/Closed
class Shape:
def area(self):
raise NotImplementedError
class Circle(Shape):
def area(self):
return 3.14 * self.radius ** 2
class Square(Shape):
def area(self):
return self.side ** 2
Чек-лист рефакторинга
- Написать/обновить тесты — они вам помогут
- Запустить тесты — убедиться что работает
- Сделать изменение — маленькое, локальное
- Запустить тесты — проверить что не сломалось
- Повторить — шаги 3-4 много раз
- Code review — попроси коллегу посмотреть
- Commit — понятное сообщение: "Refactor: extract method X"
Когда рефакторить
✅ Когда:
- Код сложный и непонятный
- Duplication очевидна
- Нужно добавить фичу
- Тесты покрывают функцию
❌ Когда:
- Нет тестов
- Срочный дедлайн
- Код работает и никто не трогает
- Ты не понимаешь что делает код