Принцип DRY в Python: как избегать повторений в коде
Принцип DRY в Python: как избегать повторений в коде
Принцип DRY (Don’t Repeat Yourself — «Не повторяйся») — одно из ключевых правил разработки программного обеспечения. Он направлен на минимизацию дублирования кода, что упрощает поддержку, уменьшает вероятность ошибок и повышает читаемость. В этой статье мы разберем, как применять DRY в Python, и покажем практические примеры.
Что такое DRY?
DRY — принцип, сформулированный в книге «The Pragmatic Programmer». Его суть:
«Каждое знание должно иметь единственное, однозначное представление в системе».
На практике это означает:
- Избегайте копирования блоков кода.
- Выносите повторяющуюся логику в функции, классы или модули.
- Используйте абстракции для управления изменениями.
Почему DRY важен?
- Упрощение изменений: Исправления вносятся в одном месте.
- Снижение ошибок: Меньше копий → меньше шансов забыть обновить дубликат.
- Читаемость: Код становится компактным и структурированным.
Примеры нарушений DRY и их исправление
1. Повторяющиеся вычисления
Проблема:
# Расчет НДС для трех товаров
price1 = 100
vat1 = price1 * 0.20 # НДС 20%
price2 = 200
vat2 = price2 * 0.20
price3 = 150
vat3 = price3 * 0.20
Решение через DRY:
def calculate_vat(price):
return price * 0.20
prices = [100, 200, 150]
vats = [calculate_vat(price) for price in prices]
2. Дублирование условий
Проблема:
if user_role == "admin":
print("Доступ разрешен")
log_action("Администратор вошел в систему")
elif user_role == "editor":
print("Доступ разрешен")
log_action("Редактор вошел в систему")
elif user_role == "guest":
print("Доступ запрещен")
Решение через DRY:
access_rules = {
"admin": ("Доступ разрешен", "Администратор вошел в систему"),
"editor": ("Доступ разрешен", "Редактор вошел в систему"),
"guest": ("Доступ запрещен", "")
}
if user_role in access_rules:
message, log_message = access_rules[user_role]
print(message)
if log_message:
log_action(log_message)
3. Повторяющиеся функции
Проблема:
def send_email_user(user_email, message):
# Код отправки email
...
def send_email_admin(admin_email, message):
# Тот же код, но для админа
...
Решение через DRY:
def send_email(recipient, message):
# Общая логика отправки
...
send_email(user_email, "Привет!")
send_email(admin_email, "Отчет готов")
Техники применения DRY в Python
1. Функции и классы
Выносите повторяющиеся операции в функции или методы классов:
# Вместо этого:
area1 = 3.14 * radius1 ** 2
area2 = 3.14 * radius2 ** 2
# Используйте функцию:
def circle_area(radius):
return 3.14 * radius ** 2
2. Циклы и генераторы
Заменяйте повторяющиеся строки циклами:
# Плохо:
print("Строка 1")
print("Строка 2")
print("Строка 3")
# Хорошо:
for i in range(1, 4):
print(f"Строка {i}")
3. Декораторы
Для повторяющейся логики (например, логирования или проверки прав):
def log_time(func):
def wrapper(*args, **kwargs):
start = time.time()
result = func(*args, **kwargs)
print(f"Время выполнения: {time.time() - start:.2f} сек")
return result
return wrapper
@log_time
def process_data(data):
# Логика обработки
...
4. Наследование
Если классы имеют общую функциональность:
class Animal:
def __init__(self, name):
self.name = name
def speak(self):
raise NotImplementedError
class Dog(Animal):
def speak(self):
return "Гав!"
class Cat(Animal):
def speak(self):
return "Мяу!"
5. Использование библиотек
Не изобретайте велосипеды. Например, для работы с датами используйте datetime:
from datetime import datetime
now = datetime.now() # Вместо ручного парсинка времени
Когда DRY не стоит применять?
- Избыточная абстракция: Не нужно объединять код, который лишь кажется похожим, но имеет разную природу.
- Микроменеджмент: Иногда дублирование пары строк лучше, чем усложнение архитектуры.
- Прототипирование: На ранних этапах можно нарушать DRY ради скорости.
Практические кейсы применения
- Валидация данных: Создайте единую функцию для проверки входных параметров.
- Шаблоны сообщений: Используйте
f-stringsили шаблонизаторы (например, Jinja2) для генерации текста. - Конфигурация: Храните настройки в отдельном файле (
config.pyили.env).
Заключение
Принцип DRY в Python помогает писать чистый, поддерживаемый и масштабируемый код. Главное — находить баланс: устранять вредное дублирование, но не создавать избыточных абстракций. Используйте функции, классы, декораторы и стандартные библиотеки, чтобы код оставался «сухим» (в хорошем смысле!).
Совет: Перед тем как скопировать код, спросите себя:
«Можно ли это вынести в отдельный модуль?». Часто ответ будет «да».