Встречается практика, когда один объект используется исключительно как контейнер для данных – он не содержит бизнес-логики, а только хранит информацию. Рассмотрим пример:
class User
{
private string $name;
private string $email;
public function getName(): string
{
return $this->name;
}
public function setName(string $name): void
{
$this->name = $name;
}
public function getEmail(): string
{
return $this->email;
}
public function setEmail(string $email): void
{
$this->email = $email;
}
}{note} Часто такие классы называют «Data Transfer Object» (DTO), однако стоит отметить, что в классическом понимании DTO рекомендуется делать иммутабельными — без сеттеров, чтобы обеспечить неизменность передаваемых данных.
Здесь объект User используется только для хранения данных.
Дальше эти данные обрабатываются в различных частях приложения. Например:
// В одном участке кода создаем объект и заполняем его данными
$user = new User();
$user->setName('John Doe');
$user->setEmail('john.doe@example.com');
// В другом участке кода валидируем данные
$validator = new Validator();
$validator->validate($user);
// В третьем участке кода отправляем письмо пользователю
$notification = new WelcomeNotification();
$notification->send($user->getEmail());В этом примере мы видим, что объект User не обладает собственной логикой – за обработку данных отвечают внешние
классы, такие как Validator и Mailer. По сути, вместо использования массива для хранения информации мы применяем
объект, но бизнес-логика вынесена за его пределы. Это приближает архитектуру к процедурному стилю, где программа состоит
из набора функций, выполняющих действия над данными.
Аналогичная ситуация наблюдается и в ORM, которые не используют подход Active Record, например, в Doctrine:
$entityManager = EntityManager::create($connection, $config);
// Создаем объект пользователя
$user = new User();
$user->setName("John Doe");
$user->setEmail("john.doe@example.com");
// Сохраняем в БД
$entityManager->persist($user);
$entityManager->flush();Это очень сильный архитектурный компромисс, который отступает от принципов объектно-ориентированного программирования, так как объекты должны быть ответственными за свои данные и поведение.
В результате мы получаем систему, где логика распределена между «глупыми» объектами которые хранят только данные, и отдельными сервисами и/или процедурными участками кода, работающими с этими данными. Это затрудняет понимание, тестирование и сопровождение кода, а также увеличивает связанность компонентов.