Рефакторинг кода — как, для чего, когда
Рефакторинг кода — это процесс улучшения структуры существующего кода без изменения его внешнего поведения. Цель рефакторинга — сделать код более читаемым, поддерживаемым, эффективным и удобным для дальнейшего развития. Рефакторинг не добавляет новых функций, а лишь улучшает качество кода.
Зачем нужен рефакторинг?
- Улучшение читаемости: Код становится понятнее для других разработчиков и для вас в будущем.
- Упрощение поддержки: Упрощается процесс исправления ошибок и добавления новых функций.
- Устранение дублирования: Удаление повторяющегося кода уменьшает вероятность ошибок.
- Повышение производительности: Оптимизация кода может улучшить его скорость работы.
- Соблюдение принципов SOLID: Рефакторинг помогает привести код в соответствие с лучшими практиками разработки.
Примеры рефакторинга
1. Устранение дублирования кода
До рефакторинга:
def calculate_area(shape, *args):
if shape == "circle":
radius = args[0]
return 3.14 * radius * radius
elif shape == "rectangle":
length, width = args
return length * width
elif shape == "triangle":
base, height = args
return 0.5 * base * height
# Вызовы функций
print(calculate_area("circle", 5))
print(calculate_area("rectangle", 4, 6))
print(calculate_area("triangle", 3, 7))
После рефакторинга:
class Shape:
def area(self):
pass
class Circle(Shape):
def __init__(self, radius):
self.radius = radius
def area(self):
return 3.14 * self.radius * self.radius
class Rectangle(Shape):
def __init__(self, length, width):
self.length = length
self.width = width
def area(self):
return self.length * self.width
class Triangle(Shape):
def __init__(self, base, height):
self.base = base
self.height = height
def area(self):
return 0.5 * self.base * self.height
# Использование
circle = Circle(5)
rectangle = Rectangle(4, 6)
triangle = Triangle(3, 7)
print(circle.area())
print(rectangle.area())
print(triangle.area())
Что улучшено:
- Устранено дублирование логики вычисления площади.
- Код стал более расширяемым (легко добавить новые фигуры).
2. Упрощение сложных условий
До рефакторинга:
def get_discount(age, is_student, is_employed):
if age < 18:
return "50% discount"
elif age >= 18 and age <= 25 and is_student:
return "30% discount"
elif age > 60 and not is_employed:
return "40% discount"
else:
return "No discount"
После рефакторинга:
def get_discount(age, is_student, is_employed):
if age < 18:
return "50% discount"
if 18 <= age <= 25 and is_student:
return "30% discount"
if age > 60 and not is_employed:
return "40% discount"
return "No discount"
Что улучшено:
- Упрощены условия, удалены лишние проверки.
- Код стал более читаемым.
3. Разделение большой функции на smaller функции
До рефакторинга:
def process_data(data):
# Очистка данных
cleaned_data = []
for item in data:
if item.strip():
cleaned_data.append(item.strip())
# Фильтрация данных
filtered_data = []
for item in cleaned_data:
if item.startswith("A"):
filtered_data.append(item)
# Сортировка данных
sorted_data = sorted(filtered_data)
return sorted_data
После рефакторинга:
def clean_data(data):
return [item.strip() for item in data if item.strip()]
def filter_data(data):
return [item for item in data if item.startswith("A")]
def sort_data(data):
return sorted(data)
def process_data(data):
cleaned_data = clean_data(data)
filtered_data = filter_data(cleaned_data)
sorted_data = sort_data(filtered_data)
return sorted_data
Что улучшено:
- Большая функция разделена на smaller функции, каждая из которых выполняет одну задачу.
- Код стал более модульным и тестируемым.
4. Замена магических чисел на константы
До рефакторинга:
def calculate_tax(income):
if income < 10000:
return income * 0.1
elif income < 50000:
return income * 0.2
else:
return income * 0.3
После рефакторинга:
TAX_RATE_LOW = 0.1
TAX_RATE_MEDIUM = 0.2
TAX_RATE_HIGH = 0.3
INCOME_THRESHOLD_LOW = 10000
INCOME_THRESHOLD_MEDIUM = 50000
def calculate_tax(income):
if income < INCOME_THRESHOLD_LOW:
return income * TAX_RATE_LOW
elif income < INCOME_THRESHOLD_MEDIUM:
return income * TAX_RATE_MEDIUM
else:
return income * TAX_RATE_HIGH
Что улучшено:
- Магические числа заменены на константы, что делает код более понятным и удобным для изменения.
Принципы рефакторинга
- Делайте маленькие шаги: Изменяйте код постепенно, чтобы не сломать его.
- Пишите тесты: Убедитесь, что после рефакторинга код работает корректно.
- Избегайте рефакторинга и добавления функциональности одновременно: Сначала рефакторинг, потом новая функциональность.
- Следуйте принципам SOLID:
- Single Responsibility: Каждый класс или функция должны решать одну задачу.
- Open/Closed: Код должен быть открыт для расширения, но закрыт для изменений.
- Liskov Substitution: Подтипы должны быть заменяемы своими базовыми типами.
- Interface Segregation: Много специализированных интерфейсов лучше одного общего.
- Dependency Inversion: Зависимости должны строиться на абстракциях, а не на деталях.
Инструменты для рефакторинга
- Для Python:
black
,flake8
,pylint
,autopep8
. - Для JavaScript:
ESLint
,Prettier
. - Для Java:
IntelliJ IDEA
,Eclipse
. - Для PHP:
PHPStan
,Psalm
.
Рефакторинг — это важная часть разработки, которая помогает поддерживать код в хорошем состоянии. Регулярно рефакторите код, чтобы избежать накопления технического долга!