Skip to content

Latest commit

 

History

History
81 lines (63 loc) · 4.04 KB

File metadata and controls

81 lines (63 loc) · 4.04 KB

Глупые объекты рождают процедурные участки кода

Встречается практика, когда один объект используется исключительно как контейнер для данных – он не содержит бизнес-логики, а только хранит информацию. Рассмотрим пример:

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();

Это очень сильный архитектурный компромисс, который отступает от принципов объектно-ориентированного программирования, так как объекты должны быть ответственными за свои данные и поведение.

В результате мы получаем систему, где логика распределена между «глупыми» объектами которые хранят только данные, и отдельными сервисами и/или процедурными участками кода, работающими с этими данными. Это затрудняет понимание, тестирование и сопровождение кода, а также увеличивает связанность компонентов.