Перейти к основному содержимому

Одна причина для изменения

Принцип единственной ответственности — это буква S в SOLID, пяти правилах проектирования кода, который остаётся легко изменять. Он гласит: у типа должна быть одна задача — а значит, и только одна причина для изменения.

Когда один тип сохраняет заказы и отправляет письма, он меняется и при изменении хранилища, и при изменении текста письма. Две задачи, две причины и вдвое больше риска сломать одно, пока трогаешь другое.

В Go это правило действует для структур, их методов и пакетов: пусть каждый из них занимается одной задачей.


Слишком много задач в одном типе

Этот обработчик заказов работает — но он сохраняет заказ, составляет текст подтверждения и «отправляет» его, и всё это в одном методе. Проверить отдельно только текст письма невозможно, а чтобы переиспользовать часть с хранилищем в другом месте, придётся тащить за собой и код писем.

Один тип, который делает всё

Process() смешивает две задачи: сохранение и уведомление. Любое изменение в одной из них означает правку — и повторную проверку — этого же самого типа.

Prompt
Напишите программу на Go со структурой OrderProcessor, метод Process которой выполняет сразу две задачи: печатает, что заказ сохранён в хранилище, и печатает текст письма-подтверждения для клиента. Обработайте один заказ, чтобы показать, что всё работает, — как отправную точку для разговора о принципе единственной ответственности.
Вывод: программа на Go и захваченный вывод

Одна задача на тип

Решение: по одному типу на задачу. OrderStore только сохраняет, EmailSender только отправляет. Небольшая функция их связывает.

Вывод остаётся прежним — но теперь каждую часть можно изменять, тестировать и переиспользовать отдельно.

Разделение на два типа

То же поведение, но разделённое: хранилище ничего не знает о письмах, отправитель ничего не знает о хранении. Функция processOrder просто соединяет их.

Prompt
Переработайте обработку заказов в два типа Go, у каждого из которых одна задача: OrderStore с методом Save, который печатает шаг сохранения, и EmailSender с методом SendConfirmation, который печатает письмо. Добавьте функцию processOrder, вызывающую оба метода. Обработайте один заказ и покажите тот же вывод, что и раньше.
Вывод: программа на Go и захваченный вывод

Выгода: переиспользование без страха

Поскольку отправитель — самостоятельный тип, он отправляет ещё и уведомление об отгрузке, и код хранилища тут ни при чём. А хранилище архивирует заказ, не составляя ни одного письма. Каждый тип вырос внутри своей единственной задачи.

Prompt
Используя разделённые типы OrderStore и EmailSender на Go, покажите выгоду от единственной ответственности: отправьте уведомление об отгрузке тем же отправителем, не трогая хранилище, и заархивируйте заказ через хранилище, не отправляя ни одного письма. Напечатайте каждое действие.
Вывод: программа на Go и захваченный вывод