Одна причина для изменения
Принцип единственной ответственности — это буква S в SOLID, пяти правилах проектирования кода, который остаётся простым для изменения. Он гласит: у типа должна быть одна задача — а значит, только одна причина для изменения.
Когда один тип и сохраняет заказы, и отправляет письма, он меняется, когда меняется хранилище, и когда меняется текст письма. Две задачи, две причины, вдвое больше риск сломать одно, трогая другое.
В Python это правило относится к классам, их методам и модулям: каждый из них должен быть сосредоточен на одной задаче.
Слишком много задач в одном классе
Этот обработчик заказов работает — но он сохраняет заказ, составляет текст подтверждения и «отправляет» его, всё в одном методе. Проверить текст письма отдельно невозможно, а повторное использование части с хранилищем в другом месте означает тащить за собой и код писем.
Один класс, который делает всё
process() смешивает две задачи: сохранение и уведомление. Любое изменение в одной из них означает правку — и повторное тестирование — этого же класса.
Вывод: полная программа на Python
class OrderProcessor:
# process выполняет две задачи: сохранение И уведомление.
def process(self, order, customer):
print("сохранение заказа в хранилище:", order)
print("отправка письма на", customer + ":")
print(" Спасибо! Ваш заказ", order, "получен.")
p = OrderProcessor()
p.process("#1042 (2 books)", "ana@example.com")
Одна задача на класс
Решение: один класс на одну задачу. OrderStore только сохраняет, EmailSender только отправляет. Небольшая функция координирует их работу.
Вывод тот же — но теперь каждую часть можно изменять, тестировать и повторно использовать отдельно.
Разделение на два класса
То же поведение, но разделённое: хранилище ничего не знает о письмах, отправитель ничего не знает о хранилище. Функция process_order просто соединяет их.
Вывод: полная программа на Python
# У OrderStore одна задача: сохранение заказов.
class OrderStore:
def save(self, order):
print("сохранение заказа в хранилище:", order)
# У EmailSender одна задача: отправка писем.
class EmailSender:
def send_confirmation(self, customer, order):
print("отправка письма на", customer + ":")
print(" Спасибо! Ваш заказ", order, "получен.")
def process_order(order, customer):
store = OrderStore()
sender = EmailSender()
store.save(order)
sender.send_confirmation(customer, order)
process_order("#1042 (2 books)", "ana@example.com")
Выигрыш: повторное использование без опасений
Поскольку отправитель — отдельный класс, он отправляет и уведомление об отгрузке — без участия кода хранилища. А хранилище архивирует заказ, не составляя ни одного письма. Каждый класс вырос в рамках своей единственной задачи.
Вывод: полная программа на Python
class OrderStore:
def save(self, order):
print("сохранение заказа в хранилище:", order)
def archive(self, order):
print("перемещение заказа в архив:", order)
class EmailSender:
def send_confirmation(self, customer, order):
print("письмо на", customer + ": заказ", order, "получен")
def send_shipping_notice(self, customer, order):
print("письмо на", customer + ": заказ", order, "отправлен")
store = OrderStore()
sender = EmailSender()
# Каждый класс растёт в рамках своей задачи.
sender.send_shipping_notice("ana@example.com", "#1042")
store.archive("#0997")