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

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

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

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

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


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

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

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

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

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

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

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

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

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

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

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

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

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

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