Одна причина для изменения
Принцип единственной ответственности — это буква S в SOLID, пяти правилах проектирования кода, который остаётся легко изменяемым. Он говорит: у класса должна быть одна задача — а значит, и только одна причина для изменения.
Когда один класс сохраняет заказы и отправляет письма, он меняется и при смене хранилища, и при смене текста письма. Две задачи, две причины, вдвое больше риска сломать одно, пока правишь другое.
В PHP это правило относится к классам, их методам и целым файлам: каждый из них должен быть сосредоточен на одной задаче.
Слишком много задач в одном классе
Этот обработчик заказов работает — но он сохраняет заказ, составляет текст подтверждения и «отправляет» его, всё в одном методе. Протестировать только текст письма невозможно, а чтобы переиспользовать часть с хранением, придётся тащить за собой и код отправки письма.
Один класс, который делает всё
process() смешивает две задачи: хранение и уведомление. Любое изменение в любой из них означает правку — и повторное тестирование — этого же класса.
Вывод: PHP-скрипт
<?php
class OrderProcessor {
// process выполняет две задачи: сохранение И уведомление.
public function process(string $order, string $customer): void {
echo "сохраняем заказ в хранилище: $order\n";
echo "отправляем письмо на $customer:\n";
echo " Спасибо! Ваш заказ $order получен.\n";
}
}
$p = new OrderProcessor();
$p->process("#1042 (2 books)", "ana@example.com");
Одна задача на класс
Решение: по одному классу на задачу. OrderStore только сохраняет, EmailSender только отправляет. Небольшая функция их связывает.
Вывод тот же — но теперь каждую часть можно менять, тестировать и переиспользовать отдельно.
Разделение на два класса
То же поведение, но разделённое: хранилище ничего не знает о письмах, отправитель ничего не знает о хранении. Функция processOrder просто соединяет их.
Вывод: PHP-скрипт
<?php
// У OrderStore одна задача: хранение заказов.
class OrderStore {
public function save(string $order): void {
echo "сохраняем заказ в хранилище: $order\n";
}
}
// У EmailSender одна задача: отправка писем.
class EmailSender {
public function sendConfirmation(string $customer, string $order): void {
echo "отправляем письмо на $customer:\n";
echo " Спасибо! Ваш заказ $order получен.\n";
}
}
function processOrder(string $order, string $customer): void {
$store = new OrderStore();
$sender = new EmailSender();
$store->save($order);
$sender->sendConfirmation($customer, $order);
}
processOrder("#1042 (2 books)", "ana@example.com");
Выигрыш: переиспользование без страха
Поскольку отправитель — отдельный класс, он отправляет и уведомление об отправке — без участия кода хранения. А хранилище архивирует заказ, не составляя ни одного письма. Каждый класс вырос внутри своей одной задачи.
Вывод: PHP-скрипт
<?php
class OrderStore {
public function save(string $order): void {
echo "сохраняем заказ в хранилище: $order\n";
}
public function archive(string $order): void {
echo "переносим заказ в архив: $order\n";
}
}
class EmailSender {
public function sendConfirmation(string $customer, string $order): void {
echo "письмо на $customer: заказ $order получен\n";
}
public function sendShippingNotice(string $customer, string $order): void {
echo "письмо на $customer: заказ $order отправлен\n";
}
}
$store = new OrderStore();
$sender = new EmailSender();
// Каждый класс растёт внутри своей одной задачи.
$sender->sendShippingNotice("ana@example.com", "#1042");
$store->archive("#0997");