В предыдущем примере где мы разбирали длинный метод, проблема в том, что нет действующего лица. Кот написан в процедурном стиле знакомым со школьной скамьи или университета, когда программа описывается серией последовательных инструкций: «сделай 1, сделай 2, сделай 3».
public function handle()
{
$this->load();
$this->validate();
$this->transform();
$this->generateReport();
// И ещё десяток шагов...
$this->sendMail();
}Что бы такого не было У него должно быть действующее лицо - объект. Но сразу же встает важный выбор: кто должен принимать решения? И в какой форме объекты должны взаимодействовать друг с другом?
Это один из важных принципов, который помогает сделать код объектов лаконичными, звучит так:
"Не спрашивай объект о его данных, чтобы принять решение — скажи объекту, что делать."
Когда ты спрашиваешь у объекта какие-то данные, а затем на основе этих данных принимаешь решение — ты, по сути, берёшь на себя его ответственность.
Вот пример:
// Плохо ❌
if ($invoice->isPaid()) {
$this->sendThankYouEmail($invoice->user);
}Выглядит безобидно. Но ответственность размыта. Кто решает, нужно ли отправить письмо? Внешний код. А должен — сам счёт.
Скажи объекту, что ты хочешь, а не спрашивай у него, что он знает.
// Хорошо ✅
$invoice->sendThankYouIfPaid();// Плохо ❌
if ($user->isAdmin() || $user->hasRole('manager')) {
$invoice->send();
}// Хорошо ✅
if ($user->canSend($invoice)) {
$invoice->send();
}Теперь вся логика прав находится в объекте пользователя. У тебя появляется единая точка принятия решений — легко тестировать и изменять.
// Плохо ❌
if (! $invoice->isEmpty()) {
$invoice->checkout();
}// Хорошо ✅
$invoice->checkout(); // пусть сам решает, можно ли оформляться